Reputation: 144
This small python program should encrypt plain to cipher using AES in the CFB mode using a 128bit key
from Crypto.Cipher import AES
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
key = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
iv = b'\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
plain = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
aes = AES.new(key, AES.MODE_CFB, iv)
cipher = aes.encrypt(plain)
print(' '.join('{:2x}'.format(b) for b in cipher))
I took this key, IV and plain cipher combination from one of the NIST test vectors (CFB128VarTxt128.rsp). For this particular combination I expect the cipher:
3a d7 8e 72 6c 1e c0 2b 7e bf e9 2b 23 d9 ec 34
but pycrypto calculates
3a 81 e1 d4 b8 24 75 61 46 31 63 4b 5c 79 d6 bc
The first byte is correct, whereas the others do not match. I also tried different test vectors, but the result stays the same. All bytes, except for the first byte, do not match.
I am quite sure, that the NIST test vectors are valid since I used them before when using AES with Crypto++ and I am also pretty sure, that the implementation of pycrypto is correct since its output agrees with online tools such as this page. Obviously, it is me, who is using the tools in an incorrect way...
Does anyone have a clue, how to reproduce the NIST test vectors with pycrypto?
This is the NIST example
# CAVS 11.1
# Config info for aes_values
# AESVS VarTxt test data for CFB128
# State : Encrypt and Decrypt
# Key Length : 128
# Generated on Fri Apr 22 15:11:53 2011
...
COUNT = 0
KEY = 00000000000000000000000000000000
IV = 80000000000000000000000000000000
PLAINTEXT = 00000000000000000000000000000000
CIPHERTEXT = 3ad78e726c1ec02b7ebfe92b23d9ec34
Upvotes: 3
Views: 588
Reputation: 41974
You are missing a keyword argument, segment_size
, in your AES.new(...)
call. This is the feedback size, and it defaults to 8. If your line of code is changed to
aes = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
you get the correct result.
As stated in the docs:
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.
Your results correspond to what would likely be labeled "CFB8" in NIST docs.
Upvotes: 4
Reputation: 55479
I also get the same results as you when using AES.MODE_CFB, but I get the results you expect when I use AES.MODE_CBC instead.
from Crypto.Cipher import AES
def show(b):
print(*['{:02x}'.format(u) for u in b])
key = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
iv = b'\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
plain = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
crypto = AES.new(key, AES.MODE_CBC, iv)
cipher = crypto.encrypt(plain)
show(cipher)
# We need a fresh AES object to decrypt
crypto = AES.new(key, AES.MODE_CBC, iv)
decoded = crypto.decrypt(cipher)
show(decoded)
output
3a d7 8e 72 6c 1e c0 2b 7e bf e9 2b 23 d9 ec 34
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Upvotes: -1