pythonphpencryptionphp-openssl

Decrypt a value in Python that was encrypted using PHP openssl


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)

Solution

  • 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:

    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)