在浏览器/ CryptoJS中解密openssl AES 256 CBC

时间:2020-06-25 15:17:40

标签: javascript encryption openssl aes cryptojs

我想在服务器上解密已用openssl加密的字符串,如下所示:

model ClassicModel "This is the typical equation-oriented model"
  parameter Real alpha=0.1 "Reproduction rate of prey per day";
  parameter Real beta=0.02 "Mortality rate of prey per predator per day";
  parameter Real gamma=0.4 "Mortality rate of predator per day";
  parameter Real delta=0.02 "Reproduction rate of predator per day";
  parameter Real x0=10 "Start value of prey population";
  parameter Real y0=10 "Start value of predator population";

  Real x "Prey population";
  Real y "Predator population";
  Real alpha_S=alpha/(60*60*24) "Reproduction rate of prey per second";
  Real beta_S=beta/(60*60*24) "Mortality rate of prey per predator per second";
  Real gamma_S=gamma/(60*60*24) "Mortality rate of predator per second";
  Real delta_S=delta/(60*60*24) "Reproduction rate of predator per second";
  
initial equation
  x=x0;
  y=y0;
  
equation
  der(x) = x*(alpha_S-beta_S*y);
  der(y) = y*(delta_S*x-gamma_S);
end ClassicModel;

请注意,仅提供盐和密码即可完成此操作,openssl应该自动处理密钥和IV。如果浏览器也解密,我是否会感到乐观?如果可能的话,我只想使用那些加密设置或增加复杂性的最低限度来做到这一点。在浏览器中,我正在尝试使用CryptoJS进行如下解密:

openssl enc -e -aes-256-cbc -pbkdf2 -a -S 0123456789ABCDEF -A -k mypassword

但是对import * as CryptoJS from 'crypto-js' const encrypted = <ENCRYPTED_STRING_FROM_SERVER> const password = 'mypassword' const salt = '0123456789ABCDEF' const key = CryptoJS.PBKDF2(password, salt) // Generate key const bytes = CryptoJS.AES.decrypt(encrypted, key) const decrypted = bytes.toString(CryptoJS.enc.Utf8) console.log(decrypted) 的调用出现了CryptoJS.AES.decryptCannot read property '0' of undefined错误。 CryptoJS.AES.decrypt的文档非常薄,调用该函数时我知道要更改的任何设置似乎都给出了相同的错误。感谢任何可以发光的人!

1 个答案:

答案 0 :(得分:3)

在OpenSSL语句中,未指定迭代计数和摘要,因此使用默认值10000和SHA256。这是相关的,因为 CryptoJS 使用不同的默认值(1和SHA1)。

CryptoJS 对密文应用 OpenSSL 格式,即,加密的数据以Salted__的ASCII编码开头,然后是盐,然后是密文。因此,Base64编码密文的开头始终以U2FsdGVkX1开始。

CryptoJS 使用WordArray数据类型,该数据类型封装了单词数组。一个单词由4个字节组成。

在解密期间,必须首先将密文和盐分开。然后,必须使用PBKDF2确定密钥和IV。由于默认值不同,因此必须明确指定迭代次数和摘要。最终可以将其解密:

// 1. Separate ciphertext and salt
var encrypted = "U2FsdGVkX18BI0VniavN78vlhR6fryIan0VvUrdIr+YeLkDYhO2xyA+/oVXJj/c35swVVkCqHPh9VdRbNQG6NQ=="
var encryptedWA = CryptoJS.enc.Base64.parse(encrypted);
var prefixWA = CryptoJS.lib.WordArray.create(encryptedWA.words.slice(0, 8/4));                             // Salted__ prefix
var saltWA = CryptoJS.lib.WordArray.create(encryptedWA.words.slice(8/4, 16/4));                            // 8 bytes salt: 0x0123456789ABCDEF
var ciphertextWA = CryptoJS.lib.WordArray.create(encryptedWA.words.slice(16/4, encryptedWA.words.length)); // ciphertext        

// 2. Determine key and IV using PBKDF2
var password = 'mypassword'
var keyIvWA = CryptoJS.PBKDF2(
    password, 
    saltWA, 
    {
        keySize: (32+16)/4,          // key and IV
        iterations: 10000,
        hasher: CryptoJS.algo.SHA256
    }
);
var keyWA = CryptoJS.lib.WordArray.create(keyIvWA.words.slice(0, 32/4));
var ivWA = CryptoJS.lib.WordArray.create(keyIvWA.words.slice(32/4, (32+16)/4));

// 3. Decrypt
var decryptedWA = CryptoJS.AES.decrypt(
    {ciphertext: ciphertextWA}, 
    keyWA, 
    {iv: ivWA}
);
var decrypted = decryptedWA.toString(CryptoJS.enc.Utf8)
console.log(decrypted)
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

更多详细信息可以在CryptoJS documentation中找到。