【问题标题】:Encryption with AES-128-CTR giving different results on PHP (openssl_encrypt) vs Node.js (crypto)使用 AES-128-CTR 加密在 PHP (openssl_encrypt) 与 Node.js (crypto) 上给出不同的结果
【发布时间】:2019-02-22 12:02:05
【问题描述】:

我有一个 API,要求我对通过 AES 密码发送给它的数据进行编码。

但是,我得到的唯一示例代码是 Node.js 代码。

我想,用 PHP 重新实现它有多难?

显然很难。

您可以在下面看到这两种方法,但您也可以看到不同的结果。

有人知道可能出了什么问题吗?

NODE.js 版本

var crypto = require('crypto');
var algorithm = 'aes-128-ctr';

function encrypt(text, password) {
  const key = Buffer.from(password, "hex").slice(0, 16);
  const ivBuffer = Buffer.alloc(16);
  const cipher = crypto.createCipheriv(algorithm, key, ivBuffer);
  let crypted = cipher.update(text, "utf8", 'hex');
  crypted += cipher.final('hex');
  console.log(crypted);
}

encrypt('test','ed8f68b144f94c30b8add43276f0fa14');

结果:3522ca23

PHP 版本

function encrypt($text, $password) {
  $iv = "0000000000000000";
  $encrypted = openssl_encrypt($text, 'aes-128-ctr', $password, OPENSSL_RAW_DATA, $iv);
  return bin2hex($encrypted);
}

echo encrypt('test', 'ed8f68b144f94c30b8add43276f0fa14');

结果:8faa39d2

【问题讨论】:

  • 您使用不同的密钥和 IV。在 PHP 中,您不是对密钥进行十六进制解码,因此它是一个 32 字节的 a-f0-9 字符串。此外,您在 PHP 中的 IV 是 16 个零字符,而不是 16 个零字节。
  • 在浏览相关部分时,我已经遇到了一个似乎符合您逻辑的解决方案。还是谢谢你的回复!!
  • 没问题!你知道,你可以发布一个答案,如果你认为它可能对其他人有用。
  • 我刚刚做了,请随意看看我是否正确理解了我的错误所在:)

标签: php node.js encryption aes


【解决方案1】:

在浏览相关部分时(在我的帖子之后),我遇到了这个: C# and PHP have different AES encryption results

正如上面t-m-adam 所提到的,显然我需要在两个示例中对齐iv 和密码。在 PHP 中,我的 iv 和密码是“常规”字符串,它们应该是与密码块大小相同长度的二进制字符串。我的 iv 应该(在我的情况下)是 16 个零字节而不是 16x 0 字符。您可以通过回显以下代码来查看差异:

$iv = "00000000000000000000000000000000";
echo $iv;
echo strlen($iv);

$iv = pack("H*", "00000000000000000000000000000000");
echo $iv;
echo strlen($iv);

两个 $iv 变量的长度都是 16(按照 AES 的要求),但第二个版本由 0 字节组成,实际上是不可打印的。

事不宜迟,最终结果,在 PHP 中工作:

function encrypt($text, $password) {
  $iv = pack("H*", "00000000000000000000000000000000");
  $password = pack("H*", $password);
  $encrypted = openssl_encrypt($text, 'aes-128-ctr', $inputKey, OPENSSL_RAW_DATA, $iv);
   return bin2hex($encrypted);
}

echo encrypt('test', 'ed8f68b144f94c30b8add43276f0fa14');

结果:3522ca23

成功!!

【讨论】:

  • 太棒了!如果您需要一些建议,您可以使用随机 IV 和AEAD 算法来改进您的加密。我最近使用 GCM 回答了一个类似的问题。如果你愿意,你可以找到它here
  • 我必须将其传递给实现 API 的人员(另一家公司)。根据我从您的示例(和我的直觉)中收集到的信息,这意味着我们必须发送用于加密数据本身的加密的 $iv,以便能够对其进行解密,对吗?随机 $iv 的目的是不那么“可破解”,就像一种盐?
  • 是的,IV 必须是不可预测的,但它不一定是秘密的,您可以将其与密文一起发送(如果您选择使用经过身份验证的加密,则标记)。我找不到任何来源,但我认为当 IV 被重复使用时,CTR 很容易受到攻击。
  • 好的,我找到了一篇关于 CTR 的 RFC3686 论文。请参阅section 3.1 了解 IV 和 section 7 了解安全性。
猜你喜欢
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
  • 2017-03-17
  • 2012-10-29
  • 1970-01-01
相关资源
最近更新 更多