Encryption on crypto-js and decryption on node crypto using CTR mode issue
我正在尝试使用crypto-js javascript库对数据进行加密,并尝试使用node crypto库在nodejs端解密相同的加密文本。我正在CTR模式下使用无填充的AES 256加密算法。我能够正确加密,但是对nodejs crypto模块的描述未生成相同的纯文本。
如果我尝试使用相同的crypto-js和节点crypto库进行加密或解密,则可以正常工作,但是对crypto-js进行加密和对crypto的描述无法正常工作。我试图确认是否在同一个库中对它进行加密和解密,而不是正常工作,并且效果很好。有人可以检查我在这里犯什么错误吗?
请找到以下代码示例。
加密:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 crypo模块解密:
1 2 3 4 5 6 7 8 9 10 11 12 | 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); |
如前所述,如果我使用相同的库进行加密和解密,那么我的JavaScript crypo-js和NodeJS crypo模块会话可以正常工作,但不能正常工作。请检查以下工作代码。
JavaScript:http://jsfiddle.net/usr_r/2qwt8jsh/2/
NodeJS:https://repl.it/repls/AchingRegalPhp
我认为您的CryptoJS代码未使用AES-256,因为密钥和IV太短,因此隐式使用了AES-128。如果从
为了绕过这种实现的不确定性,最好复制一个"黄金标准"。 NIST提供了许多测试矢量,其中一些适用于CTR模式AES-256。首先,我从该文档中提取了一组(十六进制编码的)测试向量:
1 2 3 4 5 6 7 8 9 | const key = ( '603deb1015ca71be2b73aef0857d7781' + '1f352c073b6108d72d9810a30914dff4' ) const ctr = 'f0f1f2f3f4f5f6f7f8f9fafbfcfdff00' const output = '5a6e699d536119065433863c8f657b94' const cipher = 'f443e3ca4d62b59aca84e990cacaf5c5' const plain = 'ae2d8a571e03ac9c9eb76fac45af8e51' |
接下来,我尝试从Node的
1 2 3 4 5 6 7 8 9 10 11 | 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') } |
现在,我可以编写一个简单的测试工具来测试上述内容,并将其与该功能配合使用:
1 2 3 4 5 6 7 8 9 10 | 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)) |
这使我在所有测试中均
最后,CryptoJS的等效代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key.
与NodeJS代码(
选项1:将JavaScript代码更改为AES-256:替换为JavaScript代码
1 2 | var key = CryptoJS.enc.Hex.parse('F18AB33A57F9B229CC9C250D00FC3273'); var iv = CryptoJS.enc.Hex.parse('D959B836CD9FB162'); |
通过
1 2 | var key = CryptoJS.enc.Utf8.parse('F18AB33A57F9B229CC9C250D00FC3273'); var iv = CryptoJS.enc.Utf8.parse('D959B836CD9FB162'); |
选项2:将NodeJS代码更改为AES-128:替换为NodeJS代码
1 2 3 | var algorithm = 'aes-256-ctr'; var key = 'F18AB33A57F9B229CC9C250D00FC3273'; var iv = 'D959B836CD9FB162'; |
通过
1 2 3 | var algorithm = 'aes-128-ctr'; var key = Buffer.from('F18AB33A57F9B229CC9C250D00FC3273', 'hex'); var iv = Buffer.from('D959B836CD9FB1620000000000000000', 'hex'); |
使用两个更改中的每个更改,两个链接的代码将产生相同的结果。
如果应使用AES-256并且密钥和IV应指定为十六进制字符串,则必须使用相应的较大密钥和IV,例如在JavaScript方面:
1 2 | var key = CryptoJS.enc.Hex.parse('F18AB33A57F9B229CC9C250D00FC3273F18AB33A57F9B229CC9C250D00FC3273'); var iv = CryptoJS.enc.Hex.parse('D959B836CD9FB16200000000000000'); |
在NodeJS端:
1 2 3 | var algorithm = 'aes-256-ctr'; var key = Buffer.from('F18AB33A57F9B229CC9C250D00FC3273F18AB33A57F9B229CC9C250D00FC3273', 'hex'); var iv = Buffer.from('D959B836CD9FB1620000000000000000', 'hex'); |