2
votes

I am currently using Angular7. I have Java encryption, decryption code implemented with me given by client, same I need to in Angular.

Below is code for Java.

import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

Inside Class I have

class EnDc(String passPhrase)
{
    private static final byte[] SALT = { 8 random numbers between -127 to 127 };
    private static final int ITERATION_COUNT = 1000;
    private static final int KEY_LENGTH = 256;
    private static final int IV_LENGTH = 16;
    private Cipher eCipher;
    private Cipher dCipher;
    private byte[] encrypt;
    private byte[] iv;

Generation of hashed key and iv is as below:

    SecretKeyFactory secretKeyFactory = 
            SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT, 
            1000, 256);

They have generated temp secret key with keyspec as follows :

    secretKeyTemp = secretKeyFactory.generateSecret(keySpec);

Generated new secret key with temp key and with "AES"

    secretKey = new SecretKeySpec(secretKeyTemp.getEncoded(), //encode 
            "AES");

Next Steps :

    this.eCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    this.eCipher.init(1, secretKey);
    // 1 - ENCRYPT_MODE, 2 - DECRYPT_MODE

IV generation :

    this.iv = ((IvParameterSpec)this.eCipher.getParameters().getParameterSpec(IvParameterSpec.class)).getIV();

}

Actual Encrypt function as below

public String encrypt(String encrypt)
      {
        String encStr = null;
        try
        {
          byte[] bytes = encrypt.getBytes("UTF8");
          byte[] encrypted = encrypt(bytes);
          byte[] cipherText = new byte[encrypted.length + this.iv.length];
          System.arraycopy(this.iv, 0, cipherText, 0, this.iv.length);
          System.arraycopy(encrypted, 0, cipherText, this.iv.length, encrypted.length);
          encStr = new String(Base64.getEncoder().encode(cipherText));
        }
        catch (Exception ex)
        {
          ex.printStackTrace();
        }
        return encStr;
      }

I am trying to implement this in Service file in Angular, Here as per my understanding here SALT byte array is predefined and IV is random which is appended before encrypted string and extracted while decryption,

So JS way I tried as below

import * as CryptoJS from 'crypto-js';

encrypt (msg, pass) {
  const salt = CryptoJS.lib.WordArray.random(128 / 8);

  const key = CryptoJS.PBKDF2( pass, salt, {
      keySize: this.keySize / 32,
      iterations: this.iterations
  });

  const iv =  CryptoJS.lib.WordArray.random(128 / 8);
  const encrypted = CryptoJS.AES.encrypt(msg, key, {
    iv: iv,
    padding: CryptoJS.pad.Pkcs7,
    mode: CryptoJS.mode.CBC
  });

  const transitmessage = salt.toString() + iv.toString() + encrypted.toString();
  return transitmessage;
}

So, I have done this code from link http://www.adonespitogo.com/articles/encrypting-data-with-cryptojs-aes/ , so now question is how can I implement SALT which is hard coded in JAVA, and also inside JAVA code they have not sent salt key attached with Encrypted String, but IV only as first 16 bits. How can I implement this ?

I have tried to do like this

salt = CryptoJS.lib.WordArray.create([-67, -85, 13, -28, 75, 112, -126, 103]);

but key getting generated is object and also I am getting error while decrypting

Edit 1: I want salt to be same each time which I am currently generating as random and attaching to encrypted string.

I don't know if there is some implementation of SecretKeyFactory and Keyspec for Javascript

Help Appreciated, Thanks in Advance.

2

2 Answers

2
votes

Please find below solution if it works for you.

encrypt (msg, pass) {
    const key = CryptoJS.PBKDF2(pass, this.salt, {
        keySize: this.keySize / 32,
        iterations: this.iterations
    });

    const iv =  CryptoJS.lib.WordArray.random(128 / 8);

    const encrypted = CryptoJS.AES.encrypt(msg, key, {
          iv: iv,
          padding: CryptoJS.pad.Pkcs7,
          mode: CryptoJS.mode.CBC
    });

    const transitmessage = iv + encrypted.ciphertext;
    var tm=CryptoJS.enc.Hex.parse(transitmessage); // This converts to Type Word which is required for below function as input
    return CryptoJS.enc.Base64.stringify(tm); // Encoding
}
1
votes

When you do below, WordArray.create method uses your numbers as 32-bits integers:

salt = CryptoJS.lib.WordArray.create([-67, -85, 13, -28, 75, 112, -126, 103]);

In this case your salt in hex is:

ffffffbdffffffab0000000dffffffe40000004b00000070ffffff8200000067

If you convert javascript Array object to Int8Array, CryptoJS will create the same salt as in Java:

salt = CryptoJS.lib.WordArray.create(new Int8Array([-67, -85, 13, -28, 75, 112, -126, 103]));

Result:

bdab0de44b708267