Search code examples
javascriptjavaaescryptojs

Java decode AES encoded message issue


This is my java program:

package com.util;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;

public class Coder1 {

    public static int AES_KEY_SIZE = 256 ;
    public static int IV_SIZE = 16 ;
    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException 
    {
        String message = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        message =message +message;
        message =message +message;
        KeyGenerator keygen = KeyGenerator.getInstance("AES") ; // Specifying algorithm key will be used for 
        keygen.init(AES_KEY_SIZE) ; // Specifying Key size to be used, Note: This would need JCE Unlimited Strength to be installed explicitly 
        SecretKey aesKey = keygen.generateKey();

        // Generating IV
        byte iv[] = new byte[IV_SIZE];

        SecureRandom secRandom = new SecureRandom() ;
        secRandom.nextBytes(iv);
        Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING");
        Cipher decipher = Cipher.getInstance("AES/CTR/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, aesKey,new IvParameterSpec(iv));
        decipher.init(Cipher.DECRYPT_MODE, aesKey,new IvParameterSpec(iv));
        byte[] cipherTextInByteArr = cipher.doFinal(message.getBytes());
        byte[] plainTextInByteArr = decipher.doFinal(cipherTextInByteArr);
        System.out.println("Key="+Base64.getEncoder().encodeToString(aesKey.getEncoded())+"|");
        System.out.println("IV="+Base64.getEncoder().encodeToString(iv)+"|");
        System.out.println("Encrypted Text=" + Base64.getEncoder().encodeToString(cipherTextInByteArr)+"|") ;
        System.out.println("Decrypted text=" + new String(plainTextInByteArr));
    }

}

In order to decode the output of the above java program, which javascript library should I use? I want to setup a secure websocket channel. I have tried using RSA algorithm. Unfortunately, it does not support the message size larger than 128 byte.

I follow the example in here. It work fine in java side, however, I don't know how to send SealedObject to javascript side, therefore, dead end again.

The java program output as follow:

Key=hlnUjh4GM1PegSzl13YFQgI5+I1qcbsmqlBV8vDsVy0=|
IV=ZkqiRuDS7YUrjZMLRr/gfQ==|
Encrypted Text=HFROj40Qh9YagJAS+7saN2/ugqszCPpmjT9Qwy2yt9dCntSbpbYqTt/tW0ju5QO614+S9zQyOdBXFKtNdDew9Ouo9YkmRgRkjY7NNGyVbt+Z5CYCgcwpRmNUuH7Fqyat5H3hFSUi05UyLLA6lIa47wyP7jKsq0rtj1yHth8qN06aisB18s4Cf9YBPbUM72qXS+IcpKLMWEVVw7Q0qA91WRCt9y93SptNUme75D/qCKyym20UJ5f0ZCgijOnnsbWJKci1R179qZ8UthFBjqcZm88VmV1UuA7OsAvzxsyA7iVtwsf9u6UnrlOtoMTl41Q5nLod4unkdbomrXb6hDKhV9ThtCy1ZWPFHhKbEAPMdzUnmmBSwcuGSTKvdPJeHAWH|
Decrypted text=abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890

According to the post here, the Crypto-JS can decode the Java output successfully.

However, the java program cannot decode the javascript output sucessfully. Here is my javascript progarm

    <script src="js/cryptojs/rollups/aes.js"></script>
    <script src="js/cryptojs/components/mode-ctr-min.js"></script>
    <script language=javascript>
          ..................
      var result;
      var encoded=CryptoJS.AES.encrypt("hello",
                                       keyArray,
                                       {
                                         iv: ivArray,
                                         mode: CryptoJS.mode.CTR,
                                         padding: CryptoJS.pad.Pkcs7
                                        });

      result=encoded.ciphertext.toString(CryptoJS.enc.Base64);
   </script>

My java program:

   byte iv[] = new byte[16];
   SecureRandom secRandom = new SecureRandom() ;
   secRandom.nextBytes(iv);       
   Cipher decipher = Cipher.getInstance("AES/CTR/PKCS5PADDING");
   decipher.init(Cipher.DECRYPT_MODE, aesKey,new IvParameterSpec(iv)); 
   byte[] cipherTextInByteArr =Base64.getDecoder().decode(encodedText);
   byte[] plainTextInByteArr = decipher.doFinal(cipherTextInByteArr);     
   String result=new String(plainTextInByteArr,"UTF-8");

However,the output is "hello???????". Is there something wrong?


Solution

  • Finally, I get it works. According to this post, CTR mode does not require padding. Therefore the javascript program look like:

    <script src="js/cryptojs/rollups/aes.js"></script>
    <script src="js/cryptojs/components/mode-ctr-min.js"></script>
    <script language=javascript>
          ..................
      var result;
      var encoded=CryptoJS.AES.encrypt("hello",
                                       keyArray,
                                       {
                                         iv: ivArray,
                                         mode: CryptoJS.mode.CTR,
                                         padding: CryptoJS.pad.NoPadding
                                        });
    
      result=encoded.ciphertext.toString(CryptoJS.enc.Base64);
    </script>
    

    And the java program look like:

    byte iv[] = new byte[16];
    SecureRandom secRandom = new SecureRandom() ;
    secRandom.nextBytes(iv);       
    Cipher decipher = Cipher.getInstance("AES/CTR/NoPadding");
    decipher.init(Cipher.DECRYPT_MODE, aesKey,new IvParameterSpec(iv)); 
    byte[] cipherTextInByteArr =Base64.getDecoder().decode(encodedText);
    byte[] plainTextInByteArr = decipher.doFinal(cipherTextInByteArr);     
    String result=new String(plainTextInByteArr,"UTF-8");