我有以下用Javascript编写的函数,用于使用aes-256-gcm加密:
encrypt: function (text, masterkey){
try {
// random initialization vector
var iv = crypto.randomBytes(12);
// random salt
var salt = crypto.randomBytes(64);
// derive key: 32 byte key length - in assumption the masterkey is a cryptographic and NOT a password there is no need for
// a large number of iterations. It may can replaced by HKDF
var key = crypto.pbkdf2Sync(masterkey, salt, 2145, 32, 'sha512');
// AES 256 GCM Mode
var cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
// encrypt the given text
var encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
// extract the auth tag
var tag = cipher.getAuthTag();
// generate output
return Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
}catch(e){
}
// error
return null;
}
使用以下函数成功解密上述函数的加密文本:
decrypt: function (data, masterkey){
try {
// base64 decoding
var bData = new Buffer(data, 'base64');
var salt = bData.slice(0, 64);
var iv = bData.slice(64, 76);
var tag = bData.slice(76, 92);
var text = bData.slice(92);
// derive key using; 32 byte key length
var key = crypto.pbkdf2Sync(masterkey, salt , 2145, 32, 'sha512');
// AES 256 GCM Mode
var decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(tag);
// decrypt the given text
var decrypted = decipher.update(text, 'binary', 'utf8') + decipher.final('utf8');
return decrypted;
}catch(e){
}
// error
return null;
}
现在,我需要一个Java解密方法,它相当于上面的Javascript解密函数。以下是我为解密编写的Java代码:
public void decrypt(byte[] nkb, String crKey){
//nkb is byte array formed by Base64 decoding of 'data' variable in the Javascript code
//crKey corresponds to the 'masterkey' variable
byte[] salt = Arrays.copyOfRange(nkb, 0, 64);
byte[] iv = Arrays.copyOfRange(nkb, 64, 76);
byte[] tag = Arrays.copyOfRange(nkb, 76, 92);
byte[] text = Arrays.copyOfRange(nkb, 92, nkb.length);
PBEKeySpec ks = new PBEKeySpec(crKey.toCharArray(), salt, iterations, 256);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
SecretKey pbeKey = skf.generateSecret(ks);
byte[] decrypted = decrypt(iv, pbeKey.getEncoded(), text, tag);
}
public static byte[] decrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes, byte[] tagBytes)
throws java.io.UnsupportedEncodingException,
NoSuchAlgorithmException,
NoSuchPaddingException,
InvalidKeyException,
InvalidAlgorithmParameterException,
IllegalBlockSizeException,
BadPaddingException,
NoSuchProviderException {
GCMParameterSpec ivSpec = new GCMParameterSpec(tagBytes.length*Byte.SIZE, ivBytes);
SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
return cipher.doFinal(textBytes); //getting tag mismatch error here
}
正如我在上面的代码中所评论的,我在最后一行得到了一个标签不匹配错误。我很感激帮助找出我做错了什么。
我在这行代码中有错误:
cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec)
java.security.InvalidKeyException: Illegal key size
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
at javax.crypto.Cipher.implInit(Cipher.java:805)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at com.micropro.namwebservice.utils.CryptoUtils.decrypt(CryptoUtils.java:93)
at com.micropro.namwebservice.utils.CryptoUtils.decrypt(CryptoUtils.java:82)
答案 0 :(得分:2)
您需要将标记提供给Java GCM代码,以便它可以检查消息是否可信。 Java API期望将标记附加到密文。更改代码的最简单方法是替换行
return cipher.doFinal(textBytes);
有两行:
cipher.update(textBytes);
return cipher.doFinal(tagBytes);
答案 1 :(得分:-1)
cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec); // Error in this line
java.security.InvalidKeyException: Illegal key size
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
at javax.crypto.Cipher.implInit(Cipher.java:805)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at com.micropro.namwebservice.utils.CryptoUtils.decrypt(CryptoUtils.java:93)
at com.micropro.namwebservice.utils.CryptoUtils.decrypt(CryptoUtils.java:82)