Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / db / aes_encrypt.py @ 9835a70d

History | View | Annotate | Download (2 kB)

1 30e0ed74 Christos Stavrakakis
from binascii import b2a_base64, a2b_base64
2 30e0ed74 Christos Stavrakakis
from Crypto.Cipher import AES
3 3dbd9457 Christos Stavrakakis
from Crypto import Random
4 30e0ed74 Christos Stavrakakis
from random import choice
5 30e0ed74 Christos Stavrakakis
from string import letters, digits
6 ca8b1c21 Christos Stavrakakis
from synnefo.settings import SECRET_ENCRYPTION_KEY
7 30e0ed74 Christos Stavrakakis
8 30e0ed74 Christos Stavrakakis
9 30e0ed74 Christos Stavrakakis
DB_ENCRYPTED_FIELD_PREFIX = 'encrypted'
10 30e0ed74 Christos Stavrakakis
SALT_LEN = 8
11 30e0ed74 Christos Stavrakakis
12 30e0ed74 Christos Stavrakakis
13 30e0ed74 Christos Stavrakakis
def _pad_secret(secret, blocksize=32, padding='}'):
14 0224049a Christos Stavrakakis
    len_secret = len(secret)
15 0224049a Christos Stavrakakis
    if len_secret > 32:
16 0224049a Christos Stavrakakis
        raise ValueError('Encryption key must be smaller than 32 bytes')
17 0224049a Christos Stavrakakis
    if not len_secret in (16, 24, 32):
18 30e0ed74 Christos Stavrakakis
        return secret + (blocksize - len(secret)) * padding
19 30e0ed74 Christos Stavrakakis
    return secret
20 30e0ed74 Christos Stavrakakis
21 30e0ed74 Christos Stavrakakis
22 3dbd9457 Christos Stavrakakis
def encrypt(s, iv):
23 3dbd9457 Christos Stavrakakis
    obj = AES.new(_pad_secret(SECRET_ENCRYPTION_KEY), AES.MODE_CFB, iv)
24 30e0ed74 Christos Stavrakakis
    return obj.encrypt(s)
25 30e0ed74 Christos Stavrakakis
26 30e0ed74 Christos Stavrakakis
27 3dbd9457 Christos Stavrakakis
def decrypt(s, iv):
28 3dbd9457 Christos Stavrakakis
    obj = AES.new(_pad_secret(SECRET_ENCRYPTION_KEY), AES.MODE_CFB, iv)
29 30e0ed74 Christos Stavrakakis
    return obj.decrypt(s)
30 30e0ed74 Christos Stavrakakis
31 30e0ed74 Christos Stavrakakis
32 30e0ed74 Christos Stavrakakis
def encrypt_db_charfield(plaintext):
33 68b952f9 Christos Stavrakakis
    if not plaintext:
34 30e0ed74 Christos Stavrakakis
        return plaintext
35 30e0ed74 Christos Stavrakakis
    salt = "".join([choice(letters + digits) for i in xrange(SALT_LEN)])
36 30e0ed74 Christos Stavrakakis
37 3dbd9457 Christos Stavrakakis
    iv = Random.get_random_bytes(16)
38 30e0ed74 Christos Stavrakakis
    plaintext = "%s%s" % (salt, plaintext)
39 30e0ed74 Christos Stavrakakis
    # Encrypt and convert to binary
40 3dbd9457 Christos Stavrakakis
    ciphertext = b2a_base64(encrypt(plaintext, iv))
41 3dbd9457 Christos Stavrakakis
    iv = b2a_base64(iv)
42 30e0ed74 Christos Stavrakakis
    # Append prefix,salt and return encoded value
43 3dbd9457 Christos Stavrakakis
    final = '%s:%s:%s$%s' % (DB_ENCRYPTED_FIELD_PREFIX, iv, salt, ciphertext)
44 30e0ed74 Christos Stavrakakis
    return final.encode('utf8')
45 30e0ed74 Christos Stavrakakis
46 30e0ed74 Christos Stavrakakis
47 30e0ed74 Christos Stavrakakis
def decrypt_db_charfield(ciphertext):
48 68b952f9 Christos Stavrakakis
    if not ciphertext:
49 30e0ed74 Christos Stavrakakis
        return ciphertext
50 30e0ed74 Christos Stavrakakis
    has_prefix = ciphertext.startswith(DB_ENCRYPTED_FIELD_PREFIX + ':')
51 30e0ed74 Christos Stavrakakis
    if not has_prefix:  # Non-encoded value
52 30e0ed74 Christos Stavrakakis
        return ciphertext
53 30e0ed74 Christos Stavrakakis
    else:
54 3dbd9457 Christos Stavrakakis
        _, iv, ciphertext = ciphertext.split(':')
55 30e0ed74 Christos Stavrakakis
56 30e0ed74 Christos Stavrakakis
    pure_salt, encrypted = ciphertext.split('$')
57 3dbd9457 Christos Stavrakakis
    iv = a2b_base64(iv)
58 30e0ed74 Christos Stavrakakis
59 3dbd9457 Christos Stavrakakis
    plaintext = decrypt(a2b_base64(encrypted), iv)
60 30e0ed74 Christos Stavrakakis
61 30e0ed74 Christos Stavrakakis
    salt = plaintext[:SALT_LEN]
62 30e0ed74 Christos Stavrakakis
    plaintext = plaintext[SALT_LEN:]
63 30e0ed74 Christos Stavrakakis
64 30e0ed74 Christos Stavrakakis
    if salt != pure_salt:
65 8d5795b4 Christos Stavrakakis
        # Cannot decrtypt password
66 8d5795b4 Christos Stavrakakis
        raise CorruptedPassword("Cannot decrypt password. Check the key")
67 30e0ed74 Christos Stavrakakis
    else:
68 30e0ed74 Christos Stavrakakis
        return plaintext
69 30e0ed74 Christos Stavrakakis
70 30e0ed74 Christos Stavrakakis
71 30e0ed74 Christos Stavrakakis
class CorruptedPassword(Exception):
72 30e0ed74 Christos Stavrakakis
    pass