Mercurial > libervia-backend
comparison src/memory/crypto.py @ 1098:77cd312d32c4
memory: fixes encoding issues during encryption
author | souliane <souliane@mailoo.org> |
---|---|
date | Sun, 06 Jul 2014 21:13:47 +0200 |
parents | 127c96020022 |
children | 069ad98b360d |
comparison
equal
deleted
inserted
replaced
1097:dace0ede919c | 1098:77cd312d32c4 |
---|---|
40 def encrypt(cls, key, text, leave_empty=True): | 40 def encrypt(cls, key, text, leave_empty=True): |
41 """Encrypt a message. | 41 """Encrypt a message. |
42 | 42 |
43 Based on http://stackoverflow.com/a/12525165 | 43 Based on http://stackoverflow.com/a/12525165 |
44 | 44 |
45 @param key (str): the encryption key | 45 @param key (unicode): the encryption key |
46 @param text (str): the text to encrypt | 46 @param text (unicode): the text to encrypt |
47 @param leave_empty (bool): if True, empty text will be returned "as is" | 47 @param leave_empty (bool): if True, empty text will be returned "as is" |
48 @return: Deferred: base-64 encoded str | 48 @return: Deferred: base-64 encoded str |
49 """ | 49 """ |
50 if leave_empty and text == '': | 50 if leave_empty and text == '': |
51 return succeed(text) | 51 return succeed(text) |
52 iv = BlockCipher.getRandomKey() | 52 iv = BlockCipher.getRandomKey() |
53 key = key.encode('utf-8') | |
53 key = key[:BlockCipher.MAX_KEY_SIZE] if len(key) >= BlockCipher.MAX_KEY_SIZE else BlockCipher.pad(key) | 54 key = key[:BlockCipher.MAX_KEY_SIZE] if len(key) >= BlockCipher.MAX_KEY_SIZE else BlockCipher.pad(key) |
54 cipher = AES.new(key, AES.MODE_CFB, iv) | 55 cipher = AES.new(key, AES.MODE_CFB, iv) |
55 d = deferToThread(cipher.encrypt, BlockCipher.pad(text)) | 56 d = deferToThread(cipher.encrypt, BlockCipher.pad(text.encode('utf-8'))) |
56 d.addCallback(lambda ciphertext: b64encode(iv + ciphertext)) | 57 d.addCallback(lambda ciphertext: b64encode(iv + ciphertext)) |
57 return d | 58 return d |
58 | 59 |
59 @classmethod | 60 @classmethod |
60 def decrypt(cls, key, ciphertext, leave_empty=True): | 61 def decrypt(cls, key, ciphertext, leave_empty=True): |
61 """Decrypt a message. | 62 """Decrypt a message. |
62 | 63 |
63 Based on http://stackoverflow.com/a/12525165 | 64 Based on http://stackoverflow.com/a/12525165 |
64 | 65 |
65 @param key (str): the decryption key | 66 @param key (unicode): the decryption key |
66 @param ciphertext (base-64 encoded str): the text to decrypt | 67 @param ciphertext (base-64 encoded str): the text to decrypt |
67 @param leave_empty (bool): if True, empty ciphertext will be returned "as is" | 68 @param leave_empty (bool): if True, empty ciphertext will be returned "as is" |
68 @return: Deferred: str or None if the password could not be decrypted | 69 @return: Deferred: str or None if the password could not be decrypted |
69 """ | 70 """ |
70 if leave_empty and ciphertext == '': | 71 if leave_empty and ciphertext == '': |
71 return succeed('') | 72 return succeed('') |
72 ciphertext = b64decode(ciphertext) | 73 ciphertext = b64decode(ciphertext) |
73 iv, ciphertext = ciphertext[:BlockCipher.IV_SIZE], ciphertext[BlockCipher.IV_SIZE:] | 74 iv, ciphertext = ciphertext[:BlockCipher.IV_SIZE], ciphertext[BlockCipher.IV_SIZE:] |
75 key = key.encode('utf-8') | |
74 key = key[:BlockCipher.MAX_KEY_SIZE] if len(key) >= BlockCipher.MAX_KEY_SIZE else BlockCipher.pad(key) | 76 key = key[:BlockCipher.MAX_KEY_SIZE] if len(key) >= BlockCipher.MAX_KEY_SIZE else BlockCipher.pad(key) |
75 cipher = AES.new(key, AES.MODE_CFB, iv) | 77 cipher = AES.new(key, AES.MODE_CFB, iv) |
76 d = deferToThread(cipher.decrypt, ciphertext) | 78 d = deferToThread(cipher.decrypt, ciphertext) |
77 d.addCallback(lambda text: BlockCipher.unpad(text)) | 79 d.addCallback(lambda text: BlockCipher.unpad(text)) |
78 # XXX: cipher.decrypt gives no way to make the distinction between | 80 # XXX: cipher.decrypt gives no way to make the distinction between |
79 # a decrypted empty value and a decryption failure... both return | 81 # a decrypted empty value and a decryption failure... both return |
80 # the empty value. Fortunately, we detect empty passwords beforehand | 82 # the empty value. Fortunately, we detect empty passwords beforehand |
81 # thanks to the "leave_empty" parameter which is used by default. | 83 # thanks to the "leave_empty" parameter which is used by default. |
82 d.addCallback(lambda text: text if text else None) | 84 d.addCallback(lambda text: text.decode('utf-8') if text else None) |
83 return d | 85 return d |
84 | 86 |
85 @classmethod | 87 @classmethod |
86 def getRandomKey(cls, size=None, base64=False): | 88 def getRandomKey(cls, size=None, base64=False): |
87 """Return a random key suitable for block cipher encryption. | 89 """Return a random key suitable for block cipher encryption. |