Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / db / aes_encrypt.py @ 19b2c29d

History | View | Annotate | Download (3.5 kB)

1 91884d63 Giorgos Korfiatis
# Copyright 2012, 2013 GRNET S.A. All rights reserved.
2 91884d63 Giorgos Korfiatis
#
3 91884d63 Giorgos Korfiatis
# Redistribution and use in source and binary forms, with or without
4 91884d63 Giorgos Korfiatis
# modification, are permitted provided that the following conditions
5 91884d63 Giorgos Korfiatis
# are met:
6 91884d63 Giorgos Korfiatis
#
7 91884d63 Giorgos Korfiatis
#   1. Redistributions of source code must retain the above copyright
8 91884d63 Giorgos Korfiatis
#      notice, this list of conditions and the following disclaimer.
9 91884d63 Giorgos Korfiatis
#
10 91884d63 Giorgos Korfiatis
#  2. Redistributions in binary form must reproduce the above copyright
11 91884d63 Giorgos Korfiatis
#     notice, this list of conditions and the following disclaimer in the
12 91884d63 Giorgos Korfiatis
#     documentation and/or other materials provided with the distribution.
13 91884d63 Giorgos Korfiatis
#
14 91884d63 Giorgos Korfiatis
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15 91884d63 Giorgos Korfiatis
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 91884d63 Giorgos Korfiatis
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 91884d63 Giorgos Korfiatis
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18 91884d63 Giorgos Korfiatis
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 91884d63 Giorgos Korfiatis
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 91884d63 Giorgos Korfiatis
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 91884d63 Giorgos Korfiatis
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 91884d63 Giorgos Korfiatis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 91884d63 Giorgos Korfiatis
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 91884d63 Giorgos Korfiatis
# SUCH DAMAGE.
25 91884d63 Giorgos Korfiatis
#
26 91884d63 Giorgos Korfiatis
# The views and conclusions contained in the software and documentation are
27 91884d63 Giorgos Korfiatis
# those of the authors and should not be interpreted as representing official
28 91884d63 Giorgos Korfiatis
# policies, either expressed or implied, of GRNET S.A.
29 91884d63 Giorgos Korfiatis
30 30e0ed74 Christos Stavrakakis
from binascii import b2a_base64, a2b_base64
31 30e0ed74 Christos Stavrakakis
from Crypto.Cipher import AES
32 3dbd9457 Christos Stavrakakis
from Crypto import Random
33 30e0ed74 Christos Stavrakakis
from random import choice
34 30e0ed74 Christos Stavrakakis
from string import letters, digits
35 ca8b1c21 Christos Stavrakakis
from synnefo.settings import SECRET_ENCRYPTION_KEY
36 30e0ed74 Christos Stavrakakis
37 30e0ed74 Christos Stavrakakis
38 30e0ed74 Christos Stavrakakis
DB_ENCRYPTED_FIELD_PREFIX = 'encrypted'
39 30e0ed74 Christos Stavrakakis
SALT_LEN = 8
40 30e0ed74 Christos Stavrakakis
41 30e0ed74 Christos Stavrakakis
42 30e0ed74 Christos Stavrakakis
def _pad_secret(secret, blocksize=32, padding='}'):
43 0224049a Christos Stavrakakis
    len_secret = len(secret)
44 0224049a Christos Stavrakakis
    if len_secret > 32:
45 0224049a Christos Stavrakakis
        raise ValueError('Encryption key must be smaller than 32 bytes')
46 0224049a Christos Stavrakakis
    if not len_secret in (16, 24, 32):
47 30e0ed74 Christos Stavrakakis
        return secret + (blocksize - len(secret)) * padding
48 30e0ed74 Christos Stavrakakis
    return secret
49 30e0ed74 Christos Stavrakakis
50 30e0ed74 Christos Stavrakakis
51 3dbd9457 Christos Stavrakakis
def encrypt(s, iv):
52 3dbd9457 Christos Stavrakakis
    obj = AES.new(_pad_secret(SECRET_ENCRYPTION_KEY), AES.MODE_CFB, iv)
53 30e0ed74 Christos Stavrakakis
    return obj.encrypt(s)
54 30e0ed74 Christos Stavrakakis
55 30e0ed74 Christos Stavrakakis
56 3dbd9457 Christos Stavrakakis
def decrypt(s, iv):
57 3dbd9457 Christos Stavrakakis
    obj = AES.new(_pad_secret(SECRET_ENCRYPTION_KEY), AES.MODE_CFB, iv)
58 30e0ed74 Christos Stavrakakis
    return obj.decrypt(s)
59 30e0ed74 Christos Stavrakakis
60 30e0ed74 Christos Stavrakakis
61 30e0ed74 Christos Stavrakakis
def encrypt_db_charfield(plaintext):
62 68b952f9 Christos Stavrakakis
    if not plaintext:
63 30e0ed74 Christos Stavrakakis
        return plaintext
64 30e0ed74 Christos Stavrakakis
    salt = "".join([choice(letters + digits) for i in xrange(SALT_LEN)])
65 30e0ed74 Christos Stavrakakis
66 3dbd9457 Christos Stavrakakis
    iv = Random.get_random_bytes(16)
67 30e0ed74 Christos Stavrakakis
    plaintext = "%s%s" % (salt, plaintext)
68 30e0ed74 Christos Stavrakakis
    # Encrypt and convert to binary
69 3dbd9457 Christos Stavrakakis
    ciphertext = b2a_base64(encrypt(plaintext, iv))
70 3dbd9457 Christos Stavrakakis
    iv = b2a_base64(iv)
71 30e0ed74 Christos Stavrakakis
    # Append prefix,salt and return encoded value
72 3dbd9457 Christos Stavrakakis
    final = '%s:%s:%s$%s' % (DB_ENCRYPTED_FIELD_PREFIX, iv, salt, ciphertext)
73 30e0ed74 Christos Stavrakakis
    return final.encode('utf8')
74 30e0ed74 Christos Stavrakakis
75 30e0ed74 Christos Stavrakakis
76 30e0ed74 Christos Stavrakakis
def decrypt_db_charfield(ciphertext):
77 68b952f9 Christos Stavrakakis
    if not ciphertext:
78 30e0ed74 Christos Stavrakakis
        return ciphertext
79 30e0ed74 Christos Stavrakakis
    has_prefix = ciphertext.startswith(DB_ENCRYPTED_FIELD_PREFIX + ':')
80 30e0ed74 Christos Stavrakakis
    if not has_prefix:  # Non-encoded value
81 30e0ed74 Christos Stavrakakis
        return ciphertext
82 30e0ed74 Christos Stavrakakis
    else:
83 3dbd9457 Christos Stavrakakis
        _, iv, ciphertext = ciphertext.split(':')
84 30e0ed74 Christos Stavrakakis
85 30e0ed74 Christos Stavrakakis
    pure_salt, encrypted = ciphertext.split('$')
86 3dbd9457 Christos Stavrakakis
    iv = a2b_base64(iv)
87 30e0ed74 Christos Stavrakakis
88 3dbd9457 Christos Stavrakakis
    plaintext = decrypt(a2b_base64(encrypted), iv)
89 30e0ed74 Christos Stavrakakis
90 30e0ed74 Christos Stavrakakis
    salt = plaintext[:SALT_LEN]
91 30e0ed74 Christos Stavrakakis
    plaintext = plaintext[SALT_LEN:]
92 30e0ed74 Christos Stavrakakis
93 30e0ed74 Christos Stavrakakis
    if salt != pure_salt:
94 8d5795b4 Christos Stavrakakis
        # Cannot decrtypt password
95 8d5795b4 Christos Stavrakakis
        raise CorruptedPassword("Cannot decrypt password. Check the key")
96 30e0ed74 Christos Stavrakakis
    else:
97 30e0ed74 Christos Stavrakakis
        return plaintext
98 30e0ed74 Christos Stavrakakis
99 30e0ed74 Christos Stavrakakis
100 30e0ed74 Christos Stavrakakis
class CorruptedPassword(Exception):
101 30e0ed74 Christos Stavrakakis
    pass