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
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