AES-CBC 128, 192 and 256 encryption decryption in Python 3 using PKCS#7 padding
Made it working by padding of 16 bytes for any encryption types. For that I used AES.block_size which is 16 by default for AES.
import base64
from Crypto.Cipher import AES
class AESCipher:
class InvalidBlockSizeError(Exception):
"""Raised for invalid block sizes"""
pass
def __init__(self, key):
self.key = key
self.iv = bytes(key[0:16], 'utf-8')
print(self.key)
print(key[0:16])
def __pad(self, text):
text_length = len(text)
amount_to_pad = AES.block_size - (text_length % AES.block_size)
if amount_to_pad == 0:
amount_to_pad = AES.block_size
pad = chr(amount_to_pad)
return text + pad * amount_to_pad
def __unpad(self, text):
pad = ord(text[-1])
return text[:-pad]
def encrypt( self, raw ):
raw = self.__pad(raw)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
return base64.b64encode(cipher.encrypt(raw))
def decrypt( self, enc ):
enc = base64.b64decode(enc)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv )
return self.__unpad(cipher.decrypt(enc).decode("utf-8"))
e = AESCipher('1234567812345678', 16)
#e = AESCipher('123456781234567812345678', 24)
#e = AESCipher('12345678123456781234567812345678', 32)
secret_data = "hi"
enc_str = e.encrypt(secret_data)
print('enc_str: ' + enc_str.decode())
dec_str = e.decrypt(enc_str)
print('dec str: ' + dec_str)
Nilesh Vora
Embedded Software developer at Dryad Networks Gmbh, Berlin
Updated on June 09, 2022Comments
-
Nilesh Vora almost 2 years
I have searched a lot on SO about complete encryption decryption example with my requirement. In fact, I've got many links and examples but None is working for me for AES-192-CBC mode and AES-256-CBC.
I have got following example which is supposed to be working with all types but it is working only with AES-128-CBC mode. I am new to Python. Can anyone help me where I am wrong?
I am using Python 3.4 on windows and I can not move to Python 2.7.
import base64 from Crypto.Cipher import AES class AESCipher: class InvalidBlockSizeError(Exception): """Raised for invalid block sizes""" pass def __init__(self, key, block_size=16): if block_size < 2 or block_size > 255: raise AESCipher.InvalidBlockSizeError('The block size must be between 2 and 255, inclusive') self.block_size = block_size self.key = key self.iv = bytes(key[0:16], 'utf-8') print(self.key) print(key[0:16]) def __pad(self, text): text_length = len(text) amount_to_pad = self.block_size - (text_length % self.block_size) if amount_to_pad == 0: amount_to_pad = self.block_size self.pad = chr(amount_to_pad) return text + self.pad * amount_to_pad def __unpad(self, text): #pad = ord(text[-1]) #return text[:-pad] text = text.rstrip(self.pad) return text def encrypt( self, raw ): raw = self.__pad(raw) cipher = AES.new(self.key, AES.MODE_CBC, self.iv) return base64.b64encode(cipher.encrypt(raw)) def decrypt( self, enc ): enc = base64.b64decode(enc) cipher = AES.new(self.key, AES.MODE_CBC, self.iv ) return self.__unpad(cipher.decrypt(enc).decode("utf-8")) e = AESCipher('1234567812345678', 16) #e = AESCipher('123456781234567812345678', 24) #e = AESCipher('12345678123456781234567812345678', 32) secret_data = "hi" enc_str = e.encrypt(secret_data) print('enc_str: ' + enc_str.decode()) dec_str = e.decrypt(enc_str) print('dec str: ' + dec_str)
Though this code encrypts the data with 192 and 256 bit encryption and successfully decrypt that too but my other .Net and Ruby application only able to decrypt the data which was encrypted using 128 encryption.
Note .Net and Ruby application are successfully tested with each other and with online encryption tool with all encryption types.
Note that my application requires AES-CBC mode and PKCS#7 padding and must be run on Python 3.4.
-
Artjom B. over 7 yearsI don't understand this answer. You've changed
self.block_size
to16
, butblock_size
was initialized with16
so nothing should have changed. Have you changed something else? -
Nilesh Vora over 7 yearsplease read the question fully. I have wrote that when I took 24 and 32 block size then it was not working. because previously black size initialized with what is passed in argument. See __pad function and commented code man.
-
Artjom B. over 7 yearsI see. I haven't seen your commented code. Still, the 256 in AES-256 always means the key size not the block size, because as you probably already learned, AES has a single fixed block size of 16 byte and you can get this with
AES.block_size
in pyCrypto. You don't need to hard code this. Since you don't need to pass in the block size during initialization, you should include that code in your answer (ping me when you're done, so I can remove my downvote). -
pors over 6 yearsIt is not secure to use (a slice of) the key as the IV: crypto.stackexchange.com/questions/16161/…
-
caffeinate_me almost 5 yearsThe
_pad
function is unnecessarily expanding the text asamount_to_pad
becausen % m
will never equal m. Also plus 1 to comment about IV coming from key being a fail.