AES-GCM mit BouncyCastle wirft "mac-check-in GCM fehlgeschlagen", wenn verwendet mit IV
Ich bin relativ neu in der Entwicklung etwas mit der Verschlüsselung. Jetzt versuche ich eine Klasse schreiben, die ver-und entschlüsslung von Strings mit BouncyCastle mit AES-GCM. Ich lese über die Dinge, die Sie haben zu berücksichtigen, wenn die Implementierung von Verschlüsselung. Einer von Ihnen war, dass Sie sollten immer die Verwendung eines randomisierten IV.
Das problem ist, jedes mal wenn ich versuche zu initialisieren, meine Chiffre mit einer IV ist es nicht entschlüsseln, meinen text richtig.
Es wirft nur folgende Ausnahme:
javax.crypto.AEADBadTagException: mac check in GCM failed
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$AEADGenericBlockCipher.doFinal(Unknown Source)
at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at BouncyCastleEX.decrypt(BouncyCastleEX.java:78)
at BouncyCastleEX.main(BouncyCastleEX.java:43)
Ich bin mit dem folgenden Methoden zum verschlüsseln und entschlüsseln meine Daten.
private static final String fallbackSalt = "ajefa6tc73t6raiw7tr63wi3r7citrawcirtcdg78o2vawri7t";
private static final int iterations = 2000;
private static final int keyLength = 256;
private static final SecureRandom random = new SecureRandom();
public byte[] encrypt(String plaintext, String passphrase, String salt)
throws Exception {
SecretKey key = generateKey(passphrase, salt);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key, generateIV(cipher),random);
return cipher.doFinal(plaintext.getBytes());
}
public String decrypt(byte[] encrypted, String passphrase, String salt)
throws Exception {
SecretKey key = generateKey(passphrase, salt);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
cipher.init(Cipher.DECRYPT_MODE, key, generateIV(cipher),random);
return new String(cipher.doFinal(encrypted));
}
private SecretKey generateKey(String passphrase, String salt)
throws Exception {
PBEKeySpec keySpec = new PBEKeySpec(passphrase.toCharArray(),
salt.getBytes(), iterations, keyLength);
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC");
return keyFactory.generateSecret(keySpec);
}
private IvParameterSpec generateIV(Cipher cipher) throws Exception {
byte[] ivBytes = new byte[cipher.getBlockSize()];
random.nextBytes(ivBytes);
return new IvParameterSpec(ivBytes);
}
Wenn ich entfernen Sie die "generateIV(cipher)" aus meiner cipher.init(...) alles funktioniert einwandfrei. Aber soweit ich weiß, es schwächt die Verschlüsselung enorm.
Rechts weiß, ich bin nicht in der Lage, um herauszufinden, ob dies ist ein kleiner Fehler im code oder etwas anderes, ich weiß nichts über.
Ich wirklich zu schätzen Ihre Hilfe und vielen Dank!
- Es ist nicht ein Fehler im code, müssen Sie die gleichen IV auf die Entschlüsselung verwenden wie bei der Verschlüsselung. Ob ein IV gesendet werden können, in offenen, hängt davon ab, welche Effekte will man mit den IV.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie verwenden die gleiche IV für die Verschlüsselung und die Entschlüsselung. Es muss nicht geheim sein, sondern nur einzigartige für AES-GCM (es ist technisch eine nonce). Ein üblicher Weg ist, um voranstellen IV an den ciphertext und entfernen Sie es, bevor die Entschlüsselung.
Es ist auch üblich, in einer Meldung Zähler anstelle der zufälligen Generierung einer IV.
AES-GCM angegeben ist für IVG von 96 bit, was bedeutet, dass Sie verschlüsseln, 64 GB in einer einzigen Nachricht sicher. Wenn Sie das IVs eines full-block-Größe, gibt es eine Möglichkeit, dass die IV + counter überlappen würde für mehrere Nachrichten, die sich in einer viele-time-pad für diejenigen, die überlappenden Blöcke.
Hier ist die Finale version von meinem code, den ich schrieb, mit der Hilfe von Artjom.
Es scheint gut zu funktionieren, aber wenn Sie irgendwelche Fehler oder Dinge, die Sie zu Schwächen, die Sicherheit, lassen Sie es mich bitte wissen.