简体   繁体   English

Java中的AES加密无法用Javascript解密

[英]AES encryption in Java unable to decrypt in Javascript

I am using password based encryption (PBKDF2WithHmacSHA1) using AES-256 (AES/CBC/PKCS5Padding). 我正在使用使用AES-256(AES / CBC / PKCS5Padding)的基于密码的加密(PBKDF2WithHmacSHA1)。

In Java, I am using the following encryption and decryption codes and it works fine. 在Java中,我正在使用以下加密和解密代码,并且工作正常。

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. 现在,对于互操作,我需要使用Javascript解密加密的字符串。 I tried to use forge ( https://github.com/digitalbazaar/forge ) and I am unable to decrypt. 我尝试使用伪造( https://github.com/digitalbazaar/forge ),但无法解密。

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... 我的猜测是它与提供给JS的输入格式(密码,salt,IV,encrptedtext)有关,我只是无法弄清楚它是否必须是base64,hex等。

The reason is that Java uses signed bytes. 原因是Java使用带符号的字节。 You should use two's complement on the JavaScript side on the IV and the Ciphertext. 您应该在IV和Ciphertext的JavaScript端使用二进制补码。 Your JS code should look like this: 您的JS代码应如下所示:

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: 其中iv_inencrypted是您从Java接收的输入字节数组,例如:

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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM