Search code examples
javascriptjavacryptographyaescryptojs

Why can't java decrypt CryptoJS encrypted data?


I have function for decrypting in Java as such

public String decrypt() throws Exception {
        SecretKey secretKey = getSecretKey("o9szYIOq1rRMiouNhNvaq96lqUvCekxR");

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return new String(cipher.doFinal(base64Decode("ASDASDADS")));
    }

public SecretKey getSecretKey(String secretKey) throws Exception {
        byte[] decodeSecretKey = base64Decode(secretKey);
        return new SecretKeySpec(decodeSecretKey, 0, decodeSecretKey.length, "AES");
    }

I tried to encrypt the data using CryptoJS as such

  function aesEncrypt(data, secretKey) {
    var encrypted = CryptoJS.AES.encrypt(data, secretKey, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
    });

    var ciphertext = encrypted.ciphertext.toString();

    var wordArray = CryptoJS.enc.Utf8.parse(ciphertext);
    var base64 = CryptoJS.enc.Base64.stringify(wordArray);
    return base64
  }
  //call the function
  aesEncrypt('Test' , 'o9szYIOq1rRMiouNhNvaq96lqUvCekxR');

When I send the request to JAVA API I get

Given final block not properly padded. Such issues can arise if a bad key is used during decryption

I even tried with forge library. It does not work either.

function aesEncrypt(data, secretKey) {
    var cipher = forge.cipher.createCipher('AES-ECB', secretKey)

    cipher.start()
    cipher.update(forge.util.createBuffer(data))
    cipher.finish()

    return forge.util.encode64(cipher.output.data)
  }

The difference I see between the two is from forge, when I output the data i.e console.log(cipher.output.data) . I get

uJ­@^$¿EÅKÖé1ÙN¢cÖúpxÇÅÂëv¥qè9Ï/¨§È5æý»¸,À¿ "y§¯:ßñ[®ÓjÃùØQèó÷à¯~6jØ¿óðn5»§Ñ ,A.ÛCeða©ëZÁR¸:­jy¹ScÃ6d#ÚÔí\N¤s~ã¯ÃÉ5d0U:©ªÕ"ã¾xx §F?ØïÅFÛbÒÓJ§j ¸²ä2½]Õç£ÿ#È&C! M¡ è ÁÖÈ ¾¦aÒc~: °j>yc6ÞÖú]OAÅÖ!x ìJu2ðΡ¦*õô±¤kÆ ÂTùû=|2^XAy5¹Êè?díXÝg ëq" %üSyÿO¾bzjc²·á­kÑî¼¾¡ÓV *Çr¢ rÎlòz°»yNûöCpã

But from CryptoJS I get console.log(ciphertext)

ad423bc873ca1cc2f228c7158ccf95e67eae4029d5a2e9fbad42e7be7bcad23fcfb94217b90a84c4e6e9786d36edd337615c392a4d260dd68fb6bf45032a31fc6eec99a8f9b5e8efa6e5f2fe2a2b1e68e3a6a57cee0f12d42ff66c986d45da825398213361de9f448b7db0b8a38c79091519105b7c12a4d19998de8e0fb211d81fa1b3d1801d5c8eba907e7aacfa891fa7872e951ee645840e86699c93e98a355ea0f6331889663326f88f0d09b7a6245bd52443f98e6bb274edda32b7135e17d342db77759099688a14ac5edddc7c760e179ad4ad08d9d1fd3b11f1c96be0804c74bf9a9032d07af12e60a76dfddf28984901485e032b33e19db8332a8b49244c9c46081d13c6c632c8792c318a5cc8a7aa4612a76d0b6413367c248b3c0c6e53f301601b0f1bea6ee2b0b5344c445a1da32274c63e81f94dff3db98aae6348c936a2bbac6a3912595c981349556f161d12c843e516aadf95c8ab6be3aaa49d382e5af074575777e8d96964c2fd7a4cad03dd2a9137d8b4ffd85eaaabdd0f86

How to use either of the two? and Why is there a difference between the above output?


Solution

  • Please find below a code pair that uses Javascript to en- and decrypt a string with static key in ECB mode. The Java code is taking the ciphertext (= output of encryption function) from Javascript and decrypts the Base64 encoded ciphertext.

    Security warning: Both codes are UNSECURE as they use the ECB mode and static encryption key.

    Javascript output (see live example with this link: https://playcode.io/682378)

    plaintext: Test
    ciphertext: oNP8t53ZTi1WUptGCDh5NQ==
    decryptedtext: Test
    

    Java output:

    ciphertextFromJavascript: oNP8t53ZTi1WUptGCDh5NQ==
    decrypted: Test
    

    Javascript code:

    // *** Security warning **
    // DO NOT USE THIS CODE IN PRODUCTION AS IT IS UNSECURE
    // it uses ECB mode and static key
    
    var plaintext = 'Test';
    console.log('plaintext: ', plaintext);
    
    /**
     * Encryption
     * @param word
     * @returns {*}
     */
    function encrypt(word){
        const keyBase64 = "o9szYIOq1rRMiouNhNvaq96lqUvCekxR";
        var key = CryptoJS.enc.Base64.parse(keyBase64);
        var srcs = CryptoJS.enc.Utf8.parse(word);
        var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
        return encrypted.toString();
    }
     
    /**
       * Decrypt
     * @param word
     * @returns {*}
     */
    function decrypt(word){
        const keyBase64 = "o9szYIOq1rRMiouNhNvaq96lqUvCekxR";
        var key = CryptoJS.enc.Base64.parse(keyBase64);
        var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
        return CryptoJS.enc.Utf8.stringify(decrypt).toString();
    }
    
    var ciphertext = encrypt(plaintext);
    console.log('ciphertext: ', ciphertext);
    var decryptedtext = decrypt(ciphertext);
    console.log('decryptedtext: ', decryptedtext);
    

    Java code:

    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import java.util.Base64;
    
    public class Main {
        public static void main(String[] args) throws Exception {
            System.out.println("Why can't java decrypt CryptoJS encrypted data ?");
            String ciphertextFromJavascript = "oNP8t53ZTi1WUptGCDh5NQ==";
            System.out.println("ciphertextFromJavascript: " + ciphertextFromJavascript);
            System.out.println("decrypted: " + decrypt(ciphertextFromJavascript));
        }
        public static String decrypt(String ciphertext) throws Exception {
            SecretKey secretKey = getSecretKey("o9szYIOq1rRMiouNhNvaq96lqUvCekxR");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)));
            //return new String(cipher.doFinal(base64Decode("ASDASDADS")));
        }
    
        public static SecretKey getSecretKey(String secretKey) throws Exception {
            byte[] decodeSecretKey = Base64.getDecoder().decode(secretKey);
            //byte[] decodeSecretKey = base64Decode(secretKey);
            return new SecretKeySpec(decodeSecretKey, 0, decodeSecretKey.length, "AES");
        }
    }