I';我得到javax.crypto.AEADBadTagException:标记不匹配!使用AES/GCM/NoPadding解密大文件时
我一直在使用BouncyCastle的提供程序加密文件,使用“AES/GCM/NoPadding”作为转换。它适用于许多较小的文件。但是,对于较大的文件,我得到了一个例外: javax.crypto.AEADBadTagException:标记不匹配 下面是我用来加密的代码:I';我得到javax.crypto.AEADBadTagException:标记不匹配!使用AES/GCM/NoPadding解密大文件时,java,encryption,Java,Encryption,我一直在使用BouncyCastle的提供程序加密文件,使用“AES/GCM/NoPadding”作为转换。它适用于许多较小的文件。但是,对于较大的文件,我得到了一个例外: javax.crypto.AEADBadTagException:标记不匹配 下面是我用来加密的代码: try (DataOutputStream os = new DataOutputStream(new FileOutputStream(encryptedFile))) { os.writeInt
try (DataOutputStream os = new DataOutputStream(new FileOutputStream(encryptedFile))) {
os.writeInt(CURRENT_ENCRYPTION_FILE_VERSION);
os.writeInt(CURRENT_RSA_KEY_VERSION);
// Generate a new random symmetric key for the AES encryption cipher
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey aesKey = keyGenerator.generateKey();
// Write the RSA encrypted AES key to the file
os.write(doRsaTransformation(aesKey.getEncoded(), publicRsaKey, Cipher.ENCRYPT_MODE));
// Generate an initialization vector (IV)
SecureRandom sr = new SecureRandom();
byte[] iv = new byte[16];
sr.nextBytes(iv);
// Write the RSA encrypted IV to the file
os.write(doRsaTransformation(iv, publicRsaKey, Cipher.ENCRYPT_MODE));
// Write the encrypted file
doAesFileEncryption(fileToEncrypt, aesKey, iv, os);
} catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException | IOException | InvalidAlgorithmParameterException ex) {
throw new EncryptionException(ex);
}
private void doAesFileEncryption(File fileToEncrypt, SecretKey aesKey, byte[] iv, OutputStream os) {
Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding");
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey, new GCMParameterSpec(128, iv));
byte[] block = new byte[1024];
int i;
try (FileInputStream fis = new FileInputStream(fileToEncrypt)) {
while ((i = fis.read(block)) != -1) {
byte[] encryptedBlock = aesCipher.update(block, 0, i);
if (encryptedBlock != null) {
os.write(encryptedBlock);
}
}
byte[] encryptedFinal = aesCipher.doFinal();
if (encryptedFinal != null) {
os.write(encryptedFinal);
}
}
}
下面是我用来解密的代码:
Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding");
aesCipher.init(Cipher.DECRYPT_MODE, aesKey, new GCMParameterSpec(128, iv));
byte[] block = new byte[1073741824];
int i;
try (FileOutputStream fos = new FileOutputStream(decryptedFile)) {
while ((i = is.read(block)) != -1) {
byte[] decryptedBlock = aesCipher.update(block, 0, i);
if (decryptedBlock != null) {
fos.write(decryptedBlock);
}
}
byte[] decryptedFinal = aesCipher.doFinal();
if (decryptedFinal != null) {
fos.write(decryptedFinal);
}
}
更新:
我已经想了好几天了。幸运的是,我至少知道了如何解密一个我急需的文件
该文件正在运行Java 7 update 51的服务器上加密。(我知道我不适合不让它保持最新。)现在我正试图在运行Java8的本地计算机(和其他本地计算机)上解密它。对于较大的文件,我总是得到上述例外,而不是较小的文件。如果我用Java7解密这个大文件,那么它解密时不会出错
这是预期的行为吗?在我看来,Java8应该能够解密用Java7加密的大型文件
如果我不能依赖较新版本的Java解密文件,而这些文件是用较旧版本的Java加密的,那么我该如何前进呢?我是否必须用旧版本解密所有文件,以便用新版本加密
多谢各位!非常感谢您的帮助 这不是完整的代码。例如,我们看不出你是否正确关闭了溪流。谢谢你,@MaartenBodewes!我非常专注于加密部分,甚至没有想到这是一个流问题。这是我使用try with resources块的第一个应用程序。我假设它会为我刷新并关闭流。应该这样做,但我们不知道您使用了try/catch:)来澄清:您在Oracle Java 7u51上对BC进行了加密(因为非Oracle Java在版本中通常不使用“u”)?decrypt也是Oracle Java 8吗?如果是这样的话,因为Oracle Java 8现在在SunJCE中有AES/GCM,那么您发布的代码或配置是否超出了获取BC提供程序的范围?仅在大数据上出现的问题,因此长时间(er)运行可能意味着JIT问题;试着用
-Xint
运行,看看它是否不同(不仅仅是速度较慢)。你能在doFinal抛出之前得到部分解密,看看它是否是一个好的明文前缀吗?谢谢你,@dave_thompson_085!是的,我安装了几个不同的Oracle Java 7更新来进行加密和解密。我可以用任何Oracle Java 7更新解密大文件。我还使用Oracle Java 8的许多不同更新测试了解密。我无法用任何Oracle Java 8更新解密任何大文件。我有加载bouncy castle提供程序的代码。我将很快用这个代码更新这个问题。我很高兴你提到这一点!我没有想到这是一个潜在的问题。