我有一个可逆编码的实现:
# coding=utf-8
from Crypto.Cipher import AES
from Crypto import Random
import uuid
import unittest
import random
key = r'Sixteen byte key' # Keep this real secret
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CFB, iv)
def encode(role, plaintext):
'''Encode the message, prefix with the role specifier'''
msg = iv + cipher.encrypt(plaintext)
msg = msg.encode('hex')
msg = role + '-' + msg
return msg
def decode(msg):
'''Decode message, return role and plaintext'''
role, msg = msg.split('-', 1)
plaintext = cipher.decrypt(msg.decode('hex'))[len(iv):]
return role, plaintext
class TestMe(unittest.TestCase):
def test_whole(self):
ROLES = ['sales', 'vendor', 'designer']
for _ in xrange(100):
role = random.choice(ROLES)
txt = uuid.uuid4().hex
msg = encode(role, txt)
drole, dtxt = decode(msg)
self.assertEqual(role, drole)
self.assertEqual(txt, dtxt)
print 'ok'
if __name__ == '__main__':
unittest.main()
但这是失败的,总是在第二轮测试中。我做的事情显然是错的,但我不知道是什么。
你需要:
pip install pycrypto
运行该代码
代码失败了:
» python test.py
ok
F
======================================================================
FAIL: test_whole (__main__.TestMe)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 40, in test_whole
self.assertEqual(txt, dtxt)
AssertionError: 'b2e7894dd6254b259ae06350f199e6a2' != '\xa7\xcd\t\xde~\x15\xce\x9d\xcfU\x8f\xb2\xfa\x08\x98\x1c9ae06350f199e6a2'
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
答案 0 :(得分:2)
错误消息提供了有关正在发生的事情的重要线索。如您所见,解密消息的前16个字节不同,但接下来的16个字节是相同的。当密钥正确时会发生这种情况,但IV不是。
问题似乎是pyCrypto在加密/解密后没有重置密码的状态,而IV是其他值。
无论哪种方式,您都不应该设置IV一次并重复使用它多次。 IV用于提供密文的随机化,以便观察密文的攻击者无法确定加密的明文是否重复。
将AES对象创建移动到函数中,解决了这个问题:
key = r'Sixteen byte key' # Keep this real secret
def encode(role, plaintext):
'''Encode the message, prefix with the role specifier'''
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CFB, iv)
msg = iv + cipher.encrypt(plaintext)
msg = msg.encode('hex')
msg = role + '-' + msg
return msg
def decode(msg):
'''Decode message, return role and plaintext'''
role, msg = msg.split('-', 1)
msg = msg.decode('hex')
iv = msg[:AES.block_size]
cipher = AES.new(key, AES.MODE_CFB, iv)
plaintext = cipher.decrypt(msg[AES.block_size:])
return role, plaintext
您应该查看pyCrypto的2.7-alpha版本,其中包括经过验证的模式,如GCM,EAX,SIV。密文认证很重要,因为可能在系统中使用填充oracle攻击来解密任何密文。