Skip to content

Commit 0f95cfe

Browse files
committed
Separate AES cipher
Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
1 parent 55ef583 commit 0f95cfe

File tree

2 files changed

+80
-75
lines changed

2 files changed

+80
-75
lines changed

src/pyop/crypto.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import base64
2+
import hashlib
3+
4+
from Cryptodome import Random
5+
from Cryptodome.Cipher import AES
6+
7+
8+
class _AESCipher(object):
9+
"""
10+
This class will perform AES encryption/decryption with a keylength of 256.
11+
12+
@see: http://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256
13+
"""
14+
15+
def __init__(self, key):
16+
"""
17+
Constructor
18+
19+
:type key: str
20+
21+
:param key: The key used for encryption and decryption. The longer key the better.
22+
"""
23+
self.bs = 32
24+
self.key = hashlib.sha256(key.encode()).digest()
25+
26+
def encrypt(self, raw):
27+
"""
28+
Encryptes the parameter raw.
29+
30+
:type raw: bytes
31+
:rtype: str
32+
33+
:param: bytes to be encrypted.
34+
35+
:return: A base 64 encoded string.
36+
"""
37+
raw = self._pad(raw)
38+
iv = Random.new().read(AES.block_size)
39+
cipher = AES.new(self.key, AES.MODE_CBC, iv)
40+
return base64.urlsafe_b64encode(iv + cipher.encrypt(raw))
41+
42+
def decrypt(self, enc):
43+
"""
44+
Decryptes the parameter enc.
45+
46+
:type enc: bytes
47+
:rtype: bytes
48+
49+
:param: The value to be decrypted.
50+
:return: The decrypted value.
51+
"""
52+
enc = base64.urlsafe_b64decode(enc)
53+
iv = enc[:AES.block_size]
54+
cipher = AES.new(self.key, AES.MODE_CBC, iv)
55+
return self._unpad(cipher.decrypt(enc[AES.block_size:]))
56+
57+
def _pad(self, b):
58+
"""
59+
Will padd the param to be of the correct length for the encryption alg.
60+
61+
:type b: bytes
62+
:rtype: bytes
63+
"""
64+
return b + (self.bs - len(b) % self.bs) * chr(self.bs - len(b) % self.bs).encode("UTF-8")
65+
66+
@staticmethod
67+
def _unpad(b):
68+
"""
69+
Removes the padding performed by the method _pad.
70+
71+
:type b: bytes
72+
:rtype: bytes
73+
"""
74+
return b[:-ord(b[len(b) - 1:])]

src/pyop/storage.py

+6-75
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# -*- coding: utf-8 -*-
22

33
from abc import ABC, abstractmethod
4-
from Cryptodome import Random
5-
from Cryptodome.Cipher import AES
64
import copy
75
import json
8-
import base64
9-
import hashlib
106
import logging
117
from datetime import datetime
12-
from urllib.parse import urlparse, parse_qs
8+
from urllib.parse import urlparse
9+
from urllib.parse import parse_qs
10+
11+
from .crypto import _AESCipher
12+
1313

1414
logger = logging.getLogger(__name__)
1515

@@ -241,7 +241,7 @@ def __init__(self, collection, encryption_key, alg=None):
241241
if not alg or alg.lower() == "aes256":
242242
self.cipher = _AESCipher(encryption_key)
243243
else:
244-
return ValueError(f"Invalid encryption algorithm: {alg}")
244+
raise ValueError(f"Invalid encryption algorithm: {alg}")
245245

246246
def __setitem__(self, key, value):
247247
pass
@@ -282,75 +282,6 @@ def _unpack(self, value):
282282
return unpacked_val
283283

284284

285-
class _AESCipher(object):
286-
"""
287-
This class will perform AES encryption/decryption with a keylength of 256.
288-
289-
@see: http://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256
290-
"""
291-
292-
def __init__(self, key):
293-
"""
294-
Constructor
295-
296-
:type key: str
297-
298-
:param key: The key used for encryption and decryption. The longer key the better.
299-
"""
300-
self.bs = 32
301-
self.key = hashlib.sha256(key.encode()).digest()
302-
303-
def encrypt(self, raw):
304-
"""
305-
Encryptes the parameter raw.
306-
307-
:type raw: bytes
308-
:rtype: str
309-
310-
:param: bytes to be encrypted.
311-
312-
:return: A base 64 encoded string.
313-
"""
314-
raw = self._pad(raw)
315-
iv = Random.new().read(AES.block_size)
316-
cipher = AES.new(self.key, AES.MODE_CBC, iv)
317-
return base64.urlsafe_b64encode(iv + cipher.encrypt(raw))
318-
319-
def decrypt(self, enc):
320-
"""
321-
Decryptes the parameter enc.
322-
323-
:type enc: bytes
324-
:rtype: bytes
325-
326-
:param: The value to be decrypted.
327-
:return: The decrypted value.
328-
"""
329-
enc = base64.urlsafe_b64decode(enc)
330-
iv = enc[:AES.block_size]
331-
cipher = AES.new(self.key, AES.MODE_CBC, iv)
332-
return self._unpad(cipher.decrypt(enc[AES.block_size:]))
333-
334-
def _pad(self, b):
335-
"""
336-
Will padd the param to be of the correct length for the encryption alg.
337-
338-
:type b: bytes
339-
:rtype: bytes
340-
"""
341-
return b + (self.bs - len(b) % self.bs) * chr(self.bs - len(b) % self.bs).encode("UTF-8")
342-
343-
@staticmethod
344-
def _unpad(b):
345-
"""
346-
Removes the padding performed by the method _pad.
347-
348-
:type b: bytes
349-
:rtype: bytes
350-
"""
351-
return b[:-ord(b[len(b) - 1:])]
352-
353-
354285
class MongoDB(object):
355286
"""Simple wrapper to get pymongo real objects from the settings uri"""
356287

0 commit comments

Comments
 (0)