4

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 ?

3
  • 3
    write your code in the post Commented Dec 25, 2019 at 2:36
  • Have you found proper answer to this? I am facing the similar problem. I am Encrypting in PHP and decrypting in JS. however the PHP is working fine and I can pass the encrypted file to this devglan and it decrypts it perfectly but on JS I am having issue 'Malformed UTF-8 data'. Let me know if you have found any solution to tis. Commented Aug 22, 2023 at 11:27
  • @HashirQadeer For a long time, but you can try Topaco's answer below for this issue. Commented Sep 1, 2023 at 4:02

1 Answer 1

6

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>

Sign up to request clarification or add additional context in comments.

8 Comments

Many thanks for your detail explanation, but I have one more question: If I have only encryptedBase64 string how can I convert encryptedBase64 string to encryptedCP object ?
See the Update-section in my answer.
Great answer, this should have much more upvotes.
This works. Nice one
what is the solution without using the CryptoJS dependency?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.