2016-09-23 369 views
1

我在SO上搜索了很多关于完成加密解密示例与我的要求。事实上,我有很多链接和例子,但是对于AES-192-CBC模式和AES-256-CBC,我无法使用它。使用PKCS#7填充的Python 3中的AES-CBC 128,192和256加密解密

我得到了下面的例子,它应该与所有类型一起工作,但它只能用于AES-128-CBC模式。我是Python的新手。任何人都可以帮助我,我错了吗?

我在Windows上使用Python 3.4,我无法移动到Python 2.7。

import base64 
from Crypto.Cipher import AES 

class AESCipher: 
    class InvalidBlockSizeError(Exception): 
     """Raised for invalid block sizes""" 
     pass 

    def __init__(self, key, block_size=16): 
     if block_size < 2 or block_size > 255: 
      raise AESCipher.InvalidBlockSizeError('The block size must be between 2 and 255, inclusive') 
     self.block_size = block_size 
     self.key = key 
     self.iv = bytes(key[0:16], 'utf-8') 
     print(self.key) 
     print(key[0:16]) 

    def __pad(self, text): 
     text_length = len(text) 
     amount_to_pad = self.block_size - (text_length % self.block_size) 
     if amount_to_pad == 0: 
      amount_to_pad = self.block_size 
     self.pad = chr(amount_to_pad) 
     return text + self.pad * amount_to_pad 

    def __unpad(self, text): 
     #pad = ord(text[-1]) 
     #return text[:-pad] 
     text = text.rstrip(self.pad) 
     return text 

    def encrypt(self, raw): 
     raw = self.__pad(raw) 
     cipher = AES.new(self.key, AES.MODE_CBC, self.iv) 
     return base64.b64encode(cipher.encrypt(raw)) 

    def decrypt(self, enc): 
     enc = base64.b64decode(enc) 
     cipher = AES.new(self.key, AES.MODE_CBC, self.iv) 
     return self.__unpad(cipher.decrypt(enc).decode("utf-8")) 

e = AESCipher('1234567812345678', 16) 
#e = AESCipher('123456781234567812345678', 24) 
#e = AESCipher('12345678123456781234567812345678', 32) 
secret_data = "hi" 
enc_str = e.encrypt(secret_data) 
print('enc_str: ' + enc_str.decode()) 
dec_str = e.decrypt(enc_str) 
print('dec str: ' + dec_str) 

虽然这个代码加密与192和256位加密的数据,并成功解密太多,但我的其他.Net和Ruby应用程序只能够解密这是用128加密方法加密的数据。

注意.Net和Ruby应用程序已成功通过相互之间的测试以及使用所有加密类型的联机加密工具进行测试。

请注意,我的应用程序需要AES-CBC模式和PKCS#7填充,并且必须在Python 3.4上运行。

回答

2

它使用任何加密类型的16个字节的填充工作。为此,我使用AES.block_size,AES默认为16。

import base64 
from Crypto.Cipher import AES 

class AESCipher: 
    class InvalidBlockSizeError(Exception): 
     """Raised for invalid block sizes""" 
     pass 

    def __init__(self, key): 
     self.key = key 
     self.iv = bytes(key[0:16], 'utf-8') 
     print(self.key) 
     print(key[0:16]) 

    def __pad(self, text): 
     text_length = len(text) 
     amount_to_pad = AES.block_size - (text_length % AES.block_size) 
     if amount_to_pad == 0: 
      amount_to_pad = AES.block_size 
     pad = chr(amount_to_pad) 
     return text + pad * amount_to_pad 

    def __unpad(self, text): 
     pad = ord(text[-1]) 
     return text[:-pad] 

    def encrypt(self, raw): 
     raw = self.__pad(raw) 
     cipher = AES.new(self.key, AES.MODE_CBC, self.iv) 
     return base64.b64encode(cipher.encrypt(raw)) 

    def decrypt(self, enc): 
     enc = base64.b64decode(enc) 
     cipher = AES.new(self.key, AES.MODE_CBC, self.iv) 
     return self.__unpad(cipher.decrypt(enc).decode("utf-8")) 

e = AESCipher('1234567812345678', 16) 
#e = AESCipher('123456781234567812345678', 24) 
#e = AESCipher('12345678123456781234567812345678', 32) 
secret_data = "hi" 
enc_str = e.encrypt(secret_data) 
print('enc_str: ' + enc_str.decode()) 
dec_str = e.decrypt(enc_str) 
print('dec str: ' + dec_str) 
+0

我不明白这个答案。您已将'self.block_size'更改为'16',但'block_size'已使用'16'初始化,所以没有任何更改。你换了别的东西吗? –

+0

请完整阅读该问题。我写过,当我采取24和32块大小,那么它不起作用。因为之前的黑色大小通过参数中传递的内容初始化。请参阅__pad函数和注释代码man。 –

+0

我明白了。我没有看到你的评论代码。尽管如此,AES-256中的256总是意味着密钥大小而不是块大小,因为正如你可能已经知道的那样,AES有一个16字节的固定块大小,你可以在pyCrypto中用'AES.block_size'得到这个。您不需要对此进行硬编码。由于在初始化过程中您不需要传递块大小,因此您应该在答案中包含该代码(完成后请ping我,以便删除我的downvote)。 –