11import base64
22import binascii
3- from typing import Union
3+ from typing import Union , Callable , Optional
44
55from Crypto .Cipher import AES
66from Crypto .Random import get_random_bytes
77from Crypto .Util .Padding import pad , unpad
88
9- _AES_CIPHER_METHODS = { # FULL_CIPHER_NAME: (dict_params,)
10- "AES/ECB/PKCS5Padding" : {'mode' : AES .MODE_ECB },
11- # "AES/ECB/NoPadding": {'mode': AES.MODE_ECB},
12- # "AES/CBC/PKCS5Padding ": {'mode': AES.MODE_CBC, 'iv': b'0000000000000000'},
13- # "AES/CBC/NoPadding": {'mode': AES.MODE_CBC, 'iv': b'0000000000000000'},
9+ _AES_CIPHER_METHODS = { # FULL_CIPHER_NAME: (dict_params, pad_style )
10+ "AES/ECB/PKCS5Padding" : ( {'mode' : AES .MODE_ECB }, 'pkcs7' ) ,
11+ "AES/ECB/NoPadding" : ( {'mode' : AES .MODE_ECB }, 'pkcs7' ) ,
12+ "AES/CBC/PKCS7Padding " : ( {'mode' : AES .MODE_CBC , 'iv' : b'0000000000000000' }, 'pkcs7' ) ,
13+ "AES/CBC/NoPadding" : ( {'mode' : AES .MODE_CBC , 'iv' : b'0000000000000000' }, 'x923' ) ,
1414}
1515
1616
@@ -23,6 +23,8 @@ def _generate_key(key_size: int, method='const') -> bytes:
2323
2424
2525class AesEncryptor :
26+ supported_cipher_methods = _AES_CIPHER_METHODS
27+
2628 def __init__ (self , key : Union [str , bytes ] = None , key_size : int = 16 , cipher_name : str = 'AES/ECB/PKCS5Padding' ):
2729 _key = key
2830 if key is None :
@@ -37,10 +39,13 @@ def __init__(self, key: Union[str, bytes] = None, key_size: int = 16, cipher_nam
3739 # https://pycryptodome.readthedocs.io/en/latest/src/util/util.html
3840 self .cipher_name = cipher_name
3941
40- def encrypt (self , text : str , output_format = 'hex' ) -> Union [str , bytes ]:
41- padded = pad (text .encode (), block_size = self .block_size )
42+ def encrypt (self , text : str , output_format = 'hex' , func_pad : Optional [Callable ] = None ) -> Union [str , bytes ]:
43+ dict_params , pad_style = _AES_CIPHER_METHODS .get (self .cipher_name )
44+ if not callable (func_pad ):
45+ func_pad = lambda x : pad (data , block_size = self .block_size , style = pad_style )
4246
43- dict_params = _AES_CIPHER_METHODS .get (self .cipher_name )
47+ data = text .encode ()
48+ padded = func_pad (data )
4449 cipher = AES .new (key = self .key_aes , ** dict_params )
4550 bytes_crypt = cipher .encrypt (padded )
4651
@@ -54,7 +59,7 @@ def encrypt(self, text: str, output_format='hex') -> Union[str, bytes]:
5459 raise ValueError ('Unknown output_type [%s]' % output_format )
5560 return crypt
5661
57- def decrypt (self , text : Union [str , bytes ], input_format : str = 'hex' ) -> Union [str , bytes ]:
62+ def decrypt (self , text : Union [str , bytes ], input_format : str = 'hex' , func_unpad : Optional [ Callable ] = None ) -> Union [str , bytes ]:
5863 text += (len (text ) % 4 ) * '='
5964 if input_format == 'hex' :
6065 crypt = binascii .a2b_hex (text )
@@ -64,10 +69,12 @@ def decrypt(self, text: Union[str, bytes], input_format: str = 'hex') -> Union[s
6469 crypt = text
6570 else :
6671 raise ValueError ('Unknown output_type [%s]' % input_format )
67- dict_params = _AES_CIPHER_METHODS .get (self .cipher_name )
72+ dict_params , pad_style = _AES_CIPHER_METHODS .get (self .cipher_name )
6873 cipher = AES .new (key = self .key_aes , ** dict_params )
6974 data = cipher .decrypt (crypt )
70- data = unpad (data , block_size = self .block_size )
75+ if not callable (func_unpad ):
76+ func_unpad = lambda x : unpad (x , block_size = self .block_size , style = pad_style )
77+ data = func_unpad (data )
7178 return data .decode ('UTF-8' )
7279
7380
0 commit comments