AES-256-CBC Python decrypt data encrypted with PHP openssl_encrypt. Full Example
Our PHP is encrypting in such a way that I can not decrypt using Python.
PHP global
$cipherType = 'AES-256-CBC';
$secretKey = '12345678-abcd-abcd-abcd-123456789012';
PHP encrypt (comment show the $response [encrypted])
$value = "Joe";
$iv = random_bytes(16);
$cipherText = openssl_encrypt($value, $cipherType, $secretKey, OPENSSL_RAW_DATA, $iv);
$response = base64_encode(utf8_encode($iv . $cipherText));
//f8KxT07CgsKaJMK6HcK1w51xXcK6HW3DqcKFw6TCjShbw7PDv8KTQyfCvcOxZXrDnw==
PHP decrypt (comment show the $response [decrypted])
$value='f8KxT07CgsKaJMK6HcK1w51xXcK6HW3DqcKFw6TCjShbw7PDv8KTQyfCvcOxZXrDnw=='
$cipherData = utf8_decode(base64_decode($value));
$iv = mb_substr($cipherData, 0, 16, '8bit');
$cipherText = mb_substr($cipherData, 16, null, '8bit');
$response = openssl_decrypt($cipherText, $cipherType, $secretKey, OPENSSL_RAW_DATA, $iv);
//Joe
I tried to decrypt with Python
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
IV_LENGTH=16
secret_key = '12345678abcdabcdabcd123456789012'.encode('utf-8')
cipher_data = 'f8KxT07CgsKaJMK6HcK1w51xXcK6HW3DqcKFw6TCjShbw7PDv8KTQyfCvcOxZXrDnw=='
decoded = base64.b64decode(cipher_data)
iv = decoded[:IV_LENGTH]
cipher_text = decoded[IV_LENGTH:]
decrypt_cipher = AES.new(secret_key, AES.MODE_CBC, iv)
plain_text = decrypt_cipher.decrypt(cipher_text) #ValueError: Data must be padded to 16 byte boundary in CBC mode
plain_text.decode('utf-8')
output:
print('iv {}'.format(iv)) #iv b'\x7f\xc2\xb1ON\xc2\x82\xc2\x9a$\xc2\xba\x1d\xc2\xb5\xc3'
print('cipher_text {}'.format(cipher_text)) #cipher_text b"\x9dq]\xc2\xba\x1dm\xc3\xa9\xc2\x85\xc3\xa4\xc2\x8d([\xc3\xb3\xc3\xbf\xc2\x93C'\xc2\xbd\xc3\xb1ez\xc3\x9f"
ValueError: Data must be padded to 16 byte boundary in CBC mode
Notes:
I do not have the opportunity to modify the PHP encryption.
I am guessing PHP was removing the -
from the $secretKey, python didn't allow them and throw error such as: ValueError: Incorrect AES key length (36 bytes)
What am I missing in my python in order to decrypt?
Could the problem be that I have not padded the data in PHP and PHP is just more permissive? Or could it be the openssl_encrypt
in PHP is padding it under the hood and I need to pad/unppad in my python decrypt?
Answers
It appears that your Python decryption code is not working because it is not handling padding correctly. PHP's openssl_encrypt
function automatically applies padding, but Python's Crypto.Cipher.AES
module expects data to be padded manually.
To decrypt the data in Python, you need to ensure that you properly handle PKCS#7 padding. Here's how you can modify your Python code to include padding:
from Crypto.Cipher import AES
import base64
# Padding function for PKCS#7
def pkcs7_pad(data):
pad_length = AES.block_size - (len(data) % AES.block_size)
return data + bytes([pad_length] * pad_length)
IV_LENGTH = 16
SECRET_KEY = b'12345678abcdabcdabcd123456789012'
cipher_data = 'f8KxT07CgsKaJMK6HcK1w51xXcK6HW3DqcKFw6TCjShbw7PDv8KTQyfCvcOxZXrDnw=='
decoded = base64.b64decode(cipher_data)
iv = decoded[:IV_LENGTH]
cipher_text = decoded[IV_LENGTH:]
decrypt_cipher = AES.new(SECRET_KEY, AES.MODE_CBC, iv)
padded_plain_text = decrypt_cipher.decrypt(cipher_text)
# Remove padding
pad_length = padded_plain_text[-1]
plain_text = padded_plain_text[:-pad_length]
print('Decrypted plain text:', plain_text.decode('utf-8'))
In this modified version of your Python code, I've added a pkcs7_pad
function to pad the data before encryption. After decryption, the padding is removed to obtain the original plaintext. This should allow you to decrypt the data correctly.