import constants
import base64
from secrets import token_hex
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import padding as sym_padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import padding as rsa_padding
from cryptography.hazmat.primitives.serialization import load_pem_public_key, load_pem_private_key
from src.func.jwt_token import generate_jwt
This Fuction Encrypting the header
def encrypt_header_with_header_public_key(data: str, header_key):
header_public_key = load_pem_public_key(header_key)
encrypted_header_data = header_public_key.encrypt(
data.encode(),
rsa_padding.PKCS1v15()
)
return base64.b64encode(encrypted_header_data)
This Function will encrypt the body with AES KEY and IV
def encrypt_body_with_aes(aes_key, data, iv):
cipher = Cipher(
algorithms.AES(aes_key), modes.CBC(iv), backend=default_backend()
)
encryptor = cipher.encryptor()
padder = sym_padding.PKCS7(algorithms.AES.block_size).padder()
padded_data = padder.update(data.encode()) + padder.finalize()
encrypted_data = encryptor.update(padded_data) + encryptor.finalize()
return base64.b64encode(encrypted_data)
This Function Will decrypt the response from the server
def decrypt_response(encrypted_response, aes_key, iv):
print("AES for Decryption:",aes_key)
print("IV for Decryption:",iv)
if isinstance(encrypted_response, str):
encrypted_data = base64.b64decode(encrypted_response.encode())
else:
encrypted_data = base64.b64decode(encrypted_response)
cipher = Cipher(
algorithms.AES(aes_key), modes.CBC(iv), backend=default_backend()
)
decryptor = cipher.decryptor()
decrypted_padded_data = decryptor.update(
encrypted_data) + decryptor.finalize()
unpadder = sym_padding.PKCS7(algorithms.AES.block_size).unpadder()
decrypted_data = unpadder.update(
decrypted_padded_data) + unpadder.finalize()
return json.loads(decrypted_data.decode())
This Function Will Generate AES_KEY and IV
def generate_aes_key():
secret = "HERE IS MY SECRET"
salt = token_hex(8)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt.encode(),
iterations=100000,
backend=default_backend(),
)
encrypted_salt = encrypt_header_with_header_public_key(
salt, constants.BODY_PUBLIC_KEY
)
aes_key = kdf.derive(secret.encode())
decoded_salt = encrypted_salt.decode()
generated_salt = salt
iv = generated_salt.encode()
return aes_key, decoded_salt, generated_salt, iv
This Function Will Finally Encrypt the Request Body with AES KEY AN Iv Using the “encrypt_body_with_aes()” Fuction
def encrypt_body_with_body_public_key(request_body: dict, aes_key, iv):
print("AES for Encryption:",aes_key)
print("IV for Encryption:",iv)
encrypted_body = encrypt_body_with_aes(
aes_key, json.dumps(request_body), iv)
return encrypted_body
def main():
aes_key, decoded_salt_as_key_header, generated_salt, iv = generate_aes_key()
body = {"myaccountNumber": "1234567890"}
header_data = {
"partner": "ABCD1234",
"headerToken": "ghjdgjsgj-jdsjgsjg-gjsg-hjsghjs-jsjsgjsg",
}
encrypted_request_body = encrypt_body_with_body_public_key(
body, aes_key, iv
).decode()
headers = {
"Auth": encrypt_header_with_header_public_key(
json.dumps(header_data), constants.HEADER_PUBLIC_KEY
).decode(),
"key": decoded_salt_as_key_header,
"token": generate_jwt(),
"cache-control": "no-cache",
"content-type": "application/json",
"User-Agent": "APIAGENT/7.29.2",
}
data = {
"requestData": encrypted_request_body
}
print(data)
response = httpx.post(
constants.CHECK_ACOOUNT_ID,
headers=headers,
json=json.dumps(data),
)
response = response.json()
print(response)
encrypted_response = response.get("returnData")
print("encrypted_response :", encrypted_response)
# Decrypt the response using the same AES key and IV
decrypted_response = decrypt_response(encrypted_response, aes_key, iv)
print(decrypt_response)
if __name__ == "__main__":
main()
Here is my server response :
{'returnData': 'y7SZOuY+njhjdshjdjfdfhjdsfdh+bdjbjdbjdbjdbcjdbcdjb+tphfbs5LI+29b0plz8aEA+m0bEUQtA1OTS3EpeRfHpLFO1Llyj90ojoSvi1poodGQ53QdFi+6mMxu6hadzexRG+Nc9yLHj263OEnX5Um'}
I am Getting this error while Decrypting :
Traceback (most recent call last):
File "/home/ubuntu/ciprpa/pabitra.py", line 143, in <module>
main()
File "/home/ubuntu/ciprpa/pabitra.py", line 137, in main
decrypted_response = decrypt_response(encrypted_response, aes_key, iv)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/ciprpa/pabitra.py", line 56, in decrypt_response
decrypted_padded_data) + unpadder.finalize()
^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/ciprpa/.venv/lib/python3.12/site-packages/cryptography/hazmat/primitives/padding.py", line 136, in finalize
result = _byte_unpadding_check(
^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/ciprpa/.venv/lib/python3.12/site-packages/cryptography/hazmat/primitives/padding.py", line 103, in _byte_unpadding_check
raise ValueError("Invalid padding bytes.")
ValueError: Invalid padding bytes.
The Provider Guided I Have to use the same AES_KEY and IV to decrypt the response which I have use to encrypt the request Body and I have Done this and confirmed that the AES_KEY and IV is Same but still getting Invalid Padding bytes
Can Anyone please help me out to solve this issue