it-swarm.com.de

Kann ich bei der Verschlüsselung mit AES-256 256 Bit IV verwenden?

Ich möchte Daten mit AES in Java verschlüsseln und die Verschlüsselung mit Initialization Vector initialisieren. Kann ich 256-Bit-IV verwenden? Oder muss ich nur 128-Bit IV verwenden?

19
Hakim

Die IV hängt von der Betriebsart ab. Für die meisten Modi (z. B. CBC) muss die IV dieselbe Länge wie der Block haben. AES verwendet 128-Bit-Blöcke, also eine 128-Bit-IV. Beachten Sie, dass AES-256 einen 256-Bit-Schlüssel (daher der Name) verwendet, jedoch immer noch 128-Bit-Blöcke.

AES wurde als Teilmenge der Familie der Blockchiffren ausgewählt, die als Rijndael bekannt sind. Diese Familie umfasst nicht weniger als 15 Varianten für drei mögliche Blockgrößen (128, 192 und 256 Bit) und fünf mögliche Schlüsselgrößen (128, 160, 192, 224 und 256 Bit). AES , wie von NIST standardisiert, enthält nur drei Varianten, alle mit 128-Bit-Blöcken und mit Schlüsseln von 128, 192 oder 256 Bit.

Um die Dinge weiter zu verwirren, haben einige Software-Frameworks etwas falsch gemacht. z.B. PHP verwendet "MCRYPT_RIJNDAEL_128", um Rijndael mit 128-Bit-Schlüsseln und 128-Bit-Blöcken (dh dasselbe wie AES-128) und "MCRYPT_RIJNDAEL_256" für Rijndael mit 256-Bit-Schlüsseln und zu kennzeichnen 256-Bit-Blöcke (dh keine der AES-Varianten und insbesondere überhaupt keine AES-256).

41
Thomas Pornin

Sie müssen eine 128-Bit-IV verwenden. Für den CBC-Modus muss IV mit der Blockgröße übereinstimmen, die für AES immer 128 Bit beträgt.

Rijndael, der siegreiche AES-Kandidat, ist für 128- und 256-Bit-Blöcke definiert, aber nur 128-Bit-Blöcke wurden als AES standardisiert. Einige Bibliotheken unterstützen Rijndael mit 256-Bit-Blöcken, aber dann verwenden Sie AES nicht mehr.

Wenn Sie aus irgendeinem Grund eine längere IV benötigen, können Sie ein KDF oder einen Hash verwenden, um den Originalschlüssel und die IV in den Schlüssel zu verwandeln, den Sie tatsächlich für AES verwenden.

6
CodesInChaos

Die IV-Behandlung in Java hängt vom verwendeten kryptografischen Anbieter ab. Der Sun-Anbieter, der mit Oracle-Laufzeiten geliefert wird, ist ziemlich streng. Er erfordert, dass die IV dieselbe Größe wie die Blockgröße für hat die meisten Betriebsarten . Dies gilt auch für den CTR-Modus, in dem Sie möglicherweise erwartet haben, dass die Bereitstellung eines Nonce - der ersten Bytes der IV - ausreichend sein sollte. Der EZB-Modus erfordert natürlich keine IV, daher wird eine Ausnahme ausgelöst, wenn Sie versuchen, eine bereitzustellen.

Die Blockgröße von AES beträgt immer 128 Bit, so dass eine 256-Bit-IV für die meisten Betriebsarten nicht möglich ist. Wie bereits in einigen Antworten erwähnt, kann Rijndael mit einer Blockgröße von 256 Bit konfiguriert werden, Rijndael ist jedoch nicht in der Standardlaufzeit enthalten. Sie benötigen einen zusätzlichen Anbieter oder eine Bibliothek wie Bouncy Castle, um Rijndael nutzen zu können. Die Blockverschlüsselung AES verwendet keine IV als Eingabe, weshalb auch die Bereitstellung einer IV für den EZB-Modus fehlschlägt. Einige andere Sprachen/Laufzeiten ignorieren einfach die IV für die EZB

Jetzt gibt es eine Verschlüsselung, mit der Sie eine 256-Bit-IV (oder tatsächlich: nonce) angeben können, nämlich GCM. GCM funktioniert jedoch am besten mit einer Nonce von 12 Bytes. GCM konvertiert Daten - einschließlich Nonce - intern in einen 128-Bit-Zähler für den CTR-Modus.

Beachten Sie, dass das Erhöhen der IV-Größe den Algorithmus nicht automatisch magischer macht. Wenn Sie eine 256-Bit-Eingabe für eine IV haben, können Sie SHA-256-Bit für die Eingabe verwenden und stattdessen die 128 Bits ganz links verwenden.


Während wir über Java sprachen, hier ein Code, können Sie mit der IV-Größe experimentieren und einige Algorithmen wie "AES/CFB/NoPadding" Selbst ausprobieren. Beachten Sie, dass die im Code verwendeten statischen IVs nur zu Demonstrationszwecken dienen . CTR erfordert eine eindeutige IV, CBC erfordert eine IV, die nicht von zufällig zu einem Angreifer zu unterscheiden ist.

SecretKey aesKey = new SecretKeySpec(new byte[256 / Byte.SIZE], "AES");
byte[] pt = "owlstead".getBytes(StandardCharsets.US_ASCII);

{
    // === CBC mode requires an IV of the same size as the block size
    Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
    // changing the IV size will result in an exception
    byte[] ivBytes = new byte[c.getBlockSize()];
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, iv);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}

{
    // === CTR mode actually requires a complete IV in Java
    // Java (or actually, the Sun provider) requires a 128 bit IV instead of just a nonce
    Cipher c = Cipher.getInstance("AES/CTR/NoPadding");
    // changing the IV size will result in an exception
    byte[] ivBytes = new byte[c.getBlockSize()];
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, iv);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}

{
    // === GCM mode can do it!
    Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
    byte[] ivBytes = new byte[256 / Byte.SIZE];
    GCMParameterSpec gcmSpecWithIV = new GCMParameterSpec(128, ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, gcmSpecWithIV);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}

{
    // ===  Java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV
    Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
    byte[] ivBytes = new byte[c.getBlockSize()];
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    c.init(Cipher.ENCRYPT_MODE, aesKey, iv);
    byte[] ct = c.doFinal(pt);
    System.out.println(Hex.toHexString(ct));
}
5
Maarten Bodewes

Der Zweck der IV ist es, sie ein wenig zu "verwechseln".

Ohne sie würden Nachrichten mit demselben ersten Klartextblock alle denselben ersten Chiffretextblock verwenden. Dieses Szenario ist nicht ungewöhnlich. Betrachten Sie Dateien, die mit Standarddeklarationen über ihren Dateityp oder die Art und Weise beginnen, wie SMTP Dinge wie RCPT TO:, MAIL FROM: usw. als gemeinsame Elemente verwendet. 128 Bit (die Blockgröße von AES) sind klein, so etwas würde passieren.

Es gibt verschiedene Betriebsmodi, aber bei Verwendung von CBC als einfachste (und vielleicht immer noch häufigste?) Wird der Chiffretext von einem Block verwendet, um in den nächsten einzuspeisen, dh die verschlüsselte Ausgabe (Chiffretext) aus dem ersten Klartextblock wird verwendet to XOR der Klartext von Block 2 (bevor dieser dann verschlüsselt wird). Der Chiffretext jedes Blocks wird verwendet, um XOR (exklusives ODER) den Klartext des nächster Block, und so verkettet der Name Cipher Block [~ # ~] [~ # ~] . Das Problem ist, dass der erste Block keinen Block vorangestellt hat es (na ja in CBC sowieso ...)

Hier ist das zuerst beschriebene Problem ein Problem - Nachrichten mit demselben ersten Klartextblock würden alle denselben ersten Chiffretextblock verwenden, wenn derselbe Schlüssel zum Verschlüsseln verwendet würde.

Um dieses Problem zu vermeiden, wird eine IV (Initialisierungsvektor) verwendet. Dies ist ein Materialblock, der verwendet werden kann, um XOR (exklusives ODER)) den allerersten Block zum Starten der Kette. Die IV wird mit der Nachricht gesendet, andernfalls wäre es unmöglich, die Entschlüsselung zu starten.

Selbst wenn dieselbe Nachricht immer wieder mit demselben Schlüssel neu verschlüsselt wird, ist der erste verschlüsselte Block jedes Mal anders, und durch Verketten würde sich die gesamte verschlüsselte Nachricht jedes Mal unterscheiden.

Wenn Sie überlegen, was mit der IV gemacht wird, ist es in meinem CBC-Beispiel überhaupt nicht sinnvoll, eine IV mit einer Größe zu diskutieren, die größer oder kleiner als die 128-Bit-Blockgröße ist, da dies die Größe des ersten Blocks ist, den Sie benötigen "verwechseln" und von da an verwenden Sie den vorherigen Chiffretext, um ihn zu verketten. (OK, dies gilt nicht für alle Modi. Einige IVs müssen möglicherweise kleiner als der erste Block sein. Betrachten wir jedoch zunächst CBC.) Für CBC muss die IV also mit der Blockgröße identisch sein, die in AES immer 128 Bit beträgt (unabhängig von der Schlüsselgröße).

Der Nutzen für die Sicherheit ist angesichts der IV-Länge nicht so groß. Denken Sie nicht, dass eine längere IV eine bessere Sicherheit bedeuten muss. Die IV ist nicht der Schlüssel!

Das Problem mit IVs ist eher, was/wie Sie Ihre IVs generieren. Sie müssen von guter Qualität sein (dh einheitliches pseudozufälliges Material, das statistisch nicht mit zuvor verwendeten IVs zusammenhängt). Wenn Sie entweder ein schlechtes IV-Generierungsschema oder einen schlechten Schlüsselplan haben, können Sie die Sicherheit untergraben und sie möglicherweise für eine statistische Kryptoanalyse öffnen Techniken.

Was ich wirklich sagen möchte, ist, dass Kryptographie ein bisschen kompliziert ist :) und selbst ein Fehler mit der besten Absicht hat einige katastrophale Folgen gehabt. Einige ansonsten gute Systeme wurden durch kleine Implementierungsfehler vollständig ruiniert. Erinnern Sie sich an WEP für drahtlose Personen?

Wenn Sie nicht alle beteiligten Faktoren vollständig und gründlich verstehen, halten Sie sich bitte an die Standards und verwenden Sie gut verwendete (von Experten geprüfte) Bibliotheken und etablierte Praktiken.

Der Versuch, selbst mit den besten Absichten etwas Kluges zu tun, ist äußerst gefährlich, wenn Sie nicht alle Konsequenzen verstehen. Ich versuche sehr höflich zu sagen, dass Sie, wenn Sie eine Frage stellen müssen wie: Welche IV-Größe verwendet werden soll, nicht versuchen sollten, mit der Implementierung zu experimentieren, sondern sich nur an die Standardwerte halten sollten.

Beste Wünsche mit Ihrer Codierung, viel Spaß ...

2
TomH