如何使用Web Crypto API解密使用OpenSSL创建的文件? [英] How to use the Web Crypto API to decrypt a file created with OpenSSL?

查看:154
本文介绍了如何使用Web Crypto API解密使用OpenSSL创建的文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解密使用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);

(为简洁起见,省略了数组到缓冲区的方法 - 取自 http://qnimate.com/passphrase-based-encryption-using-web-cryptography-api/

(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使用盐渍密钥派生算法。 salt是一段随机字节,在加密时生成,并存储在文件头中;解密后,从标头中检索salt,并从提供的密码和salt值重新计算密钥和IV。

OpenSSL uses a salted key derivation algorithm. The salt is a piece of random bytes which are generated when encrypting, and stored in the file header; upon decryption, the salt is retrieved from the header, and the key and IV are recomputed from the provided password and the salt value.

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算法从密码派生密钥。派生算法未在 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创建的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆