Unable to decrypt message using Crypto-Js - javascript

I am new to encryption. What I am trying to do is decrypt a cipher text using javascript library, CryptoJS. This code example works fine. The encryption part returns ciphertext "ae06b481cecfa67c98c125" (which is right) while decrypting the same object returns the original string "Hello World".
var key = CryptoJS.enc.Latin1.parse("bad8deadcafef00d");
var iv = CryptoJS.enc.Latin1.parse("bad8deadcafef00d");
var encrypted = CryptoJS.AES.encrypt("Hello World", key, {iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
alert(encrypted.ciphertext);
var decryptedData = CryptoJS.AES.decrypt(encrypted, key, {iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
originalData = decryptedData.toString(CryptoJS.enc.Utf8);
alert(originalData);
Well this part works fine but when I try this chunk of code by passing the cipher text as a string independently, I don't get the decrypted message.
var key = CryptoJS.enc.Latin1.parse("bad8deadcafef00d");
var iv = CryptoJS.enc.Latin1.parse("bad8deadcafef00d");
var ciphertext = "ae06b481cecfa67c98c125";
// raw = CryptoJS.enc.Base64.parse(cipher);
var decryptedData = CryptoJS.AES.decrypt(ciphertext, key, {iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
originalData = decryptedData.toString(CryptoJS.enc.Utf8);
alert(originalData);
console.log(originalData);
Can somebody please point out why?
I have the following libraries included in the html file.
<script src="js/rollups/aes.js"></script>
<script src="js/components/mode-ctr.js"></script>
<script src="js/components/pad-nopadding.js"></script>

CryptoJS.AES.decrypt expects either a CipherParams object or an OpenSSL-formatted string. If the passed key is a string then the OpenSSL-formatted string is expected and otherwise the CipherParams object.
Since your key is not a string, you need this:
var decryptedData = CryptoJS.AES.decrypt({
ciphertext: CryptoJS.enc.Hex.parse("ae06b481cecfa67c98c125")
}, key, {
iv: iv,
mode: CryptoJS.mode.CTR,
padding: CryptoJS.pad.NoPadding
});
If the key is a string, then it isn't actually a key, but assumed to be a password and a key will be derived from that password with a random 8 byte salt. This would be comparable to OpenSSL's EVP_BytesToKey function.

Related

CryptoJS decrypt AES returns empty

I have trouble decrypting data in CryptoJS. After decrypting the data it returns an empty string
Here is my code:
Javascript code
var iv = CryptoJS.enc.Utf8.parse(dataa[5]);
var key = 'AAAAAAAAAAAAAAAA';
key = CryptoJS.enc.Utf8.parse(key);
var decrypted = CryptoJS.AES.decrypt(dataa[1], key, { iv: iv, mode: CryptoJS.mode.CBC});
decrypted = decrypted.toString(CryptoJS.enc.Utf8);
console.log(decrypted);
alert(decrypted);
The alert returns an empty string. Dataa[5] is the IV and dataa1 is the data that has to decrypted.
After the CryptoJS.AES.decrypt the variable decrypted is already empty.
I am new to CryptoJS and do not understand why it wont work.
dataa[ 1 ] = gXodEwQf2Mk+ZW9RDiktNw
dataa[ 5 ] = s/D0LaJK1SwL9pgF/r1DAQ==

Decrypt AES in JavaScript

I am encrypting a text with AES256 in swift language and outputting it as hex. I want to decrypt this code I received with JS, but I could not reach the result. I tried the CryptoJS library but still couldn't get the result I wanted. All I want is the js code that will give me the decoded version when I enter the IV, password and ciphertext.
const crypto = require("crypto");
var key = "";
const iv = "";
const token = "";
function decrypt(token, iv, key) {
const decrypter = crypto.createDecipheriv("aes-256-cbc", key, iv);
let decrypted = decrypter.update(token, "hex", "utf8");
decrypted += decrypter.final("utf8");
return decrypted
}
console.log(decrypt(token, iv, key));
With the Node.js code above, I achieve what I want, but I want to do it with normal JS code, not using node. I don't want to mess with the server. I would be very happy if you help.
EDIT:
I am using CryptoSwift library in Swift language.
func encryption(uuid: String, token: String) -> String {
do {
let aes = try AES(key: String(uuid.prefix(32)), iv: String(uuid.prefix(16)))
let ciphertext = try aes.encrypt(Array(token.utf8))
let encrypttext = ciphertext.toHexString()
return encrypttext
}
catch {
return "error"
}
}
I tried to do something with CryptoJS with the codes from the site below, but it didn't work like the codes in Node.js.
https://embed.plnkr.co/0VPU1zmmWC5wmTKPKnhg/
EDIT2:
I've been trying different things but couldn't quite figure it out. I get an error when I add PBKDF2. I don't fully understand the problem.
var password = "6268890F-9B58-484C-8CDC-34F9C6A9";
var iv = "6268890F-9B58-48";
var cipher = "79a247e48ac27ed33ca3f1919067fa64";
/*
var key = CryptoJS.PBKDF2(password, {
keySize: 32
});
*/
var dec= CryptoJS.enc.Hex.parse(cipher);
const decrypted = CryptoJS.AES.decrypt({
ciphertext: dec
},
password, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
console.log(decrypted.toString(CryptoJS.enc.Utf8));
<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>
CryptoJS uses WordArrays, so that key, IV and ciphertext have to be converted accordingly. For this purpose the appropriate encoders have to be applied. Furthermore decrypt() expects the ciphertext as CipherParams object.
This results in the following possible CryptoJS implementation:
var ciphertext = "79a247e48ac27ed33ca3f1919067fa64";
var key = "6268890F-9B58-484C-8CDC-34F9C6A9";
var iv = "6268890F-9B58-48";
var ciphertextWA = CryptoJS.enc.Hex.parse(ciphertext);
var keyWA = CryptoJS.enc.Utf8.parse(key);
var ivWA = CryptoJS.enc.Utf8.parse(iv);
var ciphertextCP = { ciphertext: ciphertextWA };
var decrypted = CryptoJS.AES.decrypt(
ciphertextCP,
keyWA,
{ iv: ivWA }
);
console.log(decrypted.toString(CryptoJS.enc.Utf8)); // Apple
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
which is functionally identical to the posted NodeJS code that also successfully decrypts the test data.
Regarding the question asked in the comment about the encodings:
In general, the decryption side must have knowledge of the encodings used for encryption. However, in this case the encodings can be derived from the posted NodeJS code:
For decryption, the input encoding of the ciphertext is specified as 'hex', see decipher.update().
key and iv are defined as strings which are UTF-8 encoded, see crypto.createDecipheriv().
Also, the data used is consistent with these conclusions.
Note that for security reasons a static IV may not be used. Instead, a random IV must be generated for each encryption.
Also, no password may be applied as key, even if it has the right length. If a password is to be used, a key derivation is necessary, e.g. with PBKDF2.
For test purposes, the data is of course enough.

AES encryption with Javascript using cryptojs same as Java - AES/CBC/PKCS5Padding

I am using AES encryption in Java and want to do same in Javascript/Typescript using cryptojs.
I am trying below Javascript code but both are returning different results.
Java Code
String sKey = 'MySecureKeyText1';
String _text = "ValuetoEncrypt";
byte key[] = sKey.getBytes("UTF-8");
KeySpec aKeySpec = new SecretKeySpec(key, "AES");
MessageDigest hashMD5 = MessageDigest.getInstance("MD5");
hashMD5.update(sKey.getBytes("UTF-8"));
byte[] ivbytes = hashMD5.digest();
IvParameterSpec IV = new IvParameterSpec(ivbytes, 0, ivbytes.length);
Cipher mCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
mCipher.init(Cipher.ENCRYPT_MODE, (Key) aKeySpec, IV);
string ciphertext = mCipher.doFinal(_text.getBytes());
ciphertext = ByteToHex(ciphertext); // .CAAFD9C519C23E91A4B58D158ECA5462
JavaScript Code
this.encrypt('ValuetoEncrypt', 'MySecureKeyText1');
encrypt(value : string, key:string) : string{
let ivHash = cryptoJS.MD5(key).toString();
let cipher = this.cipher(value, key, ivHash);
return cipher.ciphertext.toString(); // 5a78aa6905208aa6fa63d1d452ea482e
}
cipher(value, key, iv) {
const cipher = cryptoJS.AES.encrypt(value, key, {
iv: iv,
mode: cryptoJS.mode.CBC,
keySize: 128,
padding: cryptoJS.pad.Pkcs7
});
return cipher;
}
Issue Resolved
Fixed this issue by converting key into byte array using cryptoJS.enc.Utf8.parse before passing for ecryption.
As per the crypto-js documentation if we pass key in string format then they use it to derive an actual key and iv, If we pass in word array then it will use actual value we sent.
this.encrypt('ValuetoEncrypt', 'MySecureKeyText1');
encrypt(value: string, key: string): string {
const ivMd5Hash = cryptoJS.MD5(cryptoJS.enc.Utf8.parse(key));
const cipher = this.cipher(cryptoJS.enc.Utf8.parse(value), cryptoJS.enc.Utf8.parse(key), ivMd5Hash);
return cipher.ciphertext.toString();
}
cipher(value, key, iv): any {
const cipher = cryptoJS.AES.encrypt(value, key, {
iv: iv,
mode: cryptoJS.mode.CBC,
keySize: 128,
padding: cryptoJS.pad.Pkcs7
});
return cipher;
}
Note:- It is better to use their default behaviour as it generates different key every time that will be more secure But in my case it was requirement to use fix format.

CryptoJS encrypt in aes-256-cbc returns an unexpected value

I am encrypting some data using CryptoJS and comparing it to an online tool and I am not getting the same result. In fact the result from CryptoJS in not decryptable with the tool.
I am trying to encrypt in AES-256-CBC with the following parameters:
text = '111222333'
iv = 'I8zyA4lVhMCaJ5Kg'
key = '6fa979f20126cb08aa645a8f495f6d85'
Here's my code:
let text = '111222333';
aesEncrypt(data) {
let key = '6fa979f20126cb08aa645a8f495f6d85'; //length 32
let iv = 'I8zyA4lVhMCaJ5Kg'; //length 16
let cipher = CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return cipher.toString();
}
aesEncrypt(text);
The resulting encrypted string is U2FsdGVkX1+f3UywYmIdtb50bzdxASRCSqB00OijOb0= while the one obtained with the online tool is B6AeMHPHkEe7/KHsZ6TW/Q==. Why are they different, I seem to be using the same parameters?
My plan in using CryptoJS is to encrypt some data client side and then be able to decrypt it server side, if needed. But the differences in both encrypted values is stopping me to do so.
How 'bout encoding your data as UTF-8. Just like the "online tool" is doing.
Use CryptoJS.enc.Utf8.parse to achieve what I'm saying.
aesEncrypt (data) {
const key = '6fa979f20126cb08aa645a8f495f6d85'
const iv = 'I8zyA4lVhMCaJ5Kg'
const cipher = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(key), {
iv: CryptoJS.enc.Utf8.parse(iv), // parse the IV
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
})
// e.g. B6AeMHPHkEe7/KHsZ6TW/Q==
return cipher.toString()
}
Code snippet using CryptoJS.
function aesEncrypt (data) {
const key = '6fa979f20126cb08aa645a8f495f6d85'
const iv = 'I8zyA4lVhMCaJ5Kg'
const cipher = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(key), {
iv: CryptoJS.enc.Utf8.parse(iv),
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
})
return cipher.toString()
}
// e.g. B6AeMHPHkEe7/KHsZ6TW/Q==
console.log(aesEncrypt('111222333'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
Working Stackblitz example
Based on WeeGee's answer, added this function aesDecrypt in order to decrypt back the encrypted text and return the string in UTF8. #WeeGee you saved my day.
const key = CryptoJS.enc.Utf8.parse('6fa979f20126cb08aa645a8f495f6d85');
const iv = CryptoJS.enc.Utf8.parse('I8zyA4lVhMCaJ5Kg');
const text = '111222333';
function aesEncrypt(data) {
let cipher = CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return cipher.toString();
}
function aesDecrypt(data) {
let cipher = CryptoJS.AES.decrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return cipher.toString(CryptoJS.enc.Utf8);
}
const encryptedText = aesEncrypt(text);
const decryptedText = aesDecrypt(encryptedText);
console.log('Before Encrypt - ' + text);
console.log('Encrypted Text - ' + encryptedText);
console.log('Decrypted Text - ' + decryptedText);
Output
Before Encrypt - 111222333
Encrypted Text - B6AeMHPHkEe7/KHsZ6TW/Q==
Decrypted Text - 111222333

reading encrypted object in javascript

var token = "WMwiDeJrawUKHif7D5a8yd4ne6Mv";
var salt = "ERtrg56hfg5";
var key = CryptoJS.enc.Hex.parse('B374A26A71490437AA024E4FADD5B497FDFF1A8EA6FF12F6FB65AF2720B59CCF');
var iv = CryptoJS.enc.Hex.parse('7E892875A52C59A3B588306B13C31FBD');
var encrypted = CryptoJS.AES.encrypt(token, key, { iv: iv });
context.setVariable("encryptedtoken", encrypted);
but it is not setting to variable saying it is an object.
what I need to do
I think you have to use encrypted.ciphertext
var encrypted = CryptoJS.AES.encrypt(token, key, { iv: iv });
context.setVariable("encryptedtoken", encrypted.ciphertext);
From CryptoJS documentation:
The ciphertext you get back after encryption isn't a string yet. It's a CipherParams object. A CipherParams object gives you access to all the parameters used during encryption. When you use a CipherParams object in a string context, it's automatically converted to a string according to a format strategy. The default is an OpenSSL-compatible format.
<script>
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
alert(encrypted.key); // 74eb593087a982e2a6f5dded54ecd96d1fd0f3d44a58728cdcd40c55227522223
alert(encrypted.iv); // 7781157e2629b094f0e3dd48c4d786115
alert(encrypted.salt); // 7a25f9132ec6a8b34
alert(encrypted.ciphertext); // 73e54154a15d1beeb509d9e12f1e462a0
alert(encrypted); // U2FsdGVkX1+iX5Ey7GqLND5UFUoV0b7rUJ2eEvHkYqA=
</script>

Categories