简体   繁体   中英

Decrypt openssl AES 256 CBC in browser/CryptoJS

I want to decrypt a string that has been encrypted with openssl on the server like this:

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

Note this is done providing only a salt and password, and openssl should handle key and IV automatically. Am I too optimistic that this can happen when the browser decrypts too? If at all possible, I want to do it with only those encryption settings, or the bare minimum of increased complexity. In the browser, I'm trying to decrypt with CryptoJS like this:

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)

But the call to CryptoJS.AES.decrypt errors with Cannot read property '0' of undefined , crypto-js/cipher-core.js:371 . The docs for CryptoJS.AES.decrypt are quite thin, and any settings I am aware of to change when calling that func seem to give the same error. Thanks to anyone who can shine light!

In the OpenSSL statement, the iteration count and digest are not specified, so the default values 10000 and SHA256 are used. This is relevant because CryptoJS uses different default values ( 1 and SHA1).

CryptoJS applies the OpenSSL format for the ciphertext, ie the encrypted data starts with the ASCII encoding of Salted__ followed by the salt and then the ciphertext. Therefore the beginning of the Base64 encoded ciphertext starts always with U2FsdGVkX1 .

CryptoJS uses the WordArray data type, which encapsulates an array of words. A word consists of 4 bytes.

During decryption, ciphertext and salt must first be separated. Then, key and IV must be determined using PBKDF2. Due to the different default values, iteration count and digest must be specified explicitly. Finally it can be decrypted:

 // 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>

More details can be found in the CryptoJS documentation .

try this lib in browser https://www.npmjs.com/package/cryptojs2 More details can be found in the documentation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM