Basically, my question is divided into two problems, first of all, I am having this problem when I try running this code [code below] and get an error, like this:
ImportError Traceback (most recent call last)
<ipython-input-3-3d0c04910b61> in <module>
1 import hashlib
----> 2 from crypto import Random
3 from crypto.Cipher import AES
4 from base64 import b64encode, b64decode
5
ImportError: cannot import name 'Random' from 'crypto' (C:\Users\Ahmad\anaconda3\lib\site-packages\crypto\__init__.py)
The second problem is when I enter text, i.e: "My data is here" I got the encrypted text as : "GIdd+zxj8m0nMeh7wmZJ+Q==" but reversing the process in decryption it outputs a different text, to validate the process I am using and checking through https://aesencryption.net/ as reference in my work.
My Code:
import hashlib
from crypto import Random
from crypto.Cipher import AES
from base64 import b64encode, b64decode
class AESCipher(object):
def __init__(self, key):
self.block_size = AES.block_size
self.key = hashlib.sha256(key.encode()).digest()
def encryption(self, plain_text):
plain_text = self.__pad(plain_text)
iv = Random.new().read(self.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
encrypted_text = cipher.encrypt(plain_text.encode())
return b64encode(iv + encrypted_text).decode("utf-8")
def decryption(self, encrypted_text):
encrypted_text = b64decode(encrypted_text)
iv = encrypted_text[:self.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
plain_text = cipher.decrypt(encrypted_text[self.block_size:]).decode("utf-8")
return self.__unpad(plain_text)
def __pad(self, plain_text):
number_of_bytes_to_pad = self.block_size - len(plain_text) % self.block_size
ascii_string = chr(number_of_bytes_to_pad)
padding_str = number_of_bytes_to_pad ** ascii_string
padded_plain_text = plain_text + padding_str
return padded_plain_text
@staticmethod
def __unpad(plain_text):
last_character = plain_text[len(plain_text) - 2:]
return plain_text[:-ord(last_character)]
In the __pad()
method **
is to be replaced by *
:
padding_str = number_of_bytes_to_pad * ascii_string
In the __unpad()
method the padding size is to be determined from the last byte:
last_character = plain_text[len(plain_text) - 1:]
With these changes the code can be executed successfully with PyCryptodome, see also here for the installation.
Padding does not need to be implemented explicitly. PyCryptodome supports various paddings (including PKCS7) in a dedicated module (Crypto.Util.Padding
).
Please note that deriving the key from a password with a digest is generally insecure. It is more secure to use a reliable key derivation function such as Argon2 or PBKDF2.