Search code examples
javanode.jsencryptionaes

AES/CBC/PKCS5PADDING IV - Decryption in NodeJs (Encrypted in Java)


I am trying to decrypt in NodeJs. It is working in Java. But I am not able to achieve same in Node.

node-version: 8.4

Please find my NodeJs code:

var crypto = require('crypto');
function decryption (message, key) {
var messageArray = Buffer.from(message, 'base64');
  // var kekbuf =  Buffer(key, 'utf8');

  var ivBuffer = new Buffer([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
  var iv = ivBuffer.slice(0, 16);

  var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
  decipher.setAutoPadding(false);
  var dec = decipher.update(messageArray, 'base64');

  dec += decipher.final();
  return dec.toString();
}

Please find working Java decryption code

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

class Test1 {
  public String decrypt(String message, String key) throws Exception {
    DatatypeConverter dtc = null;
    byte[] messagArray = dtc.parseBase64Binary(message);
    byte[] keyArray = dtc.parseBase64Binary(key);

    byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    IvParameterSpec ivspec = new IvParameterSpec(iv);

    SecretKey secretKey = new SecretKeySpec(keyArray, "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");

    cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);
    return new String(cipher.doFinal(messagArray));
  }
}

I am getting a different decrypted text. I am not able to achieve the same result in NodeJs as I had in Java. Also, I could not modify my java encryption code. So I have to figure out decryption in Node.

Could you please help me with this.


Solution

  • Here are complete examples in Java and also Node.js, they use the same keys/iv/plaintext and will produce identical results.

    Java

    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import javax.xml.bind.DatatypeConverter;
    import java.nio.charset.StandardCharsets;
    
    class AES
    {
        public AES()
        {
        }
    
        public String encrypt(String plainText, String keyBase64, String ivBase64) throws Exception
        {
            byte[] plainTextArray = plainText.getBytes(StandardCharsets.UTF_8);
            byte[] keyArray = DatatypeConverter.parseBase64Binary(keyBase64);
            byte[] iv = DatatypeConverter.parseBase64Binary(ivBase64);
            
            SecretKeySpec secretKey = new SecretKeySpec(keyArray, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");   
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));
            return new String(DatatypeConverter.printBase64Binary(cipher.doFinal(plainTextArray)));
        }
        
        public String decrypt(String messageBase64, String keyBase64, String ivBase64) throws Exception {
    
            byte[] messageArray = DatatypeConverter.parseBase64Binary(messageBase64);
            byte[] keyArray = DatatypeConverter.parseBase64Binary(keyBase64);
            byte[] iv = DatatypeConverter.parseBase64Binary(ivBase64);
    
            SecretKey secretKey = new SecretKeySpec(keyArray, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
            return new String(cipher.doFinal(messageArray));
        }
      
        public static void main(String[] args) {
        
            try
            {   
                String plainText = "Hello world!";
                String encryptionKeyBase64 = "DWIzFkO22qfVMgx2fIsxOXnwz10pRuZfFJBvf4RS3eY=";
                String ivBase64 = "AcynMwikMkW4c7+mHtwtfw==";
                
                AES AES = new AES();
                
                String cipherText = AES.encrypt(plainText, encryptionKeyBase64, ivBase64);
                String decryptedCipherText = AES.decrypt(cipherText, encryptionKeyBase64, ivBase64);
                
                System.out.println("Plaintext: " + plainText);
                System.out.println("Ciphertext: " + cipherText);
                System.out.println("Decrypted text: " + decryptedCipherText);
            }
            catch (Exception e)
            {
                System.out.println(e.toString());
            }
        }
    }
    

    Node.js

    var crypto = require('crypto');
    
    function getAlgorithm(keyBase64) {
        
        var key = Buffer.from(keyBase64, 'base64');
        switch (key.length) {
            case 16:
                return 'aes-128-cbc';
            case 32:
                return 'aes-256-cbc';
                
        }
        
        throw new Error('Invalid key length: ' + key.length);
    }
    
    
    function encrypt(plainText, keyBase64, ivBase64) {
    
        const key = Buffer.from(keyBase64, 'base64');
        const iv = Buffer.from(ivBase64, 'base64');
    
        const cipher = crypto.createCipheriv(getAlgorithm(keyBase64), key, iv);
        let encrypted = cipher.update(plainText, 'utf8', 'base64')
        encrypted += cipher.final('base64');
        return encrypted;
    };
    
    function decrypt (messagebase64, keyBase64, ivBase64) {
    
        const key = Buffer.from(keyBase64, 'base64');
        const iv = Buffer.from(ivBase64, 'base64');
    
        const decipher = crypto.createDecipheriv(getAlgorithm(keyBase64), key, iv);
        let decrypted = decipher.update(messagebase64, 'base64');
        decrypted += decipher.final();
        return decrypted;
    }
    
    
    var keyBase64 = "DWIzFkO22qfVMgx2fIsxOXnwz10pRuZfFJBvf4RS3eY=";
    var ivBase64 = 'AcynMwikMkW4c7+mHtwtfw==';
    var plainText = 'Why, then, ’tis none to you, for there is nothing either good or bad, but thinking makes it so';
    
    var cipherText = encrypt(plainText, keyBase64, ivBase64);
    var decryptedCipherText = decrypt(cipherText, keyBase64, ivBase64);
    
    console.log('Algorithm: ' + getAlgorithm(keyBase64));
    console.log('Plaintext: ' + plainText);
    console.log('Ciphertext: ' + cipherText);
    console.log('Decoded Ciphertext: ' + decryptedCipherText);