问题描述
我正在尝试解密使用OpenSSL命令行界面创建的文件。此文件创建时间为:
I am trying to decrypt a file that was created using the OpenSSL command-line interface. This file was created with:
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:
By using the -p
flag I can retrieve the actual value, salt and IV which will be required by the WebCrypto API:
> openssl aes-256-cbc -d -a -p -in file_encrypted.txt
salt=F57F1CC0CD384326
key=0E971326890959386F1CFB91F185CFE109203DCEBC81DCAD4EE642F34C538E5B
iv=A884549B66400EB198879F8A09148D4E
secret text
我目前的尝试如下:
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);
(为简洁起见,省略了数组到缓冲区的方法 - 取自)
(array-to-buffer methods ommited for brevity - taken from http://qnimate.com/passphrase-based-encryption-using-web-cryptography-api/)
虽然未指定 DOMException
但是失败,我不知道接下来该做什么。
This fails with an unspecified DOMException
though and I have no idea what to do next.
推荐答案
OpenSSL使用加密时生成的一些随机字节将加密密钥派生算法应用于您的密码并存储在加密的标头中文件。
OpenSSL applies a salted key derivation algorithm to your password using some random bytes generated when encrypting and stored in the header of the encrypted file.
在中有很好的解释
OpenSSL使用的加密格式是非-standard:它是OpenSSL的作用,如果OpenSSL的所有版本都倾向于彼此一致,那么除了OpenSSL源代码之外,仍然没有描述这种格式的参考文档。
The encryption format used by OpenSSL is non-standard: it is "what OpenSSL does", and if all versions of OpenSSL tend to agree with each other, there is still no reference document which describes this format except OpenSSL source code.
因此是一个固定的16字节头,以字符串Salted__的ASCII编码开头,后跟盐本身。
Hence a fixed 16-byte header, beginning with the ASCII encoding of the string "Salted__", followed by the salt itself.
要使代码正常工作:
-
加载由OpenSSL生成的密钥(或使用提供的salt使用openssl算法从密码派生密钥。派生算法未在,但在此据说是专属的,因此无法在webcrypto中使用。)
Load the key generated by OpenSSL (or derive the key from password using the provided salt with the openssl algorithm. The derivation algorithm is undocumented in the openssl encryption page, but in this post is said that is propietary, so it is not available in webcrypto)
使用<$ c从HEX解码到ArrayBuffer $ c> hex2a 和 convertStringToArrayBufferView
decode from HEX to ArrayBuffer using hex2a
and convertStringToArrayBufferView
var IV = convertStringToArrayBufferView(hex2a('A884549B66400EB198879F8A09148D4E'));
加载加密文件 :从base64解码(您使用 -a
选项)并删除盐的前16个字节
Load the encrypted file: decode from base64 (you used -a
option) and remove the first 16 bytes of the salt
这是一个简化使用相同的openssl命令生成的数据的javascript示例
This a simplified javascript example with data generated with the same openssl command
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
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);
});
效用函数
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;
}
这篇关于如何使用Web Crypto API解密使用OpenSSL创建的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!