Ric*_*asi 5 javascript openssl cryptography webcrypto-api
我试图解密使用OpenSSL命令行界面创建的文件.此文件创建于:
openssl aes-256-cbc -a -in file.txt -out file_encrypted.txt
并可以解密:
openssl aes-256-cbc -d -a -in file_encrypted.txt
通过使用-p标志,我可以检索WebCrypto API所需的实际值salt和IV:
> openssl aes-256-cbc -d -a -p -in file_encrypted.txt
salt=F57F1CC0CD384326
key=0E971326890959386F1CFB91F185CFE109203DCEBC81DCAD4EE642F34C538E5B
iv=A884549B66400EB198879F8A09148D4E
secret text
Run Code Online (Sandbox Code Playgroud)
我目前的尝试看起来像这样:
function getKey (password) {
return crypto.subtle.digest({name: "SHA-256"}, convertStringToArrayBufferView(password)).then(function(result){
return crypto.subtle.importKey("raw", result, {name: "AES-CBC"}, false, ["encrypt", "decrypt"]);
});
}
function decrypt(key, data, iv) {
return crypto.subtle.decrypt({ name: "AES-CBC", iv: iv }, key, data).then(function(result){
var decrypted_data = new Uint8Array(result);
return convertArrayBufferViewtoString(decrypted_data);
}, fail);
}
var encrypted = Uint8Array.from('0E971326890959386F1CFB91F185CFE109203DCEBC81DCAD4EE642F34C538E5B'.match(/\w\w/g));
var IV = Uint8Array.from('A884549B66400EB198879F8A09148D4E'.match(/\w\w/g));
getKey(prompt('Enter decryption password:')).then(function (key) {
decrypt(key, encrypted, IV).then(result => {
console.log(`password: ${result}`)
});
}, fail);
Run Code Online (Sandbox Code Playgroud)
(为简洁起见,省略了数组到缓冲区的方法 - 取自http://qnimate.com/passphrase-based-encryption-using-web-cryptography-api/)
这失败了,DOMException虽然没有说明,但我不知道接下来该做什么.
OpenSSL使用加密时生成的一些随机字节将加密密钥派生算法应用于密码,并存储在加密文件的标头中.
在这篇文章中有很好的解释
OpenSSL使用盐渍密钥派生算法.salt是一段随机字节,在加密时生成,并存储在文件头中; 在解密时,从头部检索盐,并从提供的密码和盐值重新计算密钥和IV.
OpenSSL使用的加密格式是非标准的:它是"OpenSSL的作用",如果OpenSSL的所有版本都倾向于彼此一致,那么除了OpenSSL源代码之外,仍然没有描述此格式的参考文档.
因此,一个固定的16字节头,从字符串"Salted__"的ASCII编码开始,然后是盐本身.
要使代码工作是必需的:
加载OpenSSL生成的密钥(或者使用提供的salt和openssl算法从密码中导出密钥.派生算法在openssl加密页面中没有记录,但是在这篇文章中说它是propietary,所以它在webcrypto中不可用)
使用hex2a和从HEX解码到ArrayBufferconvertStringToArrayBufferView
var IV = convertStringToArrayBufferView (hex2a ('A884549B66400EB198879F8A09148D4E'));
加载加密文件:从base64解码(您使用-a选项)并删除盐的前16个字节
这是一个简化的javascript示例,使用相同的openssl命令生成数据
openssl aes-256-cbc -d -a -p -in file_encrypted.txt
enter aes-256-cbc decryption password:
salt=886DBE2C626D6112
key=0DA435C43BE722BB5BF09912E11E3E25BE826C35A674EC4284CD1C49AFBCC78E
iv =7F9608BF748309A2C7DAA63600AB3825
this is the secret value of the fiile
Run Code Online (Sandbox Code Playgroud)
Javascript代码
//The content of file_encrypted.txt. It is encoded in base64
var opensslEncryptedData = atob('U2FsdGVkX1+Ibb4sYm1hEp/MYnmmcteeebZ1jdQ8GhzaYlrgDfHFfirVmaR3Yor5C9th02S2wLptpJC6IYKiCg==');
//Encrypted data removing salt and converted to arraybuffer
var encryptedData = convertStringToArrayBufferView(opensslEncryptedData.substr(16,opensslEncryptedData.length););
//key and IV. salt would be needed to derive key from password
var IV = convertStringToArrayBufferView (hex2a ('7F9608BF748309A2C7DAA63600AB3825'));
var key = convertStringToArrayBufferView (hex2a ('0DA435C43BE722BB5BF09912E11E3E25BE826C35A674EC4284CD1C49AFBCC78E'));
//var salt = convertStringToArrayBufferView (hex2a ('886DBE2C626D6112'));
crypto.subtle.importKey("raw", key, {name: "AES-CBC"}, false, ["encrypt", "decrypt"]). then (function (cryptokey){
return crypto.subtle.decrypt({ name: "AES-CBC", iv: IV }, cryptokey, encryptedData).then(function(result){
var decrypted_data = new Uint8Array(result);
var res = convertArrayBufferViewtoString(decrypted_data);
console.log(res);
}).catch (function (err){
console.log(err);
});
}).catch (function (err){
console.log(err);
});
Run Code Online (Sandbox Code Playgroud)
实用功能
function hex2a(hexx) {
var hex = hexx.toString();//force conversion
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
function convertStringToArrayBufferView(str){
var bytes = new Uint8Array(str.length);
for (var iii = 0; iii < str.length; iii++) {
bytes[iii] = str.charCodeAt(iii);
}
return bytes;
}
function convertArrayBufferViewtoString(buffer){
var str = "";
for (var iii = 0; iii < buffer.byteLength; iii++) {
str += String.fromCharCode(buffer[iii]);
}
return str;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4257 次 |
| 最近记录: |