I have a value that was encrypted using PHP openssl using cipher AES-CBC-256 but the passphrase for the final value was also encrypted using the same method. openssl_encrypt($key, $cipher, $passphrase, 0, $iv)
I need to be able to unencrypt this data using Python but I'm running into block-size issues.
Here's some of the code I have so far. I have tested decrypting this in PHP and it works properly. My final value in this example should be 'Jimmy'.
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
localKey = base64.b64decode('Po0KPxyF')
localIv = base64.b64decode('s8W+/a4jkp9mhO3NkCL7Yg==')
encrypted_value = base64.b64decode('hl5n6Nq5QYtgKIyLEVCupA==')
encrypted_key = base64.b64decode('MGRHRFlaMzhCR0lxb2VHS1JHQXcrWkV2bkJpNWFZb3cybW9iQW5KYTlOU0xKK1FHc2pPUW1MUE9JRU5zTXN1Rg==')
encrypted_iv = base64.b64decode('J31SrExr7KKIOertYIPhpQ==')
# First need to encrypted key that uses the local key as the passphrase
cipher_key = AES.new(pad(localKey,16), AES.MODE_CBC, localIv)
decrypted_key = cipher_key.decrypt(encrypted_key)
# Then decrypted the final value using the newly decrypted key
cipher_key = AES.new(unpad(decrypted_key,16), AES.MODE_CBC, encrypted_iv)
decrypted_value = cipher_key.decrypt(encrypted_value)
I managed to figure out the PHP code that does the decryption:
$localKey = base64_decode('Po0KPxyF');
$localIv = base64_decode('s8W+/a4jkp9mhO3NkCL7Yg==');
$encrypted_value = base64_decode('hl5n6Nq5QYtgKIyLEVCupA==');
$encrypted_key = base64_decode('MGRHRFlaMzhCR0lxb2VHS1JHQXcrWkV2bkJpNWFZb3cybW9iQW5KYTlOU0xKK1FHc2pPUW1MUE9JRU5zTXN1Rg==');
$encrypted_iv = base64_decode('J31SrExr7KKIOertYIPhpQ==');
$decrypted_key = openssl_decrypt(base64_decode($encrypted_key), 'aes-256-cbc', $localKey, OPENSSL_RAW_DATA, $localIv);
$decrypted_value = openssl_decrypt($encrypted_value, 'aes-256-cbc', $decrypted_key, OPENSSL_RAW_DATA, $encrypted_iv);
echo $decrypted_value;
Output:
s:5:"Jimmy";
(Demo)
Remarks:
$localKey
is shorter than 256 bits, so openssl_decrypt()
pads it with null bytes$encrypted_key
was base64-encoded twice, so you need to decode it twice$decrypted_value
was serialized with serialize()
Here is a Python implementation (based on PyCryptodome):
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
localKey = base64.b64decode('Po0KPxyF')
localIv = base64.b64decode('s8W+/a4jkp9mhO3NkCL7Yg==')
encrypted_value = base64.b64decode('hl5n6Nq5QYtgKIyLEVCupA==')
encrypted_key = base64.b64decode('MGRHRFlaMzhCR0lxb2VHS1JHQXcrWkV2bkJpNWFZb3cybW9iQW5KYTlOU0xKK1FHc2pPUW1MUE9JRU5zTXN1Rg==')
encrypted_iv = base64.b64decode('J31SrExr7KKIOertYIPhpQ==')
# First need to encrypted key that uses the local key as the passphrase
cipher_key = AES.new(localKey.ljust(32, b'\0'), AES.MODE_CBC, localIv)
decrypted_key = cipher_key.decrypt(base64.b64decode(encrypted_key))
# Then decrypted the final value using the newly decrypted key
cipher_key = AES.new(unpad(decrypted_key,16), AES.MODE_CBC, encrypted_iv)
decrypted_value = cipher_key.decrypt(encrypted_value)
value = unpad(decrypted_value,16).decode()
print(value)
Output:
s:5:"Jimmy";
(Demo)