問題描述
我有以下用 Javascript 編寫的函數,用于使用 aes-256-gcm 進行加密:
I have the following function written in Javascript for encryption using 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;
}
上述函數的加密文本使用以下函數成功解密回來:
The encrypted text by the above function is successfully decrypted back using the following function:
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代碼:
Now, I need a method in Java for decryption which is the equivalent of the above Javascript decrypt function. Following is the Java code I have written for decryption:
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
}
正如我在上面的代碼中所評論的,我在最后一行得到了一個標簽不匹配錯誤.如果能幫助我找出我做錯了什么,我將不勝感激.
As I have commented in the above code, I get a Tag mismatch error in the last line. I would appreciate some help in finding out what I am doing wrong.
我在這行代碼中有錯誤:
I have error in this line code:
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)
推薦答案
您需要將標簽提供給 Java GCM 代碼,以便它可以檢查消息是否真實.Java API 期望將標簽附加到密文中.更改代碼以執行此操作的最簡單方法是替換該行
You need to provide the tag to the Java GCM code so that it can check that the message is authentic. The Java API expects the tag to be appended to the ciphertext. The simplest way to change your code to do that would be to replace the line
return cipher.doFinal(textBytes);
兩行:
cipher.update(textBytes);
return cipher.doFinal(tagBytes);
這篇關于使用 Java 的 AES-256-GCM 解密中的標簽不匹配錯誤的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!