Reputation: 1568
I'm trying to use PHP's openssl_encrypt()
function but my key is coded in hexadecimal and the function is returning an error. When using the hex2bin()
function to convert the key to binary, the return value is garbled ASCII text. Then when inserted into openssl_encrypt()
. I get an error.
define('TEX_ENCRYPTION_KEY', 'hexadecimalkey...');
define('TEX_ENCRYPTION_IV', 'hexadecimalkey...');
$key = hex2bin(TEX_ENCRYPTION_KEY);
$iv = hex2bin(TEX_ENCRYPTION_IV);
$transData = '<Detail>blah blah blah</Detail>';
$alg = 'aes-256-cbc';
$encryptedData = openssl_encrypt(
$transData,
$alg,
$key,
OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING,$iv
);
This outputs an error:
error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data
not multiple of block length
Any idea what is going on here?
Upvotes: 1
Views: 679
Reputation: 21757
After dancing with the openssl documentation I had the solution to replace depreciated Mcrypt function with openssl (openssl_encrypt and openssl_decrypt functions) and return ASCII text with base64_encode():
//Return encrypted string
public function stringEncrypt ($plainText, $cryptKey = '7R7zX2Urc7qvjhkr') {
$length = 8;
$cstrong = true;
$cipher = 'aes-128-cbc';
if (in_array($cipher, openssl_get_cipher_methods()))
{
$ivlen = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt(
$plainText, $cipher, $cryptKey, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $cryptKey, $as_binary=true);
$encodedText = base64_encode( $iv.$hmac.$ciphertext_raw );
}
return $encodedText;
}
//Return decrypted string
public function stringDecrypt ($encodedText, $cryptKey = '7R7zX2Urc7qvjhkr') {
$c = base64_decode($encodedText);
$cipher = 'aes-128-cbc';
if (in_array($cipher, openssl_get_cipher_methods()))
{
$ivlen = openssl_cipher_iv_length($cipher);
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ivlenSha2len = $ivlen+$sha2len;
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$plainText = openssl_decrypt(
$ciphertext_raw, $cipher, $cryptKey, $options=OPENSSL_RAW_DATA, $iv);
}
return $plainText;
}
Upvotes: 1
Reputation: 42699
Though it's not in the official documentation, there's a pretty good explanation of what the OPENSSL_ZERO_PADDING
option does in the comments. By default, OpenSSL will pad your plaintext to a multiple of the cipher block size (16 bytes in the case of AES-256-CBC.) However, you've disabled that mechanism and OpenSSL is expecting you to ensure the length of your data is a multiple of 16. It's not, so you get the error message "data not multiple of block length."
Solution: pad your data or remove that option!
<?php
$transData = '<Detail>blah blah blah</Detail>';
$transData = str_pad(
$transData,
strlen($transData) + (16 - (strlen($transData) % 16)),
chr(0)
);
Upvotes: 1