我正在尝试使用CryptoJS 3.1.5解密一个用openssl加密的文件。
如果我使用CryptoJS加密和解密,一切都可以正常工作,OpenSSL在shell中也是如此,但是当我试图将CryptoJS与OpenSSL混合时,一切都会出错。
文件是使用以下命令创建的:
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);
});然后在壳牌:
openssl enc -d -aes-256-cbc -in file.enc -out file2.txt -k password
// Give me this err: bad magic number我漏掉了什么明显的东西吗?
发布于 2015-09-20 10:39:20
目前还没有确切的答案,但对于评论来说太多了:
命令行openssl enc默认使用带salt的基于密码的加密(PBE),这意味着实际的加密密钥,而适用于CBC的IV则由基于密码的密钥派生函数从给定的密码和随机盐值中计算,这使得对手更难以尝试密码猜测攻击。我不知道您的JS模块(或者完全不知道多少JS ),但是您链接的网页列出了各种低级原语,这表明它不会自动执行PBE。像"password“这样的文本字符串(可能)适用于PBE,但不适合直接AES加密,其中密钥必须是128、192或256位,并且应该是随机二进制数据。
如果您想要openssl的半标准,可以在JS端匹配它;项目evpkey听起来可能很有帮助,因为EVP是涉及的openssl模块,而且我不知道会被称为EVP的其他(PB)KDF方案。如果不是,enc默认的PBE只是密码的MD5,它与salt连接在一起,根据需要重复多次反馈,在本例中是三次。有关(大部分) perl中的示例,请参见https://superuser.com/questions/455463/openssl-hash-function-for-generating-aes-key。OpenSSL将8个ASCII字符"Salted__“和8个字节的salt前缀添加到文件中,因此您需要在解密之前删除这些字符(并使用salt),或者在加密后添加它们。
如果您想要原始加密,请选择一个更合适的密钥(任何一方),以及唯一和不可预测的IV,除非您总是使用新密钥--在这种情况下,您可以使用固定的IV;在openssl方面,请使用-K (注大写)和-iv来指定十六进制中的值。请参阅安装了openssl或https://www.openssl.org/docs/manmaster/apps/enc.html的任何Unix系统上的手册。
此外,在这两种情况下,enc默认为"PKCS#5“(实际上是PKCS#7) 填充。我不知道您的JS模块是否有;如果没有,您应该指定它。除非您能够保证您的明文始终是16个字节的确切倍数(在任何像UTF8这样的编码之后);那么您可以在JS端指定(或者可能默认)没有填充,并在openssl端指定-nopad。
发布于 2015-09-25 13:04:03
为了记录在案,我就是这样解密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
});这就是我如何加密使它与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希望它能帮助到某人:)
发布于 2015-09-21 05:24:05
此PHP代码包括命令行OpenSSL加密:
http://pastebin.com/sivmZvSw
...is与CryptoJS代码兼容,我通常在命令行上使用Mac上的jsc运行这些代码:
http://pastebin.com/LcDBG7yj
(这段代码是用CryptoJS 3.1.2编写的,不过我不认为这和3.1.5有什么大的区别。)
诀窍是:
CryptoJS.decrypt()函数。这不对。CryptoJS.decrypt()需要一个cipherParams对象。(见示例)CryptoJS和OpenSSL都默认为PKCS#7,这在功能上等同于PKCS#5,但PKCS#7可以处理任何块大小。当我们谈论8字节块大小时,它们是相同的。无论如何,您不需要在CrytoJS中指定填充。祝好运!
https://stackoverflow.com/questions/32654749
复制相似问题