Search code examples
phpencryptionencodingaes

PHP - What is expected by 'openssl_decrypt' function?


(Sorry, I'm not a native English speaker)

I have encrypted data by AES-256-ECB, I use 'openssl_decrypt' function, but I always receive a false value.

$encrypted = '86090e16c5d950a35efe801f8eb5201b';
$key = 'PasswordExample_PasswordExample_';
$text = openssl_decrypt($encrypted, 'aes-256-ecb', $key);
echo "Result: $text";

I tried with OPENSSL_RAW_DATA option, and passing $encrypted and $key with base64_encode(), but nothing worked.

A friend is sending me this encrypted text by software and I can read the answer in this site: http://aes.online-domain-tools.com/ (.:Text example:.), but I want to use PHP for an automated process.

Someone can help me? I don't think the PHP webpage has enough documentation about this function.


Update:

This test code shows my problem:

<?php

$encrypted_hex = '86090e16c5d950a35efe801f8eb5201b';
$encrypted_str = pack("H*", $encrypted_hex);
$encrypted_64 = base64_encode($encrypted_str);

echo "Encrypted (str): '$encrypted_str'<br>\n";
echo "Encrypted (hex): '$encrypted_hex'<br>\n";
echo "Encrypted (64): '$encrypted_64'<br>\n";
echo "<br>\n";

$key_str = 'PasswordExample_PasswordExample_';
$key_hex = implode(unpack("H*", $key_str));
$key_64 = base64_encode($key_str);

echo "Key (str): '$key_str'<br>\n";
echo "Key (hex): '$key_hex'<br>\n";
echo "Key (64): '$key_64'<br>\n";
echo "<br>\n";

$result_str = openssl_decrypt($encrypted_str, 'aes-256-ecb', $key_str);
$result_hex = openssl_decrypt($encrypted_hex, 'aes-256-ecb', $key_hex);
$result_64 = openssl_decrypt($encrypted_64, 'aes-256-ecb', $key_64);

echo "Result (str): '$result_str'<br>\n";
echo "Result (hex): '$result_hex'<br>\n";
echo "Result (64): '$result_64'<br>\n";
echo "<br>\n";

The generated HTML is:

Encrypted (str): '� ��P�^���� '
Encrypted (hex): '86090e16c5d950a35efe801f8eb5201b'
Encrypted (64): 'hgkOFsXZUKNe/oAfjrUgGw=='

Key (str): 'PasswordExample_PasswordExample_'
Key (hex): '50617373776f72644578616d706c655f50617373776f72644578616d706c655f'
Key (64): 'UGFzc3dvcmRFeGFtcGxlX1Bhc3N3b3JkRXhhbXBsZV8='

Result (str): ''
Result (hex): ''
Result (64): ''

If I add OPENSSL_RAW_DATA there is no change. The problem persists over Windows 10 and Ubuntu 18.04 (both with Apache 2 and PHP 7). Where is my error? Can someone show me an example of use with aes-256-ecb?


Solution

  • The decryption can be performed with:

    $result = openssl_decrypt(hex2bin($encrypted_hex), 'aes-256-ecb', $key_str, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING);
    
    • Concerning the OPENSSL_ZERO_PADDING-flag: The website uses Zero-Byte-padding, openssl_encrypt/decrypt PKCS7-padding. With the OPENSSL_ZERO_PADDING-flag the PKCS7-padding can be deactivated. Note that the OPENSSL_ZERO_PADDING-flag disables padding, it doesn't mean that Zero-Byte-padding is used (the name of the flag is somehow confusing), see openssl_encrypt, openssl at mailismagic dot com's comment. Zero-Byte-padding isn't directly supported by openssl_encrypt/decrypt, i.e. the Zero-Byte-padding must be implemented by the user. Since only decryption takes place on the PHP-side, only the un-padding (i.e. the removal of the zero-values at the end) must be done manually (which is currently missing in the PHP-code). For the current plaintext (.:Text example:.) the missing un-padding isn't noticed, because the plaintext is exactly one block (16 bytes) long, so that Zero-Byte-padding wouldn't take place during encryption (in contrast to PKCS7-padding where a complete block is appended).

    • Concerning the OPENSSL_RAW_DATA-flag: The ciphertext isn't Base64-encoded, so the OPENSSL_RAW_DATA-flag must be set. Alternatively:

      $result = openssl_decrypt(base64_encode(hex2bin($encrypted_hex)), 'aes-256-ecb', $key_str, OPENSSL_ZERO_PADDING);
      

      can be used for decryption.

    • Concerning the first parameter: Since the ciphertext is stored as hex-string, it must first be decoded (hex2bin($encrypted_hex) or pack("H*", $encrypted_hex)), as already noted in the comments.