php - 如果密码短于 16 个字符,为什么 mcrypt 和 openssl_encrypt 不能为带有 ecb 的河豚给出相同的结果?
问题描述
我已经阅读了一般建议: 不推荐使用 mcrypt,还有什么替代方案?和 PHP7.1 mcrypt 替代
并测试了以下解决方案: Migrating mcrypt with Blowfish and ECB to OpenSSL and php: mcrypt_encrypt to openssl_encrypt, and OPENSSL_ZERO_PADDING questions
他们不工作。这是我使用的代码:
$message = "My secret message";
$key = "mysecretpasswor"; // <- if you add one more character here, it's working
$iv = "\0\0\0\0\0\0\0\0";
$message_padded = $message;
if(strlen($message_padded) % 8) {
$message_padded = str_pad($message_padded, strlen($message_padded) + 8 - strlen($message_padded) % 8, "\0");
}
$encrypted_mcrypt = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $message, MCRYPT_MODE_ECB, $iv);
$encrypted_openssl = openssl_encrypt($message_padded, "bf-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);
printf("%s => %s\n", $message, base64_encode($encrypted_mcrypt));
printf("%s => %s\n", $message_padded, base64_encode($encrypted_openssl));
使用“DES-EDE3-CBC”之类的加密方法确实有效。但我无法更改使用的加密。我必须将旧代码迁移到新代码。有时会使用少于 16 个字符的键。
有什么建议么?
解决方案
首先,OPENSSL_NO_PADDING
不应该与openssl_encrypt()
. 它的文档提到OPENSSL_ZERO_PADDING
,这(令人困惑地)意味着“没有填充”。这就是你想要的。
OPENSSL_NO_PADDING
旨在与非对称加密一起使用。巧合的是,它的值为 3,等于OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
。这就是为什么您可以不正确地使用它而没有后果的原因(在这种情况下)。
您的密文是不同的,因为默认情况下模式下的函数将openssl_encrypt()
在密钥长度小于 16 个字节bf-ecb
时用 's 填充您的密钥。\0
河豚mcrypt_encrypt()
不需要这样做,也不会这样做。为了关闭该行为,请OPENSSL_DONT_ZERO_PAD_KEY
在调用时使用该标志openssl_encrypt()
。由于这个标志似乎没有被记录,你将不得不去源代码来了解它:-)。或阅读错误 #72362 OpenSSL Blowfish 加密对于短密钥不正确。
有了这个,正确的调用openssl_encrypt()
变为:
$opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING | OPENSSL_DONT_ZERO_PAD_KEY;
$encrypted_openssl = openssl_encrypt($message_padded, "bf-ecb", $key, $opts);
测试它:
$ php bf.php
My secret message => JPO/tvAqFD2KCTqfv0l8uWLfPUWdZIxQ
My secret message => JPO/tvAqFD2KCTqfv0l8uWLfPUWdZIxQ
推荐阅读
- javascript - 我如何获得价值以在 discord.js 中作为消息发布
- c - 使用 gdb 调试 stm32 nucleo
- google-maps - 带有谷歌地图 API TypeError 的 VueJs:将循环结构转换为 JSON
- django - 以 10 为底的 int() 的无效文字是什么:'startTime'
- c# - 在 .NetCore 控制台应用程序中使用 Nlog 和 ILoggerFactory 时未打印调试和跟踪日志
- vba - 访问变量引用的另一种形式的 VBA 编辑文本框
- html - 为什么我使用 table-cell css 样式的页面在相同的宽度比率下显示不同的 div 宽度?
- android - 如何在 findNavController().navigate() 中发送带有方向的导航器附加信息
- asp.net-core - Serilog - can not log to multiple files based on property
- javascript - 遍历并删除对象数组中的元素