1

I am using password based encryption (PBKDF2WithHmacSHA1) using AES-256 (AES/CBC/PKCS5Padding).

In Java, I am using the following encryption and decryption codes and it works fine.

String password = "MyPassword1";
String salt = "MysaltString"; //Will switch to random salt generation.
String plainText = "Quick Brown Fox";


SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 1024, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

/* Encrypt the message. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ciphertext = cipher.doFinal(plainText.getBytes("UTF-8"));

/* Decrypt the message, given derived key and initialization vector. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
String plaintext = new String(cipher.doFinal(ciphertext), "UTF-8");

Now, for interop I need the encrypted string to be decrypted in Javascript. I tried to use forge (https://github.com/digitalbazaar/forge) and I am unable to decrypt.

var password = "MyPassword1";
var salt = "MysaltString"; //Will switch to random salt generation.

var derivedKey = forge.pkcs5.pbkdf2(password, salt, 1024, 32);
input = forge.util.createBuffer(encrypted);
var decipher = forge.cipher.createDecipher('AES-CBC', derivedKey);
decipher.start({iv: iv});
decipher.update(input);
res = decipher.finish();

My guess is it has to do with the format of input supplied to JS (password, salt, IV, encrptedtext), I am just not able to figure it out if it has to be base64, hex etc...

LAX_DEV
  • 2,111
  • 3
  • 19
  • 29
  • Possible duplicate of [AES encryption in javascript and decrypting in java](https://stackoverflow.com/questions/20323765/aes-encryption-in-javascript-and-decrypting-in-java) – Gaurav Tyagi Jun 04 '18 at 11:40
  • @GauravTyagi Its not related to the issue you referenced. I am trying to use forge and decrpt in javascript. – LAX_DEV Jun 04 '18 at 11:56
  • How do you send the data to the javascript ? You should use base64 or hex representation for the data and the IV. – JEY Jun 04 '18 at 12:28

1 Answers1

0

The reason is that Java uses signed bytes. You should use two's complement on the JavaScript side on the IV and the Ciphertext. Your JS code should look like this:

var password = "MyPassword1";
var salt = "MysaltString";
var derivedKey = forge.pkcs5.pbkdf2(password, salt, 1024, 32);

for (var i = 0; i < iv_in.length; i++) {
    iv_in[i] = (iv_in[i] & 0xFF);
}

var iv = String.fromCharCode.apply(String, iv_in);

for (var i = 0; i < encrypted.length; i++) {
    encrypted[i] = (encrypted[i] & 0xFF);
}

var input_c = String.fromCharCode.apply(String, encrypted)

var input = forge.util.createBuffer(input_c);
var decipher = forge.cipher.createDecipher('AES-CBC', derivedKey);
decipher.start({iv: iv});
decipher.update(input);
var res = decipher.finish();

if (res) {
    console.log(decipher.output.toString('utf8'));
}

where iv_in and encrypted are the input byte arrays you receive from Java, for example:

var iv_in = [24, -54, -15, 5, 106, -44, 20, 10, 103, -62, -88, 28, 75, -68, -12, -14];

and

var encrypted = [20, -56, 117, 80, -91, -104, 22, -43, -127, -87, 7, 113, 66, 85, 105, -25]

Iakovos
  • 1,842
  • 4
  • 25
  • 30