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...

3
  • Possible duplicate of AES encryption in javascript and decrypting in java Commented Jun 4, 2018 at 11:40
  • @GauravTyagi Its not related to the issue you referenced. I am trying to use forge and decrpt in javascript. Commented Jun 4, 2018 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. Commented Jun 4, 2018 at 12:28

1 Answer 1

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]

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.