如何在 openssl 中解密使用自定义迭代和密钥大小的 CryptoJs3+ 库加密的文件
how to decrypt a file that was encrypted with CryptoJs3+ library with custom iterations and key sizes, in openssl
我有一个由 cryptojs 加密的文本文件(可能还有一些自定义 js 函数来迭代密码的哈希值),我想在 windows 中通过 openssl.exe 解密它,而不是一个浏览器(当我提供密码时它可以完美运行)。看起来 cryptojs 使用了一些自定义的东西,比如使用 sha512 派生密钥并将其迭代 11512 次,如下面的 js 解密器所示,然后使用 evpkdf 迭代 484 次(我不知道这些东西是什么意思)。下面是从 cryptojs 解密文件的代码片段,我需要 openssl exe -cli params 来这样做,而无需在浏览器中使用该 js 库。
function hex2a(t) { //hex to ascii
for (var e = t.toString(), i = "", n = 0; n < e.length && "00" !== e.substr(n, 2); n += 2) i += String.fromCharCode(parseInt(e.substr(n, 2), 16));
return i; }
function decoder(secret, passwrd) {
for (var i = CryptoJS.SHA512(passwrd), n = 0; n < 11512; n++)
i = CryptoJS.SHA512(i);
(CryptoJS.algo.AES.keySize = 32),
(CryptoJS.algo.EvpKDF.cfg.iterations = 1e4),
(CryptoJS.algo.EvpKDF.cfg.keySize = 32);
var r = CryptoJS.AES.decrypt(secret, i.toString());
return (out = hex2a(r)), out;
}
这是它调用函数和 returns 文件(如果成功解密)的时间。
var msg="base64 of the salted encrypted file via cryptojs"
function proceed() {
var pass=document.getElementById('textfield2').value;
a=decoder(msg, pass);
if (a.search('{version')>-1) {
document.getElementById('status').innerHTML="SUCCESS";
download("result.json",a);
} else {
document.getElementById('status').innerHTML="FAILED";
}
我已经尝试过这个(windows openssl.exe cli 1.1)并且得到了关于 -iter 和其他参数的错误。不知道如何给它密钥大小 32 和迭代和 evpkdf 以及 js 文件解密的任何内容。
OpenSSL.exe enc -aes-256-cbc -md md5 -d -pass pass:"simpletext" -in "tiny.bin" -out "result.txt"
使用 OpenSSL 解密原则上不可能,原因如下:
指定的密钥大小AES.keySize = 32
定义了一个128字节的密钥(这里不是直接传递的,而是从密码派生的)。大概是打算使用 32 字节的密钥,但 CryptoJS 以字为单位指定密钥大小,其中一个字由 4 个字节组成。
AES 仅为 16/24/32 字节密钥定义,即。 e.不适用于所使用的 128 字节密钥。虽然密钥对 AES 无效,但 CryptoJS 处理此密钥是由于错误 (Issue #293)。
从密钥大小直接得出轮数,结果为 38,(source code). However, AES is only defined for the round numbers 10 (AES-128), 12 (AES-192) and 14 (AES-256) (AES, Security)。因此,生成的密文与 AES 不兼容,即因此通常不可能使用符合 AES 的工具(尤其是 OpenSSL)进行解密。
要使用 OpenSSL 进行解密,AES.keySize
需要具有以下条件之一值 4/6/8,对应于允许的整数 10/12/14 或 AES-128/192/256。因此,配置 AES.keySize = 32
是所有 AES 兼容工具(如 OpenSSL)的 KO 标准。
CryptoJS 使用 OpenSSL 函数 EVP_BytesToKey()
for key derivation. However, the specified iteration count EvpKDF.cfg.iterations = 1e4
is not supported by OpenSSL for key derivation with EVP_BytesToKey()
, only the value 1
(here, last part).
More modern OpenSSL versions (from 1.1.1) have the option -iter,但这仅与密钥派生 PBKDF2 结合使用,即如果指定 -iter , 自动使用 PBKDF2 而不是 EVP_BytesToKey()
,它与 CryptoJS 不兼容。
为了使用 OpenSSL 进行解密,EvpKDF.cfg.iterations
需要具有值 1
。因此配置 EvpKDF.cfg.iterations = 1e4
是 OpenSSL 的 KO 标准。
传递给 CryptoJS 的密码是通过 SHA512 多次哈希从原始密码派生出来的。正如 Artjom B. 的评论中已经解释的那样,这不能单独使用 OpenSSL 实现,但至少可以作为脚本的一部分。
EvpKDF.cfg.keySize
参数对encryption/decryption没有影响,可以忽略。
如果在发布的代码中使用兼容值而不是不兼容值,例如CryptoJS.algo.AES.keySize = 8
和 CryptoJS.algo.EvpKDF.cfg.iterations = 1
,可以使用 OpenSSL 解密。以下示例使用具有兼容值的发布代码并执行加密和解密。密文可以用OpenSSL解密:
//
// Your code
//
function hex2a(t) {
for (var e = t.toString(), i = "", n = 0; n < e.length && "00" !== e.substr(n, 2); n += 2) i += String.fromCharCode(parseInt(e.substr(n, 2), 16));
return i;
}
function decoder(secret, passwrd) {
for (var i = CryptoJS.SHA512(passwrd), n = 0; n < 11512; n++) i = CryptoJS.SHA512(i);
CryptoJS.algo.AES.keySize = 8; // compatible with OpenSSL: 4/6/8, corresponds to AES-128/192/265
CryptoJS.algo.EvpKDF.cfg.iterations = 1; // compatible with OpenSSL: 1
CryptoJS.algo.EvpKDF.cfg.keySize = 123; // ignored
var r = CryptoJS.AES.decrypt(secret, i.toString());
return (out = hex2a(r)), out;
}
//
// The encryption counterpart
//
function encrypt(secret, passwrd) {
for (var i = CryptoJS.SHA512(passwrd), n = 0; n < 11512; n++) i = CryptoJS.SHA512(i);
CryptoJS.algo.AES.keySize = 8;
CryptoJS.algo.EvpKDF.cfg.iterations = 1;
CryptoJS.algo.EvpKDF.cfg.keySize = 456;
console.log("CryptoJS input passphrase:\n", i.toString().replace(/(.{56})/g,'\n'));
var ciphertext = CryptoJS.AES.encrypt(secret, i.toString());
return ciphertext;
}
//
// Encryption, decryption
//
var ciphertext = encrypt('The quick brown fox jumps over the lazy dog', 'my initial passphrase');
var decryptedData = decoder(ciphertext, 'my initial passphrase');
console.log("Ciphertext:\n", ciphertext.toString().replace(/(.{56})/g,'\n'));
console.log("Plaintext:\n", decryptedData.replace(/(.{56})/g,'\n'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
可能的输出:
CryptoJS input passphrase: 7bff3331f9dcfbb2e1c5b6cb4170689db91fe5b12258d59672fe0e9ce61780c61f3e6dc324e58cc2170c6a8010083aafe07930708ee63c0022a7e9bce784c4c5
Ciphertext: U2FsdGVkX1/3SLTOsvc6CoWfg53rR+l//pHiWstJibl5D5OopIFWVmhUDhEpj7zBZRjA1vQiIoU2F5qR1v8NEw==
Plaintext: The quick brown fox jumps over the lazy dog
密文可以通过以下OpenSSL语句解密(直接使用派生密码):
openssl enc -aes-256-cbc -d -a -A -in <path to ciphertext file> -md md5 -pass pass:7bff3331f9dcfbb2e1c5b6cb4170689db91fe5b12258d59672fe0e9ce61780c61f3e6dc324e58cc2170c6a8010083aafe07930708ee63c0022a7e9bce784c4c5
当使用与这些不同的参数时(例如 AES.keySize = 32
或 EvpKDF.cfg.iterations = 1e4
),解密通常会失败并显示 bad decrypt(即使使用 -iter 10000
).
我有一个由 cryptojs 加密的文本文件(可能还有一些自定义 js 函数来迭代密码的哈希值),我想在 windows 中通过 openssl.exe 解密它,而不是一个浏览器(当我提供密码时它可以完美运行)。看起来 cryptojs 使用了一些自定义的东西,比如使用 sha512 派生密钥并将其迭代 11512 次,如下面的 js 解密器所示,然后使用 evpkdf 迭代 484 次(我不知道这些东西是什么意思)。下面是从 cryptojs 解密文件的代码片段,我需要 openssl exe -cli params 来这样做,而无需在浏览器中使用该 js 库。
function hex2a(t) { //hex to ascii
for (var e = t.toString(), i = "", n = 0; n < e.length && "00" !== e.substr(n, 2); n += 2) i += String.fromCharCode(parseInt(e.substr(n, 2), 16));
return i; }
function decoder(secret, passwrd) {
for (var i = CryptoJS.SHA512(passwrd), n = 0; n < 11512; n++)
i = CryptoJS.SHA512(i);
(CryptoJS.algo.AES.keySize = 32),
(CryptoJS.algo.EvpKDF.cfg.iterations = 1e4),
(CryptoJS.algo.EvpKDF.cfg.keySize = 32);
var r = CryptoJS.AES.decrypt(secret, i.toString());
return (out = hex2a(r)), out;
}
这是它调用函数和 returns 文件(如果成功解密)的时间。
var msg="base64 of the salted encrypted file via cryptojs"
function proceed() {
var pass=document.getElementById('textfield2').value;
a=decoder(msg, pass);
if (a.search('{version')>-1) {
document.getElementById('status').innerHTML="SUCCESS";
download("result.json",a);
} else {
document.getElementById('status').innerHTML="FAILED";
}
我已经尝试过这个(windows openssl.exe cli 1.1)并且得到了关于 -iter 和其他参数的错误。不知道如何给它密钥大小 32 和迭代和 evpkdf 以及 js 文件解密的任何内容。
OpenSSL.exe enc -aes-256-cbc -md md5 -d -pass pass:"simpletext" -in "tiny.bin" -out "result.txt"
使用 OpenSSL 解密原则上不可能,原因如下:
指定的密钥大小
AES.keySize = 32
定义了一个128字节的密钥(这里不是直接传递的,而是从密码派生的)。大概是打算使用 32 字节的密钥,但 CryptoJS 以字为单位指定密钥大小,其中一个字由 4 个字节组成。
AES 仅为 16/24/32 字节密钥定义,即。 e.不适用于所使用的 128 字节密钥。虽然密钥对 AES 无效,但 CryptoJS 处理此密钥是由于错误 (Issue #293)。
从密钥大小直接得出轮数,结果为 38,(source code). However, AES is only defined for the round numbers 10 (AES-128), 12 (AES-192) and 14 (AES-256) (AES, Security)。因此,生成的密文与 AES 不兼容,即因此通常不可能使用符合 AES 的工具(尤其是 OpenSSL)进行解密。
要使用 OpenSSL 进行解密,AES.keySize
需要具有以下条件之一值 4/6/8,对应于允许的整数 10/12/14 或 AES-128/192/256。因此,配置AES.keySize = 32
是所有 AES 兼容工具(如 OpenSSL)的 KO 标准。CryptoJS 使用 OpenSSL 函数
EVP_BytesToKey()
for key derivation. However, the specified iteration countEvpKDF.cfg.iterations = 1e4
is not supported by OpenSSL for key derivation withEVP_BytesToKey()
, only the value1
(here, last part).
More modern OpenSSL versions (from 1.1.1) have the option -iter,但这仅与密钥派生 PBKDF2 结合使用,即如果指定 -iter , 自动使用 PBKDF2 而不是EVP_BytesToKey()
,它与 CryptoJS 不兼容。
为了使用 OpenSSL 进行解密,EvpKDF.cfg.iterations
需要具有值1
。因此配置EvpKDF.cfg.iterations = 1e4
是 OpenSSL 的 KO 标准。传递给 CryptoJS 的密码是通过 SHA512 多次哈希从原始密码派生出来的。正如 Artjom B. 的评论中已经解释的那样,这不能单独使用 OpenSSL 实现,但至少可以作为脚本的一部分。
EvpKDF.cfg.keySize
参数对encryption/decryption没有影响,可以忽略。
如果在发布的代码中使用兼容值而不是不兼容值,例如CryptoJS.algo.AES.keySize = 8
和 CryptoJS.algo.EvpKDF.cfg.iterations = 1
,可以使用 OpenSSL 解密。以下示例使用具有兼容值的发布代码并执行加密和解密。密文可以用OpenSSL解密:
//
// Your code
//
function hex2a(t) {
for (var e = t.toString(), i = "", n = 0; n < e.length && "00" !== e.substr(n, 2); n += 2) i += String.fromCharCode(parseInt(e.substr(n, 2), 16));
return i;
}
function decoder(secret, passwrd) {
for (var i = CryptoJS.SHA512(passwrd), n = 0; n < 11512; n++) i = CryptoJS.SHA512(i);
CryptoJS.algo.AES.keySize = 8; // compatible with OpenSSL: 4/6/8, corresponds to AES-128/192/265
CryptoJS.algo.EvpKDF.cfg.iterations = 1; // compatible with OpenSSL: 1
CryptoJS.algo.EvpKDF.cfg.keySize = 123; // ignored
var r = CryptoJS.AES.decrypt(secret, i.toString());
return (out = hex2a(r)), out;
}
//
// The encryption counterpart
//
function encrypt(secret, passwrd) {
for (var i = CryptoJS.SHA512(passwrd), n = 0; n < 11512; n++) i = CryptoJS.SHA512(i);
CryptoJS.algo.AES.keySize = 8;
CryptoJS.algo.EvpKDF.cfg.iterations = 1;
CryptoJS.algo.EvpKDF.cfg.keySize = 456;
console.log("CryptoJS input passphrase:\n", i.toString().replace(/(.{56})/g,'\n'));
var ciphertext = CryptoJS.AES.encrypt(secret, i.toString());
return ciphertext;
}
//
// Encryption, decryption
//
var ciphertext = encrypt('The quick brown fox jumps over the lazy dog', 'my initial passphrase');
var decryptedData = decoder(ciphertext, 'my initial passphrase');
console.log("Ciphertext:\n", ciphertext.toString().replace(/(.{56})/g,'\n'));
console.log("Plaintext:\n", decryptedData.replace(/(.{56})/g,'\n'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
可能的输出:
CryptoJS input passphrase: 7bff3331f9dcfbb2e1c5b6cb4170689db91fe5b12258d59672fe0e9ce61780c61f3e6dc324e58cc2170c6a8010083aafe07930708ee63c0022a7e9bce784c4c5
Ciphertext: U2FsdGVkX1/3SLTOsvc6CoWfg53rR+l//pHiWstJibl5D5OopIFWVmhUDhEpj7zBZRjA1vQiIoU2F5qR1v8NEw==
Plaintext: The quick brown fox jumps over the lazy dog
密文可以通过以下OpenSSL语句解密(直接使用派生密码):
openssl enc -aes-256-cbc -d -a -A -in <path to ciphertext file> -md md5 -pass pass:7bff3331f9dcfbb2e1c5b6cb4170689db91fe5b12258d59672fe0e9ce61780c61f3e6dc324e58cc2170c6a8010083aafe07930708ee63c0022a7e9bce784c4c5
当使用与这些不同的参数时(例如 AES.keySize = 32
或 EvpKDF.cfg.iterations = 1e4
),解密通常会失败并显示 bad decrypt(即使使用 -iter 10000
).