【发布时间】:2015-12-19 11:46:00
【问题描述】:
我正在尝试解密 OpenSSL AES 加密文件,为此我需要从文件的开头读取 salt,并将密码提供给 CryptoJS openssl 密钥派生函数以获取派生密钥和 iv。
遗憾的是,CryptoJS 期望 salt 是一个字符串,而 JS 中的字符串处理不好的二进制数据。 超过 128 的字符在 JS 中被解释为 2 位(参见:Trouble with binary string in javascript above character code 128):
// if you wanna test it, openssl command to generate a file from any file :
// openssl enc -aes-256-cbc -in file.txt -out file.enc -k password
fs.readFile('file.enc', function(err, data) {
var Salted__ = data.toString("utf-8", 0, 8); // 'Salted__' prefix
var salt = data.toString("hex", 8, 16); // the actual salt I want to give to CryptoJS
// output in hex: 46d69efb7f57380b
var buf = new Buffer(salt, "hex");
console.log(buf);
// output <Buffer 46 d6 9e fb 7f 57 38 0b>, exactly what I want, but it is a buffer not a String object.
// the problem can be seen here:
var buf2 = new Buffer(buf.toString());
console.log(buf2);
// output <Buffer 46 d6 9e ef bf bd 7f 57 38 0b>
// as you can see, fb => ef bf bd
// fun fact, when I try to do it manualy, I get another result (that seem more logical to me):
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
console.log(new Buffer(str));
// output <Buffer 46 c3 96 c2 9e c3 bb 7f 57 38 0b>
// in this case (I've tryed it char by char to be sure):
// d6 => c3 96
// 9e => c2 9e
// fb => c3 bb
var derivedParams = CryptoJS.kdf.OpenSSL.execute(password, 256/32, 128/32, buf.toString());
console.log(derivedParams.key.toString());
console.log(derivedParams.iv.toString());
// output a wrong key and a wrong iv (I know what I should get using openssl enc -P option)
});
任何关于 JS 如何处理二进制字符串的帮助或解释将不胜感激:)
【问题讨论】:
-
我对 CryptoJS 一无所知,但是代码高于 128 的字符在 JavaScript 中没有任何特殊处理,所以我猜这个问题可能与 UTF-8 中代码点的编码有关,它使用更多超过 127 个字符代码的字符。
-
既然您现在知道解决方案,我不确定您正在寻找什么样的答案。另外,请不要在您的问题中编辑答案。他们进入答案框。
-
我只是好奇它是如何工作的,为什么当我手动通过缓冲区将十六进制转换为字符时,我没有相同的结果,就像那样,出于好奇。
标签: javascript string binary cryptojs