"crypto.createCipheriv with chinese character" 的输出不正确

the output of "crypto.createCipheriv with chinese character" is not correct

当没有汉字时,php和节点输出相同的结果

但是当这是汉字时,php的输出是正确的,node的输出是不正确的

const crypto = require('crypto');
function encodeDesECB(textToEncode, keyString) {
  var key = new Buffer(keyString.substring(0, 8), 'utf8');
  var cipher = crypto.createCipheriv('des-ecb', key, '');
  cipher.setAutoPadding(true);
  var c = cipher.update(textToEncode, 'utf8', 'base64');
  c += cipher.final('base64');
  return c;
}

console.log(encodeDesECB(`{"key":"test"}`, 'MIGfMA0G'))
console.log(encodeDesECB(`{"key":"测试"}`, 'MIGfMA0G'))

node output

6RQdIBxccCUFE+cXPODJzg==
6RQdIBxccCWXTmivfit9AOfoJRziuDf4

php output

6RQdIBxccCUFE+cXPODJzg==
6RQdIBxccCXFCRVbubGaolfSr4q5iUgw

问题不在于加密,而是明文的不同 JSON 序列化。

在PHP代码中,json_encode()将字符转换为Unicode转义序列,即编码returns{"key":"\u6d4b\u8bd5"}。然而,在 NodeJS 代码中,应用了 {"key": "测试"}

这意味着最后加密的是不同的明文。因此,对于相同的密文,必须使用字节级相同的明文。


如果要在 NodeJS 代码中应用 Unicode 转义序列(如在 PHP 代码中),则需要进行适当的转换。为此,可以使用 jsesc package

const jsesc = require('jsesc');
...
console.log(encodeDesECB(jsesc(`{\"key\":\"测试\"}`, {'lowercaseHex': true}), 'MIGfMA0G')); // 6RQdIBxccCXFCRVbubGaolfSr4q5iUgw

现在 returns 发布的 PHP 代码的结果。


如果要在 PHP 代码中使用 Unicode 字符(如在 NodeJS 代码中),则需要进行适当的转换。为此,可以在 json_encode():

中设置标志 JSON_UNESCAPED_UNICODE
$data = json_encode($data, JSON_UNESCAPED_UNICODE); // 6RQdIBxccCWXTmivfit9AOfoJRziuDf4

现在 returns 发布的 NodeJS 代码的结果。