使用MCRYPT_RIJNDAEL_256替换mcrypt_encrypt和openssl_encrypt

问题描述 投票:7回答:3

你们可能知道,扩展名mcrypt将在php 7.1上弃用。

我用来维护一个“遗留”应用程序,我想最终迁移到这个版本,所以我运行测试并验证我不能再获得100%的覆盖率,因为有一段代码使用以下代码:

$key = 'sA*(DH';

// initialization vector
$iv = md5(md5($key));
$output = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string,     MCRYPT_MODE_CBC, $iv));

我试图使用此代码将此段代码移植到openssl_encrypt

$key = md5('sA*(DH');
$iv = md5($key);
echo base64_encode(openssl_encrypt($data, "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv));

但我有两个问题:

  1. IV长度应该是16个字符(而md5给我32个),所以我得到一个PHP警告
  2. 它的输出不一样(即使我截断为16个字符)

任何人都有类似的问题(或知道如何解决它?)

顺便说一句:我正在使用PHP的开发大师版本(假设是7.1.0 alpha 3)。

php mcrypt php-openssl
3个回答
1
投票

你真的应该放弃使用md5做任何事情的习惯。

$iv = openssl_random_pseudo_bytes(16);
$key = substr(hash('sha256', 'sA*(DH'), 0, 32)

给定相同的明文和密钥,mcrypt_encryptopenssl_encrypt不会输出相同的密码。

此外,mcrypt在PHP 7.1中已弃用,未被删除...因此您可以更新到7.1而无需从mcrypt更改为openssl ...但一般来说删除mcrypt是个好主意。


0
投票

有两个问题:

  1. MCrypt使用零填充,而Openssl默认使用PKCS#7
  2. Openssl需要输入字符串具有适当的长度(块长度的倍数)

要解决这个问题:

  1. 将OPENSSL_ZERO_PADDING标志添加到openssl_encrypt / openssl_decrypt
  2. 如果输入字符串长度不是块长度的倍数,则附加到输入字符串零字符“\ 0”[aka chr(0)];

话虽如此,这应该解决问题:

// key/iv in ASCII binary data, $str base64
function decrypt_stuff($key, $str, $iv) {
    // $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($str), MCRYPT_MODE_CBC, $iv);
    $plaintext_dec = openssl_decrypt(base64_decode($str), "aes-256-cbc", $key,  OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
    return $plaintext_dec;
}

// key/iv in ascii binary data, $str ascii
function encrypt_stuff($key, $str, $iv) {
    // $ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_CBC, $iv));
    if (($l = (strlen($str) & 15)) > 0) { $str .= str_repeat(chr(0), 16 - $l); }
    $ciphertext = base64_encode(openssl_encrypt($str, "aes-256-cbc", $key,  OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv));
    return $ciphertext;
}

0
投票

另一个测试解决方案采用并返回ANSI文本以使用openssl_encrypt()和openssl_decrypt()替换Mcrypt函数:

//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;
}

更多阅读openssl documentation

© www.soinside.com 2019 - 2024. All rights reserved.