2

I am encrypting a text in NODEJS and trying decrypt in Java but getting error. my nodejs code:

var crypto = require('crypto')
  , key = 'mykey@91'
  , plaintext = 'SS18617710213463'
  , cipher = crypto.createCipher('aes-128-ecb', key)
  , decipher = crypto.createDecipher('aes-128-ecb', key);



var encryptedPassword = cipher.update(plaintext, 'utf8', 'base64');

encryptedPassword += cipher.final('base64')

var decryptedPassword = decipher.update(encryptedPassword, 'base64', 'utf8');
decryptedPassword += decipher.final('utf8');

console.log('original  :', plaintext); 
console.log('encrypted :', encryptedPassword);
console.log('decrypted :', decryptedPassword);

but when I am trying to decrypt it, it always throws an error.

public static String decrypt(String encryptedText) {
    try {
         final String key = "mykey@91";
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] cipherText = Base64.getDecoder().decode(encryptedText.getBytes("UTF8"));
        String decryptedString = new String(cipher.doFinal(cipherText),"UTF8");
        return decryptedString;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

The error I am getting as below:

java.security.InvalidKeyException: Invalid AES key length: 8 bytes

Mittal Patel
  • 2,732
  • 14
  • 23
Srinivas VK
  • 23
  • 1
  • 4
  • From the [documentation](https://nodejs.org/api/crypto.html#crypto_crypto_createcipher_algorithm_password_options): "The implementation of crypto.createCipher() derives keys using the OpenSSL function EVP_BytesToKey with the digest algorithm set to MD5, one iteration, and no salt. The lack of salt allows dictionary attacks as the same password always creates the same key. The low iteration count and non-cryptographically secure hash algorithm allow passwords to be tested very rapidly." – President James K. Polk Jul 05 '18 at 16:13

1 Answers1

4

The reason you are getting Invalid AES key length: 8 bytes invalid AES is related to length of your key and text. You need to make sure that its length in bits is a power of two. If you want to use a String as your encryption key, check its length in bytes and multiply by 8 to find the length in bits. Also most String implementation will require 2 bytes for every character (Java 64bit). Detailed information here: How to solve InvalidKeyException

In this case, the mentioned error will disappear just using a padded or longer key, for example:

static String PLAIN_TEXT = "SS18617710213463"; 
static String ENCRYPTION_KEY = "mykey@91mykey@91";

However there is another important thing to consider. The Java Implementation has to match the exact algorithms provided by node.js. This is not as easy as it sounds (at least based on my experience). In your case, I would suggest you to use node-forge on node.js side which is easier to match Java implementations:

var forge = require('node-forge');

var plaintext = 'SS18617710213463';  
var key = 'mykey@91mykey@91';
var iv = 'AODVNUASDNVVAOVF';

console.log('Plain Text: ' + plaintext); 

var cipher = forge.cipher.createCipher('AES-CBC', key);
cipher.start({iv: iv});
cipher.update(forge.util.createBuffer(plaintext));
cipher.finish();
var encrypted = cipher.output;

var encodedB64 = forge.util.encode64(encrypted.data);
console.log("Encoded: " + encodedB64);

var decodedB64 = forge.util.decode64(encodedB64);
encrypted.data = decodedB64;

var decipher = forge.cipher.createDecipher('AES-CBC', key);
decipher.start({iv: iv});
decipher.update(encrypted);
var result = decipher.finish(); 

console.log("Decoded: " + decipher.output.data);

Running the code above, the output should be:

Plain Text: SS18617710213463
Encoded: HCzZD7uc13fqfM6odWcXf/mdR4aNJfkMDhEbnU+asjE=
Decoded: SS18617710213463

And the compatible Java code that will work on the same way looks like the code below:

import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Main {

    static String PLAIN_TEXT = "SS18617710213463"; 
    static String ENCRYPTION_KEY = "mykey@91mykey@91";
    static String INITIALIZATIO_VECTOR = "AODVNUASDNVVAOVF";

    public static void main(String [] args) {
        try {

            System.out.println("Plain text: " + PLAIN_TEXT);

            byte[] encryptedMsg = encrypt(PLAIN_TEXT, ENCRYPTION_KEY);
            String base64Encrypted = Base64.getEncoder().encodeToString(encryptedMsg);
            System.out.println("Encrypted: "+  base64Encrypted);

            byte[] base64Decrypted = Base64.getDecoder().decode(base64Encrypted);
            String decryptedMsg = decrypt(base64Decrypted, ENCRYPTION_KEY);
            System.out.println("Decrypted: " + decryptedMsg);
        } catch (Exception e) { 
            e.printStackTrace();
        } 
    }

    public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/pkcs5padding", "SunJCE");
        SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
        return cipher.doFinal(plainText.getBytes("UTF-8"));
      }

      public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
        Cipher cipher = Cipher.getInstance("AES/CBC/pkcs5padding", "SunJCE");
        SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
        cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
        return new String(cipher.doFinal(cipherText),"UTF-8");
      }
}

Which produces:

Plain text: SS18617710213463
Encrypted: HCzZD7uc13fqfM6odWcXf/mdR4aNJfkMDhEbnU+asjE=
Decrypted: SS18617710213463
Marcio Jasinski
  • 1,439
  • 16
  • 22