pythondjangoencryptionaespycryptodome

Error in AES Encryption/Decryption via python


We have integrated a API through which I am getting a encrypted data. Now in the docs they have given me a software link to decrypt the data.

Here is the website they have recommend me to use to decrypt the received data: https://aesencryption.net/

It works fine and I am getting the decrypted data on this website

On this website they have given their code they are using for decryption & that is in PHP. I have used chat GPT to convert that PHP code in python with little modification of my own. But it doesn't work with this code.

I am mentioning everything that I have and have tried.

import hashlib
from Crypto.Cipher import AES
import base64

class AESFunction:
    secret_key = None
    key = None
    decrypted_string = None
    encrypted_string = None

    @staticmethod
    def set_key(my_key):
        key = bytes.fromhex(my_key)
        sha = hashlib.sha256()
        sha.update(key)
        key = sha.digest()[:32]
        AESFunction.secret_key = AESFunction.key = key

    @staticmethod
    def get_decrypted_string():
        return AESFunction.decrypted_string

    @staticmethod
    def set_decrypted_string(decrypted_string):
        AESFunction.decrypted_string = decrypted_string

    @staticmethod
    def get_encrypted_string():
        return AESFunction.encrypted_string

    @staticmethod
    def set_encrypted_string(encrypted_string):
        AESFunction.encrypted_string = encrypted_string

    @staticmethod
    def encrypt(str_to_encrypt):
        cipher = AES.new(AESFunction.secret_key, AES.MODE_CBC)
        encrypted_bytes = cipher.encrypt(AESFunction.pad(str_to_encrypt).encode('utf-8'))
        AESFunction.set_encrypted_string(base64.b64encode(encrypted_bytes).decode('utf-8'))

    @staticmethod
    def decrypt(str_to_decrypt):
        cipher = AES.new(AESFunction.secret_key, AES.MODE_CBC)
        decrypted_bytes = cipher.decrypt(base64.b64decode(str_to_decrypt))
        AESFunction.set_decrypted_string(AESFunction.unpad(decrypted_bytes).decode('utf-8', errors='replace'))

    @staticmethod
    def pad(text):
        block_size = 32
        pad_len = block_size - (len(text) % block_size)
        padding = chr(pad_len) * pad_len
        return text + padding

    @staticmethod
    def unpad(text):
        pad_len = ord(text[-1])
        return text[:-pad_len]

str_password = "f4622a74c54b81f0404c1b6589e8f96c"

str_to_decrypt = "yH0lcZaFBnG3usii6UXZovCYKZYXFUuZF5vcmT+Tz59FQw2pgkke97F/O9BrlEEB3WcqxxdgoVVq+uKxg3y14HzWmByy+f7ck68eyjxULgdCjwka666rDPjm0Tf/+jjnteSbtVPc9WRLuhaPiFBblI9aK3B38ApECDCNvvRjwE+GtfeGqcu1tCo9aTJAwXroN58Tvu6Otn2quNHyLjUrDEfSzsifkGS8rdid6J+c4VZsK87pALA/CIQxtA7z8W91f+x2bb5EfH8nglfBpsE1FP9IBnI5ECjVTJy9pM45TJhnHSYOIRHX5jcwMSUDLgBdjJ57EHdzf0RqTO4ZdLHv7xpMSsVP1oHClqbGTd9UE/yXt9a2Fvm+rPKAL9rU9tXtMCe6uONgnRELrn2VePJYcp3qViP/1HReN4IbT4EYUlXJ/Tqdph6YERTKUh67mnF4lPfHCsrb9AsPNcMYn7r8tT5dMgC1wjzXO22+tUuD8DWEbnrHPPID1WBCRua3POBMyGUcMkSIEdke739pDoKxW1Ww6iGsbsQX60g5jiJEAg6fghn6P+6osKXrfLO4OirsUo8SKRO1m6YSMf31htvkcJbUbDAe2nG+aeUxEozdVyRxUauMtxYahvqcQPJtEKgAugPoCYrPx+RhutoPyaHOOzUtzXvznOV+2qcE0HfLaSotFPeteQzx7Qj4lKDVNkmkwn8jRyVfMUFzRp01v6DqsJe89uIdTyAe65rpyzNt17TDOR8BWLxifOAhDosrW61RfFE+HBU3egySbfs3PxJxHUOrwBOhnGQwILN+bENaLgcQCjczgs9BZ3i+6XK7DwLNFL1xBt42i09NpyIbJYXE1ZkrObA9rrmGLhHCqkhIDyBAaWYYNOdYOVIRbUWSA+bSeCg6xIgy/FhhxxNsmtYAMzrdjQyjYIIEuAvhe9wOTP1IPNqbtuyEPoObThCtZy3JunneK4SdW5f5rzNDOPu4dHw1EuRBYNmqmXh2Mpw2LWoit/+8Eob4aiZDpeH3HJAXrXHH+lyulJgxm4fkHZXcj25ISr0OOHjuLqAIn7ezceeRnLSfHkjL74klt0aRCIuG0p6MKwVVdHEX2n4WblcYHgEHNUoWWpOb9I3gf6Egb5uk59u9Sjc+9/MRaXoIulv+qgRNDGVMByEIqNlpmPSKnwWEEmtV54aa2QjGMOb282tTuEMpha9uHrgBfEwsKeXZ6Uwx1SPyvNHa5eoTojLc7avBdU//5XwPLp40DRvuLo6Kn6fY2SMeWRqP8A4LtarU+2eYwqWkdeggJFF3LFBkYDDwh9N+j8mBdtv1sg/bguD6yUE3UUN/jZ9nhxraxt9qrP11ifXnvSK5BToa7t5SFBiMDCM/n/bBINd+N05937KStvC76AsZHFvxl4xVZq2200qDCYzSrGbVrRcJUABvvlXm1EGHWAQcfe9K5UJ5KZIwijd9p1e2OReHNOziw1VGYR3vZ45ZkqNQnRaqYacnmXEGYgXa7ik92PWarE148+TRdoDBC1jPHRNejXNx9KRoU88cZiGENRjm80jTxZ4tWgVFDzS99GhsHkZw2+4pHZNN06gZce1KsQnnx+algAYK"

Encrypted data I am getting from https://aesencryption.net/

[{"paneli/":"7a7","panel name":"Nurition Gene Test"},{"panel_id":"798","panel name":"Fitness Genomics"},{"panel_id":"799","panel name":"Hormonal Disorders"},{"panel_id":"801","panel name":"Allergy"},{"panel_id":"802","panel name":"Personality Traits"},{"panel_id":"803","panel name":"Dermatology"},{"panel_id":"804","panel name":"Addiction"},{"panel_id":"805","panel name":"Neurology"},{"panel_id":"806","panel name":"Lifestyle Genomics"},{"panel_id":"807","panel name":"Ophthalmology"},{"panel_id":"808","panel name":"Renal Disorders"},{"panel_id":"809","panel name":"Circadian Rhythm Associated Traits"},{"panel_id":"810","panel name":"GastroIntestinal Disorders"},{"panel_id":"811","panel name":"Pulmonary Disorder"},{"panel_id":"812","panel name":"Vaccinomics"},{"panel_id":"813","panel name":"Immunology"},{"panel_id":"814","panel name":"Dental Diseases"},{"panel_id":"815","panel name":"Cardiovascular Diseases"},{"panel_id":"816","panel name":"IVF & Pregnancy Loss"},{"panel_id":"817","panel name":"Hematological Diseases"},{"panel_id":"818","panel name":"Bone Health and Diseases"},{"panel_id":"819","panel name":"Infectious Diseases"},{"panel_id":"991","panel name":"QUA Request"}]

Finally, I am using this command to get the decryption data:

AESFunction.decrypt(str_to_decrypt)
decrypted_string = AESFunction.get_decrypted_string()
print("Decrypted string:", decrypted_string)

I am getting this error (that is coming from "def unpad(text)":

TypeError: ord() expected string of length 1, but int found

I have idea of what this error means but have no solution for this. Can someone please help me out ot find a method to decrypt such data that I am receiving from the API


Solution

  • The website performs a simple encryption with AES/CBC/PKCS#7. The key results from the ASCII encoding of f462... so it is 32 bytes long (AES-256), and the IV is the ASCII encoding of 1234567890123456.
    To fix the posted Python code you need to remove the key derivation via SHA256, apply the static IV, and (for simplicity) use PyCryptodome's PKCS#7 support. Yes, you'll probably be faster if you throw away the ChatGPT solution and rewrite the code, e.g.:

    from base64 import b64decode
    from Crypto.Cipher import AES
    from Crypto.Util.Padding import unpad
    
    iv = b"1234567890123456"
    key = b"f4622a74c54b81f0404c1b6589e8f96c"
    ct = b64decode("yH0l...gAYK")
    
    cipher = AES.new(key, AES.MODE_CBC, iv)
    pt = unpad(cipher.decrypt(ct), AES.block_size)
    print(pt.decode("utf-8")) # [{"panel_id":"797",...
    

    Security notes: The IV should not be static, but random for each encryption. The key should not consist of ASCII characters only, but should be a random byte sequence ( e.g. generated with a CSPRNG or derived using a key derivation function like at least PBKDF2). For testing purposes, both are of course acceptable.