How to decrypt AES 256 CBC by javascrypt (Not Nodejs)?

How can I decrypt an encrypted string like dIwykUwOomuWcdw/QX/Aig== in AES 256 CBC mode with the key ds8am3wys3pd75nf0ggtvajw2k3uny92 and iv jm8lgqa3j1d0ajus as the picture below just with javascript (not Nodejs). I used to try with CryptoJs library but the result not like I expected.

enter image description here

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/pbkdf2.js"></script>
<script>
    var str = 'dIwykUwOomuWcdw/QX/Aig==';
    var key = 'ds8am3wys3pd75nf0ggtvajw2k3uny92';
    var iv  = 'jm8lgqa3j1d0ajus';

    var encrypted = CryptoJS.AES.encrypt("2730007809303", key, { iv: iv });
    var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv});
    var base64_str = decrypted.toString(CryptoJS.enc.Base64);
    console.log(atob(base64_str))
</script>

By the way, how can I convert input string dIwykUwOomuWcdw/QX/Aig== as encrypted object above ?

Upvotes: 4

Views: 14071

Answers (1)

Topaco
Topaco

Reputation: 49141

Your code snippet is almost right. However, the key must not be passed as a string, otherwise CryptoJS will interpret it as a passphrase and generate the actual key and IV from it [1], with an insecure algorithm by the way. Instead, key and IV must be passed as WordArray, which is easily achieved using the encoders [2]. Since key and IV are Utf8-strings in this example, they must be parsed with the Utf8-encoder. Then you will get the desired ciphertext of the web page. Be aware that encrypt returns a CipherParams-object that encapsulates the ciphertext among other data [3]. Furthermore, you don't need the Base64-detour and should decode the decrypted data directly as UTF8-string:

var key = CryptoJS.enc.Utf8.parse('ds8am3wys3pd75nf0ggtvajw2k3uny92');     // Use Utf8-Encoder. 
var iv  = CryptoJS.enc.Utf8.parse('jm8lgqa3j1d0ajus');                     // Use Utf8-Encoder

var encryptedCP = CryptoJS.AES.encrypt("2730007809303", key, { iv: iv });
var decryptedWA = CryptoJS.AES.decrypt(encryptedCP, key, { iv: iv});

var encryptedBase64 = encryptedCP.toString();                              // Short for: encryptedCP.ciphertext.toString(CryptoJS.enc.Base64);
var decryptedUtf8 = decryptedWA.toString(CryptoJS.enc.Utf8);               // Avoid the Base64 detour.
                                                                           // Alternatively: CryptoJS.enc.Utf8.stringify(decryptedWA);  
console.log("Ciphertext (Base64)  : " + encryptedBase64)
console.log("Decrypted data (Utf8): " + decryptedUtf8); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>

Note that the CBC-mode and PKCS7-padding are implicitly used, which are the default parameters of CryptoJS [4], so it is not necessary to specify them explicitly.

Update:

If the ciphertext is a string or a WordArray, a CipherParams-object must be created from it, because the decrypt-method expects an object of this type [5]. The entirety of all data encapsulated by the CipherParams-object can be most easily taken from its definition [6]. In the current case at least the ciphertext must be specified as WordArray. Optionally a formatter can be specified which determines the formatting strategy of toString() (if used):

var key = CryptoJS.enc.Utf8.parse('ds8am3wys3pd75nf0ggtvajw2k3uny92');     // Use Utf8-Encoder. 
var iv  = CryptoJS.enc.Utf8.parse('jm8lgqa3j1d0ajus');                     // Use Utf8-Encoder

var ciphertext = CryptoJS.enc.Base64.parse('dIwykUwOomuWcdw/QX/Aig==');    // Use Base64-Encoder.       
var encryptedCP = CryptoJS.lib.CipherParams.create({
    ciphertext: ciphertext,
    formatter: CryptoJS.format.OpenSSL                                     // Optional, but required for encryptedCP.toString() 
});
var decryptedWA = CryptoJS.AES.decrypt(encryptedCP, key, { iv: iv});

var encryptedBase64 = encryptedCP.toString();                              // Short for: encryptedCP.ciphertext.toString(CryptoJS.enc.Base64);
var decryptedUtf8 = decryptedWA.toString(CryptoJS.enc.Utf8);               // Avoid the Base64 detour.
                                                                           // Alternatively: CryptoJS.enc.Utf8.stringify(decryptedWA);  
console.log("Ciphertext (Base64)  : " + encryptedBase64)
console.log("Decrypted data (Utf8): " + decryptedUtf8);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>

Upvotes: 6

Related Questions