使用 pyaes 进行 AES 加密时,明文块必须为 16 字节错误

plaintext block must be 16 bytes error when using pyaes for AES Encryption

我正在尝试使用 pyaes 进行 AES 加密。

我下面的代码是 运行 完美。

text = 'Hello world !!!!'
encrypter = pyaes.AESModeOfOperationCBC('my_test_key_0001', 'my_test_vec_0001')
encrypted = base64.b64encode(encrypter.encrypt(text))
print(encrypted)

但是,当我将文本值更改为

text = 'rO0ABXVyAAJbQqzzF/gGCFTgAgAAeHAAAAAI3z7LN2KbyKE='

它returns有错误。

Traceback (most recent call last):
  File "/home/path/cryptolib/test.py", line 54, in <module>
    encrypted = base64.b64encode(encrypter.encrypt(text))
  File "/home/path/pyaes/aes.py", line 389, in encrypt
    raise ValueError('plaintext block must be 16 bytes')
ValueError: plaintext block must be 16 bytes

我不是 AES 方面的专家,所以可能缺少基础知识。

我不能使用 pycrypto,因为我正在为 redshift 开发 UDF,根据我的发现,那里不支持 pycrypto

pyaes#AESModeOfOperationCBC only allows the encryption of a text that is exactly one block (16 bytes) long. For longer texts BlockFeeder必须使用:

import pyaes, base64

#Encryption
text = 'rO0ABXVyAAJbQqzzF/gGCFTgAgAAeHAAAAAI3z7LN2KbyKE='
encrypter = pyaes.Encrypter(pyaes.AESModeOfOperationCBC('my_test_key_0001', 'my_test_vec_0001'))
ciphertext = encrypter.feed(text)
ciphertext += encrypter.feed()
ciphertext = base64.b64encode(ciphertext)

#Decryption
decrypter = pyaes.Decrypter(pyaes.AESModeOfOperationCBC('my_test_key_0001', 'my_test_vec_0001'))
decrypted = decrypter.feed(base64.b64decode(ciphertext))
decrypted += decrypter.feed()
print('>' + decrypted + '<\n')

BlockFeeder 也会自动执行padding。填充是将数据添加到消息的末尾,直到长度对应于块长度的整数倍(通常很重要,但与您的示例无关,因为长度条件已经满足)。

编辑:

Encrypter#feed(<plaindata>)缓冲明文,加密除最后一个块(如果最后一个块完整)或最后两个块(如果最后一个块不完整)以外的数据,returns加密的数据。最后的 Encrypter#feed() 调用发出明文结束的信号,触发余数的填充和加密,以及 returns 加密数据。这可以是 用以下代码片段说明:

import pyaes

#Encryption
encrypter = pyaes.Encrypter(pyaes.AESModeOfOperationCBC('my_test_key_0001', 'my_test_vec_0001'))
ciphertext = encrypter.feed ('0123456789ABCDEF')                            # 1. block buffered,                   ciphertext  = ''
ciphertext += encrypter.feed('0123456789ABCDE')                             # 1. and incomplete 2. block buffered, ciphertext += ''                     
print("Current length of ciphertext: " + str(len(ciphertext)) + " Bytes\n")
ciphertext += encrypter.feed('F')                                           # 1. block flushed, 2. block buffered, ciphertext += '<encrypted 1. block>' 
print("Current length of ciphertext: " + str(len(ciphertext)) + " Bytes\n")
ciphertext += encrypter.feed('0123456789ABCDEF')                            # 2. block flushed, 3. block buffered, ciphertext += '<encrypted 2. block>'  
print("Current length of ciphertext: " + str(len(ciphertext)) + " Bytes\n")
ciphertext += encrypter.feed('0123456')                                     # 3. and incomplete 4. block buffered, ciphertext += ''                    
print("Current length of ciphertext: " + str(len(ciphertext)) + " Bytes\n")
ciphertext += encrypter.feed()                                              # 3. and padded 4. block flushed,      ciphertext += '<encrypted 3. and 4. padded block >' 
print("Current length of ciphertext: " + str(len(ciphertext)) + " Bytes\n")

#Decryption
decrypter = pyaes.Decrypter(pyaes.AESModeOfOperationCBC('my_test_key_0001', 'my_test_vec_0001'))
decrypted = decrypter.feed(ciphertext)
decrypted += decrypter.feed()
print('>' + decrypted + '<\n')

示例中,最后一段纯文本不完整。如果纯文本的最后一个块已经完成,则填充一个额外的完整块。这里使用的padding是PKCS7.