AES解密在第二次解密时失败 [英] AES decryption fails when decrypting a second time

查看:437
本文介绍了AES解密在第二次解密时失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可逆编码的实现:

I have this implementation of a reversible encoding:

# 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()

但是这是第二个测试轮次,这是失败的,总是。我正在做一些明显错误的事情,但我不知道什么。

But this is failing, always on the second test round. I am doing something obviously wrong, but I do not know what.

您需要: / p>

You need to:

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)


推荐答案

错误信息提供了关于发生什么的重要线索。如您所见,解密消息的前16个字节不同,但接下来的16个字节是相同的。这是在键正确的时候发生的,但是IV不是。

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.

问题似乎是pyCrypto不会在加密/解密和IV是一些其他的价值。

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.

无论哪种方式,您不应该设置IV一次并重复使用多次。 IV是提供密文的随机化,以便观察密文的攻击者无法确定加密的明文是否重复。

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.

将AES对象创建移动到函数中解决这个问题:

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

您应该查看pyCrypto的2.7-alpha版本,包括认证模式,如GCM,EAX,SIV。密文验证很重要,因为可能在系统中使用填充oracle攻击来解密任何密文。

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.

这篇关于AES解密在第二次解密时失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆