问题
so I have been trying to build an AES encryption program based off of the github pycrypto guide link to github however when I go to decode an error shows up:
Traceback (most recent call last):
File "/home/pi/Desktop/aes/newAES.py", line 24, in <module>
print(decrypt(key,msg,iv))
File "/home/pi/Desktop/aes/newAES.py", line 13, in decrypt
cipher = AES.new(key,AES.MODE_CFB)
File "/usr/lib/python3/dist-packages/Crypto/Cipher/AES.py", line 94, in new
return AESCipher(key, *args, **kwargs)
File "/usr/lib/python3/dist-packages/Crypto/Cipher/AES.py", line 59, in __init__
blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs)
File "/usr/lib/python3/dist-packages/Crypto/Cipher/blockalgo.py", line 141, in __init__
self._cipher = factory.new(key, *args, **kwargs)
ValueError: IV must be 16 bytes long
my code is:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def encrypt(key,msg):
if key == 0:
key=get_random_bytes(16)
print("key: "+key)
iv = get_random_bytes(16)
print('iv: '+str(iv))
cipher = AES.new(key,AES.MODE_CFB,iv)
ciphertext= cipher.decrypt(msg)
return("your encrypted message: "+str(ciphertext))
def decrypt(key,ciphertext,iv):
cipher = AES.new(key,AES.MODE_CFB)
msg = cipher.decrypt(ciphertext)
ed = input('(e)ncrypt or (d)ecrypt: ')
if ed=='e':
key = input('16 digit key: ')
msg = input('message: ')
print(encrypt(key,msg))
elif ed =='d':
key = input('16 digit key: ')
iv = bytes(input('iv: '),'utf-8')
msg = bytes(input('encrypted message:'),'utf-8')
print(decrypt(key,msg,iv))
I would appreciate any help offered on solving this issue, hopefully it isn't some stupid error
回答1:
The problem with iv
is that it consists of random bytes, but it is being read into your program as a string. Calling bytes
on that string does not do what you expect.
>>> iv = b'\xba\x0eyO8\x17\xcf\x97=\xf2&l34#('
>>> siv = str(iv)
>>> siv
"b'\\xba\\x0eyO8\\x17\\xcf\\x97=\\xf2&l34#('" # Note 'b' is part of the string
>>> biv = bytes(siv, 'utf-8')
>>> biv
b"b'\\xba\\x0eyO8\\x17\\xcf\\x97=\\xf2&l34#('" # Now there are two 'b's!
You can resolve this by using ast.literal_eval:
>>> ast.literal_eval(siv)
b'\xba\x0eyO8\x17\xcf\x97=\xf2&l34#('
Here's a working version of your code - I removed the need to copy/paste iv
, but the same observations about inputting bytes applies to the ciphertext.
import ast
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def encrypt(key, msg):
iv = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CFB, iv)
ciphertext = cipher.encrypt(msg) # Use the right method here
return iv + ciphertext
def decrypt(key, ciphertext):
iv = ciphertext[:16]
ciphertext = ciphertext[16:]
cipher = AES.new(key, AES.MODE_CFB, iv)
msg = cipher.decrypt(ciphertext)
return msg.decode("utf-8")
if __name__ == "__main__":
ed = input("(e)ncrypt or (d)ecrypt: ")
if ed == "e":
key = input("16 digit key: ")
msg = input("message: ")
print("Encrypted message: ", encrypt(key, msg))
elif ed == "d":
key = input("16 digit key: ")
smsg = input("encrypted message: ")
msg = ast.literal_eval(smsg)
print("Decrypted message: ", decrypt(key, msg))
The code in action:
(e)ncrypt or (d)ecrypt: e
16 digit key: abcdabcdabcdabcd
message: Spam, spam, spam
Encrypted message: b'\xa4?\xa9RI>\x1f\xb5*\xb2,NWN\x0c\xfd"yB|\x1f\x82\x96\xd5\xb4\xd4\x1d&\x8bM\xdb\x07'
(e)ncrypt or (d)ecrypt: d
16 digit key: abcdabcdabcdabcd
encrypted message: b'\xa4?\xa9RI>\x1f\xb5*\xb2,NWN\x0c\xfd"yB|\x1f\x82\x96\xd5\xb4\xd4\x1d&\x8bM\xdb\x07'
Decrypted message: Spam, spam, spam
来源:https://stackoverflow.com/questions/54131181/python-3-pycrypto-iv-must-be-16-bytes-long