Skip to content
Advertisement

Crypto module and Encryption method not working

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:UsersAhmadanaconda3libsite-packagescrypto__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)]

Advertisement

Answer

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.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement