0

I have been working on cryptoJs for a week now but the issue I am facing is with Javascript. I am a newbie in Javascript and I really need your help.

I have the following cryptojs based java encryption/decryption codes which works perfectly fine but I am trying to have the Javascript equivalent.

I was getting different encryption.

in java I got: 2BECE44E5375C690FE5785CA9C4814868D620F600AFFA14584B2B7E336742AEF9D52D4102962AD81E9A1267ED48A466B2B739E71FB3433CE9F4ED7661BFA3504C7BA70583E2BC315A1EEE89167F06309D6B3D1CF69DC1028F1396E58150483BF

While in javascript I got: 2a478540c889da6bede186c21c7133d1

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.security.sasl.SaslException;
import javax.security.*;

public class AESCrypter {
    private String iv = "9%Ysr^xyBTrPr!$Y";
    private String secretkey = "GnxUFjKw9(bk7Ay$";
    private IvParameterSpec ivspec;
    private SecretKeySpec keyspec;
    private Cipher cipher;

    public static void main(String args[]) throws UnsupportedEncodingException, Exception {
        AESCrypter crypta = new AESCrypter();
        //String toenc = "1";
        String toenc = " “srcAccount”:\"0011295527\",\r\n" + 
                "“requestId\":\"12345678901234567890\",\r\n" + 
                "“pin”:\"3019\"";
        String enc = "";
        String dec = "";
        // encrypt the value
        //enc = crypta.encrypt(toenc);
        enc = crypta.encrypt(toenc);
        // encrypted value print out
        System.out.println(" ENCED : " + enc);
        // decrypt the value
        dec = crypta.decrypt(enc);
        // decrypted value print out
        System.out.println(" DECED : " + dec);
    }

    public AESCrypter(String keyz, String ivStr) {
        ivspec = new IvParameterSpec(ivStr.getBytes());
        keyspec = new SecretKeySpec(keyz.getBytes(), "AES");
        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    public AESCrypter()
    {
    ivspec = new IvParameterSpec(iv.getBytes());
    keyspec = new SecretKeySpec(secretkey.getBytes(), "AES");
    System.out.println("this ivspec = " + ivspec);
    try
    {
    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    }
    catch (NoSuchAlgorithmException e)
    {
    e.printStackTrace();
    }
    catch (NoSuchPaddingException e)
    {
    e.printStackTrace();
    }}

    public String encrypt(String text) throws SecurityException {
        System.out.println("text = " + text);
        if (text == null || text.length() == 0) {
            throw new SecurityException("Empty string");
        }
        byte[] encrypted = null;
        try {
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            encrypted = cipher.doFinal(text.getBytes("UTF-8"));
        } catch (Exception e) {
            throw new SecurityException("[encrypt] " + e.getMessage());
        }
        return bytesToHex(encrypted);
    }

    public String decrypt(String code) throws SecurityException, UnsupportedEncodingException {
        if (code == null || code.length() == 0) {
            throw new SecurityException("Empty string");
        }
        byte[] decrypted = null;
        try {
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            decrypted = cipher.doFinal(hexToBytes(code));
        } catch (Exception e) {
            e.printStackTrace();
            throw new SecurityException("[decrypt] " + e.getMessage());
        }
        return new String(decrypted, "UTF-8");
    }

    public static String bytesToHex(byte[] data)
    {
    if (data==null) {
    return null;
    }
    int len = data.length;
    String str = "";
    for (int i=0; i<len; i++)
    {
    

    if ((data[i]&0xFF)<16) {
    str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
    }
    else {
    str = str + java.lang.Integer.toHexString(data[i]&0xFF);
    }}return str;

    }

    public static byte[] hexToBytes(String str) {
        if (str == null) {
            return null;
        } else if (str.length() < 2) {
            return null;
        } else {
            int len = str.length() / 2;
            byte[] buffer = new byte[len];
            for (int i = 0; i < len; i++) {
                buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
            }
            return buffer;
        }
    }
}

Trying to solve it in Javascript I did the following:

      let iv = "tzsee5eWyBlpTHSn";
        let secret_key = "IhrhcWT@HsH!l6#M";
        let body = {"srcAccount" : user_login, 
                    "requestId" : "12345678901234567890",
                    "pin" : user_password};
        
    
    body = CryptoJS.enc.Utf8.parse(body);
    secret_key = CryptoJS.enc.Latin1.parse(secret_key);
    iv = CryptoJS.enc.Latin1.parse(iv);
    
    var encrypted = CryptoJS.AES.encrypt(body, secret_key, { iv: iv, 
    padding: CryptoJS.pad.Pkcs7, 
    mode: CryptoJS.mode.CBC
});

var encrypted = CryptoJS.enc.Hex.parse(iencrypted.ciphertext.toString());
console.log(" Encrypted  " +encrypted);

Could someone please point me to the right direction.

5
  • It looks like you're on the right track. Does the code above encrypt your data? What's missing? What's it doing that it should not be doing? If you put console.log(encrypted); on the line after your last line, did the function work? Commented Sep 16, 2020 at 13:10
  • Why CryptoJS.pad.NoPadding? That's wrong since you're using PKCS#5 (=PKCS#7) padding. Also use the same IV and key for both. Commented Sep 16, 2020 at 16:56
  • The IV doesn't have to be secret. For CBC mode it needs to be unpredictable. We usually write it in front of the ciphertext during encryption and slice it off before decryption. Commented Sep 16, 2020 at 16:57
  • @ArtjomB.Could you please help me with the code sample? I have updated my question also. Thanks. Commented Sep 16, 2020 at 17:19
  • @ArtjomB. I did use the same iv. Commented Sep 16, 2020 at 17:26

1 Answer 1

3

As you are using different key and iv values in Java and Javascript it is ovious that you will different results in Java and Javascript, as you already were told from @Artjom B.

As well your "message to encrypt" ("toenc" or "body") differs as well and won't get the same result.

I setup a simplified Java program and adjusted some missing charset encodings. For simplicity I used just a simple string to test the en- and decryption on both sides - I leave it up to you to find an identical solution for your "message to encrypt" on Java and Javascript.

The Javascript program is using CryptoJS for encryption and gets the same input values for key, iv and plaintext.

Both programs give the same encrypted value in hex:

525106e181b2ad0b507439f54d690dfaa6e22ae2c96cde79c532a2b868d5e824637b91cc59854592343c26c39f83f452

Please note: both programs do not have any exception handling and are for educational purpose only.

For a live test I setup two "fiddles" where you can test the programs with your own values:

Java: https://paiza.io/projects/e/tMzKTcUrBFCgvrTKf4hVow Javascript: https://playcode.io/672028/

Java code:

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;

public class Main {
    private String iv = "9%Ysr^xyBTrPr!$Y";
    private String secretkey = "GnxUFjKw9(bk7Ay$";
    private IvParameterSpec ivspec;
    private SecretKeySpec keyspec;
    private Cipher cipher;

    public static void main(String args[]) throws UnsupportedEncodingException, Exception {
        Main crypta = new Main();
        //String toenc = "1";
        /*
        String toenc = " “srcAccount”:\"0011295527\",\r\n" +
                "“requestId\":\"12345678901234567890\",\r\n" +
                "“pin”:\"3019\"";
        */
        String toenc = "The quick brown fox jumps over the lazy dog";
        String enc = "";
        String dec = "";
        // encrypt the value
        //enc = crypta.encrypt(toenc);
        enc = crypta.encrypt(toenc);
        // encrypted value print out
        System.out.println(" ENCED : " + enc);
        // decrypt the value
        dec = crypta.decrypt(enc);
        // decrypted value print out
        System.out.println(" DECED : " + dec);
    }

    public Main(String keyz, String ivStr) {
        ivspec = new IvParameterSpec(ivStr.getBytes(StandardCharsets.UTF_8));
        keyspec = new SecretKeySpec(keyz.getBytes(StandardCharsets.UTF_8), "AES");
        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    public Main()
    {
        ivspec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        keyspec = new SecretKeySpec(secretkey.getBytes(StandardCharsets.UTF_8), "AES");
        System.out.println("this ivspec = " + ivspec);
        try
        {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
        }}

    public String encrypt(String text) throws SecurityException {
        System.out.println("text = " + text);
        if (text == null || text.length() == 0) {
            throw new SecurityException("Empty string");
        }
        byte[] encrypted = null;
        try {
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            encrypted = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            throw new SecurityException("[encrypt] " + e.getMessage());
        }
        return bytesToHex(encrypted);
    }

    public String decrypt(String code) throws SecurityException, UnsupportedEncodingException {
        if (code == null || code.length() == 0) {
            throw new SecurityException("Empty string");
        }
        byte[] decrypted = null;
        try {
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            decrypted = cipher.doFinal(hexToBytes(code));
        } catch (Exception e) {
            e.printStackTrace();
            throw new SecurityException("[decrypt] " + e.getMessage());
        }
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    public static String bytesToHex(byte[] data)
    {
        if (data==null) {
            return null;
        }
        int len = data.length;
        String str = "";
        for (int i=0; i<len; i++)
        {
            if ((data[i]&0xFF)<16) {
                str = str + "0" + Integer.toHexString(data[i]&0xFF);
            }
            else {
                str = str + Integer.toHexString(data[i]&0xFF);
            }}return str;
    }

    public static byte[] hexToBytes(String str) {
        if (str == null) {
            return null;
        } else if (str.length() < 2) {
            return null;
        } else {
            int len = str.length() / 2;
            byte[] buffer = new byte[len];
            for (int i = 0; i < len; i++) {
                buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
            }
            return buffer;
        }
    }
}

Javascript code:

let iv = '9%Ysr^xyBTrPr!$Y';
let secret_key = 'GnxUFjKw9(bk7Ay$';
let plaintext = 'The quick brown fox jumps over the lazy dog';
console.log('plaintext: ', plaintext);

plaintext = CryptoJS.enc.Utf8.parse(plaintext);
secret_key = CryptoJS.enc.Utf8.parse(secret_key);
iv = CryptoJS.enc.Utf8.parse(iv);

var ciphertext = CryptoJS.AES.encrypt(plaintext, secret_key, {
  iv: iv,
  padding: CryptoJS.pad.Pkcs7,
  mode: CryptoJS.mode.CBC,
});

console.log('ciphertext: ', ciphertext.ciphertext.toString());

var decrypted = CryptoJS.AES.decrypt(ciphertext, secret_key,{
  iv: iv,
  padding: CryptoJS.pad.Pkcs7,
  mode: CryptoJS.mode.CBC,
});

console.log('decrypted (hex): ', decrypted.toString());
console.log('decrypted (str): ', CryptoJS.enc.Utf8.stringify(decrypted).toString());
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.