5

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?

marczellm
  • 1,224
  • 2
  • 18
  • 42

3 Answers3

4

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.

Alex Gaynor
  • 14,353
  • 9
  • 63
  • 113
  • Maybe you mean CFB-8? The default behavior for CFB PyCrypto is described [here](https://www.dlitz.net/software/pycrypto/api/current/Crypto.Cipher.AES-module.html#new): `segment_size (integer) - (Only MODE_CFB).The number of bits the plaintext and ciphertext are segmented in. It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.` – SquareRootOfTwentyThree May 14 '14 at 12:58
  • @SquareRootOfTwentyThree Yes indeed, fixed. – Alex Gaynor May 14 '14 at 13:00
2

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.

marczellm
  • 1,224
  • 2
  • 18
  • 42
0

Kindly use cryptography mode as "CFB8". The pycrypto and cryptography output will match. for ex.cipher2 = Cipher(algorithms.AES(key), modes.CFB8(iv), default_backend())

  • In my project we were using previously pycrypto aes implementation. – user3065025 Oct 23 '18 at 09:06
  • In my project we were using pycrypto aes implementation with default segment size of 8 instead of 128 .when we want to replace it with cryptography implementation we used modes.CFB8 mode to match cryptography output with pycrypto output. If you use mode.CFB then encryption output do not match – user3065025 Oct 23 '18 at 09:14