Node.js 为什么CryptoJS和节点内置加密模块使用相同的AES算法和相同的密钥加密结果不同

Node.js 为什么CryptoJS和节点内置加密模块使用相同的AES算法和相同的密钥加密结果不同,node.js,encryption,cryptojs,Node.js,Encryption,Cryptojs,我用Node.js开发服务器,用Ionic框架开发客户端 我为客户端的登录请求制作了API 当客户端请求登录时,发送加密的id和密码字符串 服务器解密接收到的id和密码字符串并检查验证 我使用crypto-js()库进行客户端加密 下面是客户端加密代码 var secret = 'abcdefghijklmnopqrstuvwxyz123456'; var id = "someId"; var encrypted = CryptoJS.AES.encrypt(id, password); con

我用Node.js开发服务器,用Ionic框架开发客户端

我为客户端的登录请求制作了API

当客户端请求登录时,发送加密的id和密码字符串

服务器解密接收到的id和密码字符串并检查验证

我使用crypto-js()库进行客户端加密

下面是客户端加密代码

var secret = 'abcdefghijklmnopqrstuvwxyz123456';
var id = "someId";
var encrypted = CryptoJS.AES.encrypt(id, password);
console.log(encrypted.toString());  // U2FsdGVkX19EfjjBwydSZL509wKl5TEX+4f3vakEejU=
对于服务器端解密,我使用了节点内置的加密模块

const crypto = require('crypto');
var method = 'aes256';
var secret = 'abcdefghijklmnopqrstuvwxyz123456';
var id = "U2FsdGVkX19EfjjBwydSZL509wKl5TEX+4f3vakEejU=" // suppose we received with no loss
var decipher = crypto.createDecipher(method, secret);
decipher.update(id,'base64','utf8');
var deciphered = decipher.final('utf8');
console.log(deciphered);
服务器端解密代码崩溃,错误消息如下

crypto.js:153
  var ret = this._handle.final();
                         ^

Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
    at Error (native)
    at Decipher.Cipher.final (crypto.js:153:26)
    at Object.<anonymous> (...\routes\index.js:33:27)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (...\app.js:18:14)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
[加密模块]

const crypto = require('crypto');
var method = 'aes256';
var secret = 'abcdefghijklmnopqrstuvwxyz123456';
var id = "someId" 
var cipher= crypto.createCipher(method, secret);
cipher.update(id,'base64','utf8');
var ciphered = decipher.final('utf8');
console.log(ciphered.toString()); // WAsd61C2bfG7UbO5STo13A==
我发现图书馆的结果不一样

plain text : 'someId'
crpyto-js  : 'U2FsdGVkX19EfjjBwydSZL509wKl5TEX+4f3vakEejU='
crpyto module : 'WAsd61C2bfG7UbO5STo13A=='
我试图理解每个库的源代码

但是太复杂了,所以我无法理解


我想知道每个库的encrytion是如何工作的,以及是什么导致不同的结果

您使用的是两个不同的系统,它们可能具有不同的默认值。不要依赖默认值,而是显式地指定两侧的所有内容都相同。加密设计为即使最小的东西不匹配也会失败。您需要指定使用的字符到字节映射、加密模式、IV(如果需要)、密钥和填充方法

您的不同输出具有不同的长度,因此最初我怀疑填充是第一件要考虑的事情。将两侧设置为PKCS#7填充,看看是否有帮助


为了进一步诊断,请检查钥匙和IV的每侧是否都是相同的。

您使用的是两个不同的系统,它们可能具有不同的默认值。不要依赖默认值,而是显式地指定两侧的所有内容都相同。加密设计为即使最小的东西不匹配也会失败。您需要指定使用的字符到字节映射、加密模式、IV(如果需要)、密钥和填充方法

您的不同输出具有不同的长度,因此最初我怀疑填充是第一件要考虑的事情。将两侧设置为PKCS#7填充,看看是否有帮助


为了进一步诊断,请检查钥匙和IV是否在每一侧都是相同的。

所有参数必须指定并正确。不要依赖默认值,它们依赖于实现,并且在实现之间会非常复杂

一般来说,您应该使用:

  • CBC模式使用随机iv,在加密时创建随机iv,将其预先添加到加密数据以用于解密。对于AES,iv应为16字节,即块大小。不要使用ECB模式,这是不安全的,请参阅,向下滚动到企鹅模式

  • PKCS#7填充(有时称为PKCS#5)。这是必需的,因为AES是一种分组密码,输入和输出必须是块大小的精确倍数。此填充将在加密期间自动添加,并在解密期间删除

  • 确保iv和钥匙的大小正确

  • 对于调试,以十六进制显示所有输入和输出。在调试期间,在加密和解密之前和之后转储所有输入和输出可能会有所帮助。十六进制允许查看每个字节,Base64将3个字节合并为4个字节,使其更难理解


  • 当所有这些都完全相同时,输出也将完全相同。

    必须指定并更正所有参数。不要依赖默认值,它们依赖于实现,并且在实现之间会非常复杂

    一般来说,您应该使用:

  • CBC模式使用随机iv,在加密时创建随机iv,将其预先添加到加密数据以用于解密。对于AES,iv应为16字节,即块大小。不要使用ECB模式,这是不安全的,请参阅,向下滚动到企鹅模式

  • PKCS#7填充(有时称为PKCS#5)。这是必需的,因为AES是一种分组密码,输入和输出必须是块大小的精确倍数。此填充将在加密期间自动添加,并在解密期间删除

  • 确保iv和钥匙的大小正确

  • 对于调试,以十六进制显示所有输入和输出。在调试期间,在加密和解密之前和之后转储所有输入和输出可能会有所帮助。十六进制允许查看每个字节,Base64将3个字节合并为4个字节,使其更难理解


  • 当所有这些都完全相同时,输出也将完全相同。

    我的这两个答案处理两个方向:并且您没有使用有效的AES密钥,因此两个系统都试图使其长度正确,显然策略不同。@dandavis这正是区别所在。两者都不使用任何密钥,但它们假定传递的“密钥”是密码,然后从密码派生出实际密钥。唯一的区别是CryptoJS使用随机salt,而node.js不使用。这就是我第一个链接背后的答案。遗憾的是,我不能提出一个重复的答案。我的这两个答案处理两个方向:你没有使用有效的AES密钥,所以两个系统都试图使其长度正确,显然策略不同。@dandavis这正是区别所在。两者都不使用任何密钥,但它们假定传递的“密钥”是密码,然后从密码派生出实际密钥。唯一的区别是CryptoJS使用随机salt,而node.js不使用。这就是我第一个链接背后的答案。遗憾的是,我不能提出复制品。
    plain text : 'someId'
    crpyto-js  : 'U2FsdGVkX19EfjjBwydSZL509wKl5TEX+4f3vakEejU='
    crpyto module : 'WAsd61C2bfG7UbO5STo13A=='