Convert mcrypt AESencrypt function to openssl but not working

125 views Asked by At

Here is my older code run perfectly in PHP 5.6

function AESencrypt($decrypted, $password, $salt) 
{ 
  $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
  $padding = $block - (strlen($decrypted) % $block);
  $decrypted .= str_repeat(chr($padding), $padding);
  $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $password, $decrypted , MCRYPT_MODE_CBC, $password));
  $encrypted = hash('SHA256', $encrypted.'|'.$salt, true);
  return strToHex($encrypted);
}

$hashkey= AESencrypt("input","password", "salt");

then I switched to PHP 7.4, but the function is not working so I tried to convert it into OpenSSL but it does not produce valid hash key

New code is here

function AESencrypt($decrypted, $password, $salt) 
{ 
  $padding = 16 - (strlen($salt) % 16);
  $salt .= str_repeat("\0", $padding);
  
  $block = 16;
  $padding = $block - (strlen($decrypted) % $block);
  $decrypted .= str_repeat(chr($padding), $padding);

  $cipher = (mb_strlen($password, '8bit') <= 8) ? 'aes-128-cbc' : 'aes-256-cbc';

  $encrypted = base64_encode(
    openssl_encrypt($decrypted, $cipher, $password, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $password)
  );

  $encrypted = hash('SHA256', $encrypted.'|'.$salt, true);
  return strToHex($encrypted);
}

$hashkey = AESencrypt("input","password", "salt");

strToHex() is here

function strToHex($string){
  $hex = '';
  for ($i=0; $i<strlen($string); $i++){
    $ord = ord($string[$i]);
    $hexCode = dechex($ord);
    $hex .= substr('0'.$hexCode, -2);
  }
  return strToUpper($hex);
}

I have tried solutions given in the previous question but it still shows invalid hash key

1

There are 1 answers

0
Topaco On

In the old code, the salt isn't padded and the design is for AES-128, i.e. for a 16 bytes key. If in the new code the padding of the salt is removed, no AES-256 is used for keys larger than 8 (?!) bytes and a 16 bytes key is applied, the results are identical.

In addition, the new code can be written more compactly by:

  • using the implicit PKCS#7 padding instead of the explicit padding (remove OPENSSL_NO_PADDING)
  • using the implicit Base64 encoding instead of the explicit encoding (remove OPENSSL_RAW_DATA)
  • using the built-in function bin2hex() instead of the custom function strToHex(). But even this can be avoided, since hash() returns the result hex encoded by default:
function AESencrypt($decrypted, $password, $salt)  
{ 
  $encrypted = openssl_encrypt($decrypted, 'aes-128-cbc', $password, 0, $password);
  $hash = hash('SHA256', $encrypted . '|' . $salt);
  return strToUpper($hash);
}

$result = AESencrypt("The quick brown fox jumps over the lazy dog", "0123456789abcdef", "01234567");
print($result . PHP_EOL); // 7A8D13F38E4A63F821A75FAA8C7B879C7BCC99B34102BAA731015735F5F5EAD3

The purpose of the method is not clear. The final hashing makes the processing irreversible, i.e. decryption is not possible. Perhaps a key derivation is to be implemented with this. However, there are more proven methods for this, e.g. Argon2 (password-based) or HKDF (key-based).