pycrypto 不会为 AES(CFB 模式)复制 NIST 测试向量
pycrypto does not reproduce NIST test vectors for AES (CFB mode)
这个小 python 程序应该使用 128 位密钥在 CFB 模式下使用 AES 将 plain 加密为 cipher
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))
我从 NIST test vectors (CFB128VarTxt128.rsp) 之一中获取了这个密钥、IV 和明文密码组合。对于这个特定的组合,我希望密码:
3a d7 8e 72 6c 1e c0 2b 7e bf e9 2b 23 d9 ec 34
但是 pycrypto 计算
3a 81 e1 d4 b8 24 75 61 46 31 63 4b 5c 79 d6 bc
第一个字节正确,而其他不匹配。我也尝试了不同的测试向量,但结果保持不变。除第一个字节外,所有字节都不匹配。
我很确定,NIST 测试向量是有效的,因为我之前在使用 AES 和 Crypto++ 时使用过它们,而且我也很确定,pycrypto 的实现是正确的,因为它的输出与在线工具一致,例如this page。很明显,是我用错了工具...
有没有人知道如何使用 pycrypto 重现 NIST 测试向量?
这是 NIST 示例
# 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
我在使用 AES.MODE_CFB 时也得到了与您相同的结果,但是当我使用 AES.MODE_CBC 时我得到了您期望的结果。
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)
输出
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
您在 AES.new(...)
调用中缺少关键字参数 segment_size
。这个是反馈大小,默认是8。如果你这行代码改成
aes = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
你得到了正确的结果。
如文档中所述:
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.
您的结果对应于 NIST 文档中可能标记的内容 "CFB8"。
这个小 python 程序应该使用 128 位密钥在 CFB 模式下使用 AES 将 plain 加密为 cipher
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))
我从 NIST test vectors (CFB128VarTxt128.rsp) 之一中获取了这个密钥、IV 和明文密码组合。对于这个特定的组合,我希望密码:
3a d7 8e 72 6c 1e c0 2b 7e bf e9 2b 23 d9 ec 34
但是 pycrypto 计算
3a 81 e1 d4 b8 24 75 61 46 31 63 4b 5c 79 d6 bc
第一个字节正确,而其他不匹配。我也尝试了不同的测试向量,但结果保持不变。除第一个字节外,所有字节都不匹配。
我很确定,NIST 测试向量是有效的,因为我之前在使用 AES 和 Crypto++ 时使用过它们,而且我也很确定,pycrypto 的实现是正确的,因为它的输出与在线工具一致,例如this page。很明显,是我用错了工具...
有没有人知道如何使用 pycrypto 重现 NIST 测试向量?
这是 NIST 示例
# 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
我在使用 AES.MODE_CFB 时也得到了与您相同的结果,但是当我使用 AES.MODE_CBC 时我得到了您期望的结果。
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)
输出
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
您在 AES.new(...)
调用中缺少关键字参数 segment_size
。这个是反馈大小,默认是8。如果你这行代码改成
aes = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
你得到了正确的结果。
如文档中所述:
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.
您的结果对应于 NIST 文档中可能标记的内容 "CFB8"。