我试图使用crypto javascript库加密数据,并试图使用节点密码库在nodejs端解密相同的加密文本。我使用AES 256加密algo与CTR模式,没有填充。我能够正确地加密,但是nodejs密码模块上的描述并不能产生相同的纯文本。
如果我试图使用相同的密码-js和节点密码库加密或解密,它可以正常工作,但加密对加密js和对密码的描述并不像预期的那样工作。我试着确认我是否在同一个库中加密和解密,而不是它是否工作,而且它运行得非常好。有人能检查一下我在这里犯了什么错误吗?
请找到下面的代码样本。
加密:
var key = CryptoJS.enc.Hex.parse('F29BA22B55F9B229CC9C250E11FD4384');
var iv = CryptoJS.enc.Hex.parse('C160C947CD9FC273');
function encrypt(plainText) {
return CryptoJS.AES.encrypt(
plainText,
key,
{
iv: iv,
padding: CryptoJS.pad.NoPadding,
mode: CryptoJS.mode.CTR
}
);
}使用NodeJS加密模块的解密码:
var algorithm = 'aes-256-ctr';
var key = 'F29BA22B55F9B229CC9C250E11FD4384';
var iv = 'C160C947CD9FC273';
var outputEncoding = 'hex';
var inputEncoding = 'hex';
const decipher = crypto.createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update('8df5e11f521cf492437a95', inputEncoding, 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);正如我前面提到的,如果我使用相同的lib加密和解密,JavaScript密码-js和NodeJS密码模块会话就可以正常工作,但否则就不能工作。请检查工作代码如下。
JavaScript:R/2 qwt8jsh/2/
发布于 2019-09-13 20:19:52
与NodeJS (Crypto)不同,JavaScript (CryptoJS)将键和IV解释为十六进制字符串。因此,在JavaScript-128和NodeJS 256中使用.为了解决这个问题,这两个代码必须使用相同的加密。
选项1:将JavaScript代码更改为AES-256:在JavaScript代码中替换
var key = CryptoJS.enc.Hex.parse('F18AB33A57F9B229CC9C250D00FC3273');
var iv = CryptoJS.enc.Hex.parse('D959B836CD9FB162');通过
var key = CryptoJS.enc.Utf8.parse('F18AB33A57F9B229CC9C250D00FC3273');
var iv = CryptoJS.enc.Utf8.parse('D959B836CD9FB162');选项2:将NodeJS-代码更改为AES-128:在NodeJS-代码中替换
var algorithm = 'aes-256-ctr';
var key = 'F18AB33A57F9B229CC9C250D00FC3273';
var iv = 'D959B836CD9FB162';通过
var algorithm = 'aes-128-ctr';
var key = Buffer.from('F18AB33A57F9B229CC9C250D00FC3273', 'hex');
var iv = Buffer.from('D959B836CD9FB1620000000000000000', 'hex');通过两个变化中的每一个,两个链接的代码产生相同的结果。
如果应该使用AES-256,并将key和IV指定为十六进制字符串,则必须使用相应的大键和大键,例如在JavaScript端:
var key = CryptoJS.enc.Hex.parse('F18AB33A57F9B229CC9C250D00FC3273F18AB33A57F9B229CC9C250D00FC3273');
var iv = CryptoJS.enc.Hex.parse('D959B836CD9FB16200000000000000'); 在NodeJS方面:
var algorithm = 'aes-256-ctr';
var key = Buffer.from('F18AB33A57F9B229CC9C250D00FC3273F18AB33A57F9B229CC9C250D00FC3273', 'hex');
var iv = Buffer.from('D959B836CD9FB1620000000000000000', 'hex');发布于 2019-09-13 21:26:44
我认为您的CryptoJS代码没有使用AES-256,因为键和IV太短,因此它隐含地使用AES-128。如果您从blockSize对象获得CryptoJS.AES,它为我指定了4。这就是说,我对CryptoJS不太了解,这可能并不意味着“四个字”。
为了避免这种实现的不确定性,最好有一个“金本位”来复制。NIST提供了大量的测试向量,其中一些应用于您的CTR模式AES-256。首先,我从该文档中提取一组(十六进制编码的)测试向量:
const key = (
'603deb1015ca71be2b73aef0857d7781' +
'1f352c073b6108d72d9810a30914dff4'
)
const ctr = 'f0f1f2f3f4f5f6f7f8f9fafbfcfdff00'
const output = '5a6e699d536119065433863c8f657b94'
const cipher = 'f443e3ca4d62b59aca84e990cacaf5c5'
const plain = 'ae2d8a571e03ac9c9eb76fac45af8e51'接下来,我尝试从模块中恢复这些
const crypto = require('crypto')
function node_crypto(text) {
const dec = crypto.createDecipheriv(
'aes-256-ctr',
Buffer.from(key, 'hex'),
Buffer.from(ctr, 'hex')
);
const out = dec.update(Buffer.from(text, 'hex'))
return out.toString('hex')
}现在,我可以编写一个简单的测试工具来测试上面的内容,并将它与该函数一起使用:
const zero = '00'.repeat(16);
function test_crypto(fn) {
return {
'zero => output': fn(zero) == output,
'cipher => plain': fn(cipher) == plain,
'plain => cipher': fn(plain) == cipher,
}
}
console.log(test_crypto(node_crypto))这给了我所有测试的true。
最后,CryptoJS的等效代码是:
const CryptoJS = require("crypto-js");
function cryptojs(text) {
const out = CryptoJS.AES.encrypt(
CryptoJS.enc.Latin1.parse(Buffer.from(text, 'hex').toString('binary')),
CryptoJS.enc.Hex.parse(key),
{
iv: CryptoJS.enc.Hex.parse(ctr),
mode: CryptoJS.mode.CTR,
padding: CryptoJS.pad.NoPadding,
}
);
return out.ciphertext.toString();
}
console.log(test_crypto(cryptojs))这对我也有用。
需要注意的是,CryptoJS只是默默地接受任意大小的键,文档中这样说:
CryptoJS支持AES-128、AES-192和AES-256.它将根据您传入的键的大小来选择变体。如果您使用密码,那么它将生成一个256位的密钥.
https://stackoverflow.com/questions/57929210
复制相似问题