无法使用Java解密AES-256 GCM

我有一个节点模块,可以使用AES-256 GCM进行encryption和解密。 现在我也试图用Java解密,无论节点模块encryption了什么,但是我总是收到AEADBadTagException。

我已经testing了自己的节点模块,并可以确认它是否按预期工作。 我知道Java假设authentication标签是消息的最后一部分,所以我确保标签是附加在节点模块中的最后一个东西。

现在我只是用“你好”这个词来testing。 这是来自节点的encryption消息: Q10blKuyyYozaRf0RVYW7bave8mT5wrJzSdURQQa3lEqEQtgYM3ss825YpCQ70A7hpq5ECPafAxdLMSIBZCxzGbv/Cj4i6W4JCJXuS107rUy0tAAQVQQA2ZhbrQ0gNV9QA==

盐现在还没有真正被使用,因为我试图保持简单的testing目的

节点模块:

 var crypto = require('crypto'); var encrypt = function(masterkey, plainText) { // random initialization vector var iv = crypto.randomBytes(12); // random salt var salt = crypto.randomBytes(64); var key = masterkey; // AES 256 GCM Mode var cipher = crypto.createCipheriv('aes-256-gcm', key, iv); // encrypt the given text var encrypted = Buffer.concat([cipher.update(plainText, 'utf8'), cipher.final()]); // extract the auth tag var tag = cipher.getAuthTag(); return Buffer.concat([salt, iv, encrypted, tag]).toString('base64'); }; var decrypt = function(masterkey, encryptedText) { // base64 decoding var bData = new Buffer(encryptedText, 'base64'); // convert data to buffers var salt = bData.slice(0, 64); var iv = bData.slice(64, 76); var tag = bData.slice(bData.length - 16, bData.length); var text = bData.slice(76, bData.length - 16); var key = masterkey; // AES 256 GCM Mode var decipher = crypto.createDecipheriv('aes-256-gcm', key, iv); decipher.setAuthTag(tag); // encrypt the given text var decrypted = decipher.update(text, 'binary', 'utf8') + decipher.final('utf8'); return decrypted; }; module.exports = { encrypt: encrypt, decrypt: decrypt } 

Java Class:主要的方法就在这里进行testing,稍后将被删除。

 package decryption; import java.util.Arrays; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class DecryptAES256 { private static String salt; private static byte[] ivBase64; private static String base64EncryptedText; private static String key; public static void main(String[] args) { String key = "123456789aabbccddeefffffffffffff"; String sourceText = "Q10blKuyyYozaRf0RVYW7bave8mT5wrJzSdURQQa3lEqEQtgYM3ss825YpCQ70A7hpq5ECPafAxdLMSIBZCxzGbv/Cj4i6W4JCJXuS107rUy0tAAQVQQA2ZhbrQ0gNV9QA=="; System.out.println(decrypt(key, sourceText)); } public static String decrypt(String masterkey, String encryptedText) { byte[] parts = encryptedText.getBytes(); salt = new String(Arrays.copyOfRange(parts, 0, 64)); ivBase64 = Arrays.copyOfRange(parts, 64, 76); ivBase64 = Base64.getDecoder().decode(ivBase64); base64EncryptedText = new String(Arrays.copyOfRange(parts, 76, parts.length)); key = masterkey; byte[] decipheredText = decodeAES_256_CBC(); return new String(decipheredText); } private static byte[] decodeAES_256_CBC() { try { SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); byte[] text = base64EncryptedText.getBytes(); GCMParameterSpec params = new GCMParameterSpec(128, ivBase64, 0, ivBase64.length); cipher.init(Cipher.DECRYPT_MODE, skeySpec, params); return cipher.doFinal(Base64.getDecoder().decode(text)); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Failed to decrypt"); } } } 

抛出的exception是正常的,你的Java代码中有两个问题:

1 – 您的AES密钥未正确解码 :以hex表示forms进行包装,并将其解码,就好像它不是。 调用SecretKeySpec()时,需要将其从hex表示转换为字节。

replace以下行:

 SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 

通过这一个:

 SecretKeySpec skeySpec = new SecretKeySpec(Hex.decodeHex(key.toCharArray()), "AES"); 

请注意,要访问Hex类,需要在类文件中导入org.apache.commons.codec.binary.Hex ,并在项目中包含相应的Apache commons-codec库。

2- 在拆分base64密码文本之前,将其转换为base64 ,这不是正确的操作顺序:

在您的decrypt()方法开始时,您需要先将密文( sourceText )上的Base64.getDecoder().decode()分解为相应的字段。

如果你想要一个在Java中使用AES-256-GCM的例子,你可以看看我几个月前写的下面的例子: https : //github.com/AlexandreFenyo/kif-idp-client

encryption和解密的源代码位于以下文件中: https : //github.com/AlexandreFenyo/kif-idp-client/blob/master/src/kif/libfc/Tools.java

请参阅名为encodeGCM()decodeGCM()

这些方法在这里由主类调用: https : //github.com/AlexandreFenyo/kif-idp-client/blob/master/src/kif/libfc/CommandLine.java