用CryptoJS解密openssl AES
我试图使用CryptoJS 3.1.5解密用opensslencryption的文件。
一切工作正常,如果我使用CryptoJSencryption和解密,壳在OpenSSL一样,但是当我尝试混合CryptoJS与OpenSSL一切都出错了。
该文件是使用以下命令创build的:
openssl enc -aes-256-cbc -in file.txt -out file.enc -k password
我试图解密这样的:
fs.readFile('file.enc', function(err, data) { var decrypted = CryptoJS.AES.decrypt( data.toString(), "password", { mode : CryptoJS.mode.CBC } ); console.log(decrypted.toString(CryptoJS.enc.Utf8)); }); // Give me this err: Uncaught Error: Malformed UTF-8 data
而另一方面,我也这样做:
fs.readFile('file.txt', function(err, data) { var encrypted = CryptoJS.AES.encrypt( data.toString(), "password", { mode : CryptoJS.mode.CBC }); fs.writeFile('file.enc', encrypted); });
然后在Shell:
openssl enc -d -aes-256-cbc -in file.enc -out file2.txt -k password // Give me this err: bad magic number
我错过了什么明显的?
不是绝对的答案,但太多的意见:
Commandline openssl enc
默认使用带有salt的基于密码的encryption(PBE),这意味着实际的encryption密钥,以及适用于CBC的IV,可以从给定的密码和随机盐值通过基于密码的密钥推导来计算使对手更难以尝试猜测密码的function。 我不知道你的JS模块(或多lessJS),但你链接的网页列出了各种低级原语,暗示它不会自动执行PBE。 像“password”这样的文本string(可能)适用于PBE,但不能直接进行AESencryption,其中密钥必须是128,192或256位,并且应该是随机二进制数据。
如果你想openssl的半标准PBE ,在JS端匹配; evpkey
项目听起来可能有帮助,因为EVP
是openssl模块,我不知道其他(PB)KDFscheme将被称为EVP。 如果没有,那么默认的PBE就是密码的MD5,与salt连接,根据需要迭代多次,在这种情况下是三次。 有关(主要)perl中的示例,请参阅https://superuser.com/questions/455463/openssl-hash-function-for-generating-aes-key 。 OpenSSL将8个ASCII字符“Salted__”和8个字节的盐加到文件中,所以你需要在解密之前删除那些(和使用salt),或者在encryption之后添加它们。
如果你想要原始的encryption ,select一个更合适的密钥(在任何一边),以及一个独特和不可预知的IV,除非你总是使用一个新的密钥,在这种情况下,你可以使用一个固定的IV,并在openssl方使用-K
大写)和-iv
以hex指定这些值。 请参阅安装了openssl的任何Unix系统上的manpage或https://www.openssl.org/docs/manmaster/apps/enc.html 。
另外,无论哪种情况, enc
默认为“PKCS#5”(真正的PKCS#7) 填充 。 我不知道你的JS模块是不是 如果没有,你应该指定它。 除非你能保证你的明文永远是16字节的精确倍数(经过UTF8编码之后); 那么你可以在JS端指定(或者默认)没有填充,并在openssl端指定-nopad
。
为了logging,这是我如何解密openssl文件。
//openssl enc -aes-256-cbc -in file.txt -out file.enc -k password fs.readFile('file.enc', function(err, data) { var salt = data.toString("hex", 8, 16), enc = data.toString("hex", 16, data.length), derivedParams = CryptoJS.kdf.OpenSSL.execute( password, 256/32, 128/32, CryptoJS.enc.Hex.parse(salt) ), cipherParams = CryptoJS.lib.CipherParams.create({ ciphertext : CryptoJS.enc.Hex.parse(enc) }), decrypted = CryptoJS.AES.decrypt( cipherParams, derivedParams.key, { iv : derivedParams.iv } ); console.log(hex2a(decrypted.toString())); // result is in hexa });
这就是我如何encryption以使其与OpenSSL一起工作
fs.readFile('file.txt', function(err, data) { var encrypted = CryptoJS.AES.encrypt(data.toString(), password); buff = new Buffer(encrypted.toString(), "base64"); fs.writeFile('file.enc', buff); }); // openssl enc -d -aes-256-cbc -in file.enc -out file2.txt -k password
希望它会帮助别人:)
这个PHP代码包含命令行OpenSSLencryption:
…与此CryptoJS代码兼容,我通常在我的Mac上使用jsc
在命令行上运行:
(这个代码是用CryptoJS
3.1.2编写的,虽然我不希望和3.1.5有很大的区别)。
这些技巧是:
-
正如另一个答案所指出的,你需要指定双方的确切的关键和IV,以使其工作。
-
尽pipeAES-256理论上可以处理128位密钥,但我发现只有256位密钥似乎可以工作。
-
在这些例子中,我避免使用盐值。 你可以说可以通过join盐来使它更安全,但是要确保你在两个地方都正确地指定了它。
-
另外一个能够吸引人们的是他们认为他们可以传递一个string给
CryptoJS.decrypt()
函数。 这是不正确的。CryptoJS.decrypt()
需要一个cipherParams
对象。 (看例子) -
关于填充:
CryptoJS
和OpenSSL
默认为PKCS#7,除了PKCS#7可以处理任何块大小外,其function与PKCS#5相同。 当我们谈论8字节块大小时,它们是相同的。 无论如何,你不需要在CrytoJS
指定填充。
祝你好运!
- 试图嘲笑github webhook请求,得到:“X-Hub-Signature不匹配blob签名”
- Angular CryptoJs Encryption在Node JS CryptoJS中没有解密
- 无法使用密钥对validationNode.js Crypto的签名
- CryptoJs不能解密我的NodeJS服务器上的URL
- .NET和nodejs之间的AESalgorithm值差异,CryptoJS
- 如何解密CryptoJS中的AES 128(nodejs / web浏览器)
- AES CryptoJSencryption和phpseclib解密
- PassportJS – 在将有效载荷数据传递给passport.authenticate作为请求参数之前获取
- 在Meteor中正确启用filepicker.io的安全性