I have been trying to implement AES CBC decryption in Python. Since the ciphered text is not a multiple of 16bytes, padding was necessary. Without padding, this error surfaced
"TypeError: Odd-length string"
But I could not find a proper reference for implementing PKCS5 in PyCrypto Python. Are there any commands to implement this? Thanks
After looking into Marcus's suggestion I did this.
My goal actually is to decrypt a hex message(128bytes) using this code. However, the output is " ?:" which is very small and the unpad command is deleting those bytes. This is the code.
from Crypto.Cipher import AES
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]
class AESCipher:
def __init__( self, key ):
self.key = key
def encrypt( self, raw ):
raw = pad(raw)
iv = raw[:16]
raw=raw[16:]
#iv = Random.new().read( AES.block_size )
cipher = AES.new( self.key, AES.MODE_CBC, iv )
return ( iv + cipher.encrypt( raw ) ).encode("hex")
def decrypt( self, enc ):
iv = enc[:16]
enc= enc[16:]
cipher = AES.new(self.key, AES.MODE_CBC, iv )
return unpad(cipher.decrypt( enc))
mode = AES.MODE_CBC
key = "140b41b22a29beb4061bda66b6747e14"
ciphertext = "4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81";
key=key[:32]
decryptor = AESCipher(key)
decryptor.__init__(key)
plaintext = decryptor.decrypt(ciphertext)
print plaintext
AES requires a secret passphrase known as a “key” to encrypt/decrypt data. Anybody with the key can decrypt your data, so you need it to be strong and hidden from everyone―only the software program should be able to access it. The key can be either 128, 192, 256, or 512 bit long.
PKCS5 PaddingIf the block length is B then add N padding bytes of value N to make the input length up to the next exact multiple of B . If the input length is already an exact multiple of B then add B bytes of value B . Thus padding of length N between one and B bytes is always added in an unambiguous manner.
AES uses 128-bits (16 bytes), and DES uses 64-bit blocks (8 bytes). The main padding methods are: CMS (Cryptographic Message Syntax). This pads with the same value as the number of padding bytes.
Padding your plaintext is required if you perform AES encryption in ECB/CBC block cipher mode, unless your plaintext is a multiple of the blocksize. You could of course make sure that your plaintext is always precisely N blocks, but in effect you would be creating your own padding mode.
You need to decode your hex encoded value before decryption. If you want to work with hex encoded keys, decode it as well..
Here, this should work.
from Crypto.Cipher import AES
from Crypto import Random
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]
class AESCipher:
def __init__( self, key ):
"""
Requires hex encoded param as a key
"""
self.key = key.decode("hex")
def encrypt( self, raw ):
"""
Returns hex encoded encrypted value!
"""
raw = pad(raw)
iv = Random.new().read(AES.block_size);
cipher = AES.new( self.key, AES.MODE_CBC, iv )
return ( iv + cipher.encrypt( raw ) ).encode("hex")
def decrypt( self, enc ):
"""
Requires hex encoded param to decrypt
"""
enc = enc.decode("hex")
iv = enc[:16]
enc= enc[16:]
cipher = AES.new(self.key, AES.MODE_CBC, iv )
return unpad(cipher.decrypt( enc))
if __name__== "__main__":
key = "140b41b22a29beb4061bda66b6747e14"
ciphertext = "4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81"
key=key[:32]
decryptor = AESCipher(key)
plaintext = decryptor.decrypt(ciphertext)
print "%s" % plaintext
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With