请问如何解决 Node 的 aes 加密结果和 JAVA 加密结果不一致的问题

小栀子
  • 120

测试内容:"这是一段需要加密的文字"
测试秘钥:"abcderf123456789"
对于这段文字, JAVA 和 Node.js 加密结果不一致
1、JAVA 中采用的是 AES/ECB/NoPadding 加密算法,核心加密代码如下:
`

SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(2, secretKey);
return cipher.doFinal(content)

`
JAVA 加密结果:
`

8F77C5E32AFF4351FE1A61F5C298AA93A403855F2C27D53083FB1D4F45390D0106C9C89F90F4CE42CE71929CC295DFEB

`

2、Node 使用的是 crypto 包。

核心加密算法如下:
`

let crypto = require('crypto');
function encryption(data, key) {
   var iv = "";
   var clearEncoding = 'utf8';
   var cipherEncoding = 'hex';
   var cipherChunks = [];
   var cipher = crypto.createCipheriv('aes-128-ecb', key, iv);
   cipher.setAutoPadding(true);

   cipherChunks.push(cipher.update(data, clearEncoding, cipherEncoding));
   cipherChunks.push(cipher.final(cipherEncoding));

   return cipherChunks.join('').toUpperCase();
}

`
Node 加密结果:
`

8F77C5E32AFF4351FE1A61F5C298AA93A403855F2C27D53083FB1D4F45390D01E5A5B5D6305CFB61487390A15C3BACCF

`

两者比较:
`

8F77C5E32AFF4351FE1A61F5C298AA93A403855F2C27D53083FB1D4F45390D0106C9C89F90F4CE42CE71929CC295DFEB

8F77C5E32AFF4351FE1A61F5C298AA93A403855F2C27D53083FB1D4F45390D01E5A5B5D6305CFB61487390A15C3BACCF

`
发现前面部分加密结果是一样的,后面的加密结果不一致。

在应用中需要 JAVA 端加密, Node.js 来解密,所以需要两者的结果能够对应上(JAVA 端代码不可改,需要考虑如何修改 Node 端的代码),请问如何解决这种问题呢?

补充:
有人说可以先把秘钥md5加密一遍,试过了,还是不行:
`

var md5Sign = function (data) {
   // 将字符转换成二进制流
   var str = new Buffer(data).toString('binary');
   var md5 = crypto.createHash('md5').update(str).digest('hex').slice(0, 16)
   return md5
}
   var key = md5Sign('abcderf123456789');
   var encodeStr = encryption(str, key);
  // 结果
  // 488DD42D1483C918FD0DD5D3B1FC869B647AE57ABD869A6EA9BF1864773380417C58CFFF0D1AEDFD4FC0A252A1EFAFA0
  

`

回复
阅读 2.3k
2 个回答
✓ 已被采纳

没有找到对应的java文档,不过实验结果显示,java的AES/ECB/NoPadding等同于C#中使用PaddingMode.Zeros,所以我假设java实际上用了0去补位。
而nodejs的crypto在设置setAutoPadding(true)后使用的是PKCS padding[1]
所以需要把这个设置为false然后手动补位
一下这个方法来自于 https://not.expert/nodejs-cry...

const zeropad = (inputData, length = 8) => {
  inputData = Buffer.from(inputData, "utf8").toString("hex");
  const bitLength = inputData.length * length;
  if (bitLength < 256) {
    for (i = bitLength; i < 256; i += length) {
          inputData += 0;
    }
  } else if (bitLength > 256) {
    while ((inputData.length * length) % 256 != 0) {
        inputData += 0;
    }
  }
  return Buffer.from(inputData, "hex").toString("utf8");
}

原nodejs方法修改如下

function encryption(data, key) {
  var iv = "";
  var clearEncoding = 'utf8';
  var cipherEncoding = 'hex';
  var cipherChunks = [];
  var cipher = crypto.createCipheriv('aes-128-ecb', key, iv);
  cipher.setAutoPadding(false);
  cipherChunks.push(cipher.update(zeropad(data, 8), clearEncoding, cipherEncoding));
  cipherChunks.push(cipher.final(cipherEncoding));

  return cipherChunks.join('').toUpperCase();
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏