Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python AES implementations difference

I'm comparing AES implementations in Python from the pycrypto and the cryptography.io library.

from cryptography.hazmat.primitives.ciphers import Cipher, modes, algorithms
from cryptography.hazmat.backends import default_backend  # http://cryptography.io
from Crypto.Cipher import AES  # http://pycrypto.org

key = b'Sixteen byte key'
iv = b'Sixteen byte ivv'
cipher1 = AES.new(key, AES.MODE_CFB, iv)
cipher2 = Cipher(algorithms.AES(key), modes.CFB(iv), default_backend())

plaintext = b"Plaintext"

print(cipher1.encrypt(plaintext))
print(cipher1.decrypt(plaintext))
print(cipher2.encryptor().update(plaintext))
print(cipher2.decryptor().update(plaintext))

The MWE prints:

b'\xe4\xb4\xeb\xe3Si\x9ap\xee'
b'7\xda\x98\xee\x05\xe4\xa0\xc7,'
b'\xe4"\xd4mo\xa3;\xa9\xe0'
b'\xe4"\xd4mo\xa3;\xa9\xe0'

Why are the outputs different?

like image 726
marczellm Avatar asked May 14 '14 11:05

marczellm


2 Answers

The answer appears to be that PyCrypto implements CFB-8 by default, which is a variant on normal CFB. https://github.com/digitalbazaar/forge/issues/100 describes the issue in more detail.

like image 124
Alex Gaynor Avatar answered Nov 15 '22 00:11

Alex Gaynor


Based on Alex Gaynor's answer, here is a more detailed description:

According to the standard, the input size must be a multiple of the segment size. Most implementations use 16 byte (128 bit) segment size by default, and ignore this requirement. PyCrypto uses 8 byte segments by default, but you can change it like so:

cipher1 = AES.new(key, AES.MODE_CFB, iv, segment_size=128)

This produces identical encrypted data with the other library.

like image 40
marczellm Avatar answered Nov 14 '22 22:11

marczellm