为什么PyCrypto不使用默认IV?

时间:2013-01-17 22:30:25

标签: python aes pycrypto

我试图弄清楚为什么我的Python客户端和Ruby服务器对如何加密数据存在分歧。我在Ruby代码和我的代码中看到的唯一区别是它们没有指定初始化向量,因此它回退到所有\ x0的默认值

当我尝试在没有iv的情况下实例化PyCrypto时它会给我一个错误。这是一个例子:

from Crypto.Cipher import AES
test = "Very, very confidential data"
key = b'Thirty Two Byte key, made Beef y' 

gryp = AES.new(key, AES.MODE_CBC)

(这个例子本质上是来自PyCrypto文档的示例代码,没有指定IV)文档说w / r / t IV“它是可选的,当不存在时,它将被赋予全零的默认值。”但是我收到错误“ValueError:IV必须长16个字节”。

所以我可以指定IV,这不是问题,但是我想弄清楚,如果它认为它不能使用默认值,如果我使用库的方式有其他错误。

2 个答案:

答案 0 :(得分:16)

这似乎是Pycrypto AES的课程文档中的一个错误,因为AES实现已经更改,因此对于那些需要一个的模式,IV 是可选的(即你必须自己传递16个字节的零,如果你想这样做的话。)

请参阅此bug report for the same issue,其中某人未指定IV并查找在线文档。有一个明确要求IV的变化,基本上没有人更新在线文档以反映这一点。 Pycrypto源中的类文档已更新,但需要重新生成在线文档以反映这一点。

来自消息来源的新文档:

  

对于所有其他模式,它必须是block_size个字节长。

而不是旧版本的

  

对于所有其他模式,它必须是block_size个字节长。它是可选的   当不存在时,它将被赋予全零的默认值。

源中更新的示例(指定iv)为:

from Crypto.Cipher import AES
from Crypto import Random

key = b'Sixteen byte key'
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CFB, iv)
msg = iv + cipher.encrypt(b'Attack at dawn')

答案 1 :(得分:3)

这是一个适用于我的实现,有一些修复:

class AESCipher:

    def __init__(self, key):
        self.bs = 32
        if len(key) >= 32:
            self.key = key[:32]
        else:
            self.key = self._pad(key)

    def encrypt(self, raw):
        raw = self._pad(raw)
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return base64.b64encode(iv + cipher.encrypt(raw))

    def decrypt(self, enc):
        enc = base64.b64decode(enc)
        iv = enc[:AES.block_size]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return self._unpad(cipher.decrypt(enc[AES.block_size:]))

    def _pad(self, s):
        return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)

    def _unpad(self, s):
        return s[:-ord(s[len(s)-1:])]