使用AES-128-CTR加密在PHP(openssl_encrypt)和Node.js(crypto)上给出了不同的结果

时间:2018-09-18 12:37:26

标签: php node.js encryption aes

我有一个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

1 个答案:

答案 0 :(得分:1)

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

也如上面t-m-adam所述,显然我需要在两个示例中对齐iv和密码。在PHP中,我的iv和密码是“常规”字符串,在这里,它们应该是长度与密码的块大小相同的二进制字符串。我的iv应该是16个零字节,而不是16个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

成功!!!