2013-01-17 150 views
13

我想弄清楚爲什麼我的Python客戶端和Ruby服務器在如何加密數據方面存在分歧。我在Ruby代碼和我的代碼中看到的唯一區別是它們沒有指定初始化向量,因此它回落到默認值\ x0's爲什麼PyCrypto不使用默認IV?

當我試圖在沒有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,這不是問題本身,但我想弄清楚,如果它認爲它不能使用默認值,如果我使用庫的方式有其他錯誤。

回答

16

這似乎是類文檔Pycrypto的AES一個錯誤,因爲AES實現已更改,從而使四是爲那些需要一個(即你必須通過16個字節的模式可選將自己歸零,如果這就是你想要的那樣)。

看到這個bug report for the same issue有人沒有指定一個IV並查閱在線文檔。有一個明確要求IV的變化,實質上,沒有人更新在線文檔以反映這一點。 Pycrypto源中的類文檔已更新,但需要重新生成在線文檔以反映這一點。

從起點狀態的新文檔:

For all other modes, it must be block_size bytes longs.

取而代之的是舊版本的

For all other modes, it must be block_size bytes longs. It is optional and when not present it will be given a default value of all zeroes.

源,指定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') 
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:])] 
+0

我不禁覺得截斷一個鍵是個壞主意。 – cpburnz

相關問題