ValueError: AES key must be either 16, 24, or 32 bytes long PyCrypto 2.7a1
ValueError: AES key must be either 16, 24, or 32 bytes long PyCrypto 2.7a1
我正在为我的学校项目编写程序,遇到上述问题。
这是我的代码:
def aes():
#aes
os.system('cls')
print('1. Encrypt')
print('2. Decrypt')
c = input('Your choice:')
if int(c) == 1:
#cipher
os.system('cls')
print("Let's encrypt, alright")
print('Input a text to be encrypted')
text = input()
f = open('plaintext.txt', 'w')
f.write(text)
f.close()
BLOCK_SIZE = 32
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
secret = os.urandom(BLOCK_SIZE)
f = open('aeskey.txt', 'w')
f.write(str(secret))
f.close()
f = open('plaintext.txt', 'r')
privateInfo = f.read()
f.close()
cipher = AES.new(secret)
encoded = EncodeAES(cipher, privateInfo)
f = open('plaintext.txt', 'w')
f.write(str(encoded))
f.close()
print(str(encoded))
if int(c) == 2:
os.system('cls')
print("Let's decrypt, alright")
f = open('plaintext.txt','r')
encryptedString = f.read()
f.close()
PADDING = '{'
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
encryption = encryptedString
f = open('aeskey.txt', 'r')
key = f.read()
f.close()
cipher = AES.new(key)
decoded = DecodeAES(cipher, encryption)
f = open('plaintext.txt', 'w')
f.write(decoded)
f.close()
print(decoded)
完整的错误文本:
Traceback (most recent call last): File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 341, in aes()
File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 180, in aes cipher = AES.new(key)
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 179, in new return AESCipher(key, *args, **kwargs)
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 114, in init blockalgo.BlockAlgo.init(self, _AES, key, *args, **kwargs)
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\blockalgo.py", line 401, in init self._cipher = factory.new(key, *args, **kwargs)
ValueError: AES key must be either 16, 24, or 32 bytes long
Process finished with exit code 1
我做错了什么?
错误很明显。密钥必须恰好是该大小。 os.urandom
会 return 为您提供正确的密钥。但是,此键是 bytes(二进制字符串值)。此外,通过使用 str(secret)
,将 repr(secret)
的值而不是 secret
写入文件。
更令人困惑的是 AES.new
允许您将密钥作为 Unicode 传递!但是,假设密钥是 ASCII 字节 1234123412341234
。现在,
f.write(str(secret))
将b'1234123412341234'
写入文本文件!它现在包含这 16 个字节 + b
和两个 '
引号字符,而不是 16 个字节;总共19个字节。
或者,如果您从 os.urandom
、
中获取随机二进制字符串
>>> os.urandom(16)
b'\xd7\x82K^\x7fe[\x9e\x96\xcb9\xbf\xa0\xd9s\xcb'
现在,它不再写入 16 个字节 D7
、82
、.. 等等,而是将该字符串写入文件。并且发生错误是因为解密尝试使用
"b'\xd7\x82K^\x7fe[\x9e\x96\xcb9\xbf\xa0\xd9s\xcb'"
作为解密密钥,当编码为 UTF-8 时,结果为
b"b'\xd7\x82K^\x7fe[\x9e\x96\xcb9\xbf\xa0\xd9s\xcb'"
这是一个 49 字节长的 bytes
值。
您有 2 个不错的选择。要么继续将密钥写入文本文件,但将其转换为十六进制,要么将密钥写入二进制文件;那么文件应该正好是密钥长度(以字节为单位)。我在这里选择后者:
因此存储密钥,使用
with open('aeskey.bin', 'wb') as keyfile:
keyfile.write(secret)
和
with open('aeskey.bin', 'rb') as keyfile:
key = keyfile.read()
同样自然地适用于密文(即加密的二进制文件),您必须将其写入二进制文件并从中读取:
with open('ciphertext.bin', 'wb') as f:
f.write(encoded)
和
with open('ciphertext.bin', 'rb') as f:
encryptedString = f.read()
如果您想对其进行 base64 编码,请注意 base64.b64encode/decode
是 bytes
-in/bytes
-out。
顺便说一句,plaintext is the original, unencrypted text; the encrypted text is called ciphertext。 AES 是一种密码,可以使用密钥将明文加密为密文,并将密文解密为明文。
尽管它们被称为“-text”,但正如 Python 所理解的那样,它们本身都不是文本数据,而是二进制数据,应表示为 bytes
。
我正在为我的学校项目编写程序,遇到上述问题。 这是我的代码:
def aes():
#aes
os.system('cls')
print('1. Encrypt')
print('2. Decrypt')
c = input('Your choice:')
if int(c) == 1:
#cipher
os.system('cls')
print("Let's encrypt, alright")
print('Input a text to be encrypted')
text = input()
f = open('plaintext.txt', 'w')
f.write(text)
f.close()
BLOCK_SIZE = 32
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
secret = os.urandom(BLOCK_SIZE)
f = open('aeskey.txt', 'w')
f.write(str(secret))
f.close()
f = open('plaintext.txt', 'r')
privateInfo = f.read()
f.close()
cipher = AES.new(secret)
encoded = EncodeAES(cipher, privateInfo)
f = open('plaintext.txt', 'w')
f.write(str(encoded))
f.close()
print(str(encoded))
if int(c) == 2:
os.system('cls')
print("Let's decrypt, alright")
f = open('plaintext.txt','r')
encryptedString = f.read()
f.close()
PADDING = '{'
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
encryption = encryptedString
f = open('aeskey.txt', 'r')
key = f.read()
f.close()
cipher = AES.new(key)
decoded = DecodeAES(cipher, encryption)
f = open('plaintext.txt', 'w')
f.write(decoded)
f.close()
print(decoded)
完整的错误文本:
Traceback (most recent call last): File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 341, in aes()
File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 180, in aes cipher = AES.new(key)
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 179, in new return AESCipher(key, *args, **kwargs)
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 114, in init blockalgo.BlockAlgo.init(self, _AES, key, *args, **kwargs)
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\blockalgo.py", line 401, in init self._cipher = factory.new(key, *args, **kwargs)
ValueError: AES key must be either 16, 24, or 32 bytes long
Process finished with exit code 1
我做错了什么?
错误很明显。密钥必须恰好是该大小。 os.urandom
会 return 为您提供正确的密钥。但是,此键是 bytes(二进制字符串值)。此外,通过使用 str(secret)
,将 repr(secret)
的值而不是 secret
写入文件。
更令人困惑的是 AES.new
允许您将密钥作为 Unicode 传递!但是,假设密钥是 ASCII 字节 1234123412341234
。现在,
f.write(str(secret))
将b'1234123412341234'
写入文本文件!它现在包含这 16 个字节 + b
和两个 '
引号字符,而不是 16 个字节;总共19个字节。
或者,如果您从 os.urandom
、
>>> os.urandom(16)
b'\xd7\x82K^\x7fe[\x9e\x96\xcb9\xbf\xa0\xd9s\xcb'
现在,它不再写入 16 个字节 D7
、82
、.. 等等,而是将该字符串写入文件。并且发生错误是因为解密尝试使用
"b'\xd7\x82K^\x7fe[\x9e\x96\xcb9\xbf\xa0\xd9s\xcb'"
作为解密密钥,当编码为 UTF-8 时,结果为
b"b'\xd7\x82K^\x7fe[\x9e\x96\xcb9\xbf\xa0\xd9s\xcb'"
这是一个 49 字节长的 bytes
值。
您有 2 个不错的选择。要么继续将密钥写入文本文件,但将其转换为十六进制,要么将密钥写入二进制文件;那么文件应该正好是密钥长度(以字节为单位)。我在这里选择后者:
因此存储密钥,使用
with open('aeskey.bin', 'wb') as keyfile:
keyfile.write(secret)
和
with open('aeskey.bin', 'rb') as keyfile:
key = keyfile.read()
同样自然地适用于密文(即加密的二进制文件),您必须将其写入二进制文件并从中读取:
with open('ciphertext.bin', 'wb') as f:
f.write(encoded)
和
with open('ciphertext.bin', 'rb') as f:
encryptedString = f.read()
如果您想对其进行 base64 编码,请注意 base64.b64encode/decode
是 bytes
-in/bytes
-out。
顺便说一句,plaintext is the original, unencrypted text; the encrypted text is called ciphertext。 AES 是一种密码,可以使用密钥将明文加密为密文,并将密文解密为明文。
尽管它们被称为“-text”,但正如 Python 所理解的那样,它们本身都不是文本数据,而是二进制数据,应表示为 bytes
。