PHP 7.2准备移除Mcrypt,该如何准备?

8
随着时间的推移,mcrypt将被PHP 7.2废弃。当然还有一个替代方案:openssl。
我发现很难从mcrypt切换到openssl,并使用AES 256 CBC来保留IVs。我在密码学方面比较新,所以不是很懂,但我了解基础知识。
假设我有以下代码:
function encrypt($masterPassword, $data) 
{
    $keySize = mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
    $ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
    $iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
    $key = mb_substr(hash('SHA256', $masterPassword), 0, $keySize);
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);
    return base64_encode($iv . $encrypted);
}

function decrypt($masterPassword, $base64) 
{
    $keySize = mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
    $ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
    $key = mb_substr(hash('SHA256', $masterPassword), 0, $keySize);
    $data = base64_decode($base64);
    $iv = substr($data, 0, $ivSize);
    $encrypted = substr($data, $ivSize, strlen($data));
    $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CBC, $iv);
    return trim($decrypted);
}

我应该如何“转换”这段代码,以使用openssl替代mcrypt?

1个回答

12
由于Rijndael-256不是AES-256,且OpenSSL扩展程序不支持Rijndael-256,因此您无法进行转换。
AES-256是具有256位(32字节)密钥的Rijndael-128。
不幸的是,您必须重新加密所有数据。
编辑:此外,您当前使用的方案存在一些问题:
  • 缺少身份验证(在PHP中使用HMACs是最简单的方法)
  • 缺少适当的填充(mcrypt用零字节填充;您需要类似于PKCS#5填充的内容),这对于块模式加密是安全的是必要的。
  • 它不是字节安全的(您正在使用mb_substr()
好消息是,OpenSSL会自动为您执行PKCS#5填充,但您应该更进一步并使用像defuse/php-encryption这样的可靠加密库。

感谢您提供的小型安全建议。我现在将我的Web应用程序移植到defuse/php-encryption。 - Scrumplex
您可以通过使用空值填充到块大小来使它们兼容。我总是将mcrypt迁移到openssl,并且保留已加密的数据始终是一个要求。 - afilina
虽然不是首选,但这对于从mcrypt Rijndael-128到openssl AES的转换可以起作用,但对于Rijndael-256则不行。 - Narf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接