Domenico Cinalli
Domenico Cinalli

Reputation: 21

AES decryption returning empty string

Hello i'm trying to encrypt and decrypt files (in Uint8Array format) using CryptoJS Library (3.1.2) This is my code:

var WPAES = {
    keySize: 256,
    ivSize: 128,
    saltSize: 128,
    iterations:1000,
    encrypt: function(data,passphrase)
    {
        try
        {
            var iv = CryptoJS.lib.WordArray.random(this.ivSize/8);
            console.log(iv.toString());
            var salt = CryptoJS.lib.WordArray.random(this.saltSize/8);
            console.log(salt.toString());

            var key = CryptoJS.PBKDF2(passphrase, salt, {
              keySize: this.keySize/32,
              iterations: this.iterations
            });
            var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.u8array.parse(data), key, {
                iv: iv,
                padding: CryptoJS.pad.Pkcs7,
                mode: CryptoJS.mode.CBC

            });

            var encryptedIv = CryptoJS.enc.u8array.stringify(iv);
            var encryptedSalt = CryptoJS.enc.u8array.stringify(salt);
            var encryptedArray = CryptoJS.enc.u8array.stringify(encrypted.ciphertext);

            var message = new Uint8Array(encryptedIv.length + encryptedSalt.length + encryptedArray.length);
            message.set(encryptedIv);
            message.set(encryptedSalt, encryptedIv.length);
            message.set(encryptedArray, encryptedIv.length+encryptedSalt.length);
            return message;
        }
        catch(e)
        {
            console.log(e);
            return false;
        }

    },
    decrypt: function(data,passphrase)
    {
        try
        {
            var iv = CryptoJS.enc.u8array.parse(data.slice(0, this.ivSize/8));
            console.log(iv.toString());
            var salt = CryptoJS.enc.u8array.parse(data.slice(this.ivSize/8, this.ivSize/8+this.saltSize/8))
            console.log(salt.toString());
            var encrypted = CryptoJS.enc.u8array.parse(data.slice(this.ivSize/8+this.saltSize/8));
            var key = CryptoJS.PBKDF2(passphrase, salt, {
              keySize: this.keySize/32,
              iterations: this.iterations
            });
            var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
                iv: iv,
                padding: CryptoJS.pad.Pkcs7,
                mode: CryptoJS.mode.CBC

            });
            var res = CryptoJS.enc.u8array.stringify(decrypted.ciphertext);

            return res;
        }
        catch(e)
        {
            console.log(e);
            return false;
        }

    }
}

I'm also use:

CryptoJS.enc.u8array = {
        stringify: function (wordArray) {
            var words = wordArray.words;
            var sigBytes = wordArray.sigBytes;
            var u8 = new Uint8Array(sigBytes);
            for (var i = 0; i < sigBytes; i++) {
                var byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
                u8[i]=byte;
            }
            return u8;
        },
        parse: function (u8arr) {
            var len = u8arr.length;
            var words = [];
            for (var i = 0; i < len; i++) {
                words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8);
            }
            return CryptoJS.lib.WordArray.create(words, len);
        }
    };

But when i decrypt the file the results is empty. Ialso check the iv, salt and the encrypted message. All seems work except for the decryption that always returns an empty value.

How can i fix this problem?

Thank you!

Upvotes: 0

Views: 3199

Answers (2)

Manish Mudgal
Manish Mudgal

Reputation: 1186

Given it a long try and finally got it.

1). CryptoJS uses hex values while java uses bytes for the same String.

2.) The two other factors which need to be same (apart from the key) are initVector and padding.

Considering both above we first have to validate that both Java are CryptoJS and encrypting to the same value given the above parameters are same.

Here is the code for Java

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.Base64;

public class JavaEncryptor {

    private static final String key = "aesEncryptionKey";
    private static final String initVector = "encryptionIntVec";

    public static String toHex(String arg) throws UnsupportedEncodingException {
        return String.format("%020x", new BigInteger(1, arg.getBytes("UTF-8")));
    }


    /**
     * Use these hex value in CryptoJS
     * @throws Exception
     */
    public static void printHexForJS() throws Exception {
        System.out.println("HexKeyForJS :  "+ toHex(key));
        System.out.println("HexInitVectorForJS :  "+ toHex(initVector));
    }

    public static String encrypt(String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");


            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes()); 
            return Base64.getEncoder().encodeToString(encrypted);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        printHexForJS();
        System.out.println(encrypt("MyPlainTextToBeEncrypted"));
    }

}

Output of the above program is

HexKeyForJS : 616573456e6372797074696f6e4b6579 HexInitVectorForJS : 656e6372797074696f6e496e74566563 MURKOx14eSOo2vs8ZQyCpXpsoKg8Uzlvyj3byQreVBk=

And then for JS encryption use the HexKeyForJS and HexInitVectorForJS as in below code

var text = "ManishMudgal";
var key = CryptoJS.enc.Hex.parse(HexKeyForJS);
var iv  = CryptoJS.enc.Hex.parse(HexInitVectorForJS);

var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv, padding: CryptoJS.pad.Pkcs7});
console.log(encrypted.toString());

Output of the above JS code should be kBgYcrSxz+kbXRnyKIFmSw==

Which is the same encrypted key generated through Java code MURKOx14eSOo2vs8ZQyCpXpsoKg8Uzlvyj3byQreVBk=

Now Decryption at Crypto End

CryptoJS.AES.decrypt('MURKOx14eSOo2vs8ZQyCpXpsoKg8Uzlvyj3byQreVBk=', CryptoJS.enc.Hex.parse(HexKeyForJS), {iv: CryptoJS.enc.Hex.parse(HexInitVectorForJS), padding: CryptoJS.pad.Pkcs7}).toString(CryptoJS.enc.Utf8);

Cheers :)

Upvotes: 2

Domenico Cinalli
Domenico Cinalli

Reputation: 21

I solved using:

 var decrypted = CryptoJS.AES.decrypt({ciphertext:encrypted}, key, {
       iv: iv,
       padding: CryptoJS.pad.Pkcs7,
       mode: CryptoJS.mode.CBC

 });

in decrypt function.

Upvotes: 2

Related Questions