The error message provides vital clues as to what is going on. As you can see, the first 16 bytes of the decrypted message are different, but the next 16 bytes are the same. This happens when the key is correct, but the IV isn't.
The problem seems to be that pyCrypto doesn't reset the state of the cipher after the encryption/decryption and the IV is some other value.
Either way, you shouldn't be setting the IV once and reusing it multiple times. The IV is there to provide randomization of the ciphertexts so that attackers who observe the ciphertexts cannot determine whether the plaintext that is encrypted has repeated.
Moving AES object creation into the function, solves this issue:
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
You should check out the 2.7-alpha release of pyCrypto which includes authenticated modes such as GCM, EAX, SIV. Ciphertext authentication is important, because it might be possible to use a padding oracle attack in your system to decrypt any ciphertext.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…