Zum Inhalt springen
ecdsa.com

AES-GCM vs. ChaCha20-Poly1305: welches AEAD-Verfahren du einsetzen solltest

Beide sind Standard-AEADs mit 128-Bit-Tag und 96-Bit-Nonces. AES-GCM liegt auf CPUs mit AES-Befehlen und in FIPS-Umgebungen vorn, ChaCha20-Poly1305 überall sonst.

Bei AES-GCM vs. ChaCha20-Poly1305 geht es um die Wahl zwischen den beiden Algorithmen für authentifizierte Verschlüsselung, die fast den gesamten verschlüsselten Datenverkehr tragen: TLS 1.3, QUIC, SSH, WireGuard, age und den Großteil der Verschlüsselung auf Anwendungsebene. Richtig eingesetzt sind beide sicher, beide versagen gravierend, sobald sich eine Nonce wiederholt, und ihre Geschwindigkeit hängt stark von der Hardware ab.

Auf einen Blick

AES-GCMChaCha20-Poly1305
SpezifikationNIST SP 800-38D (2007)RFC 8439 (2018, ersetzt RFC 7539)
Schlüssellängen128, 192, 256 Bit256 Bit
Nonce96 Bit empfohlen96 Bit (192 Bit bei XChaCha20)
Tag128 Bit (kürzer erlaubt, nicht empfohlen)128 Bit
Maximale Datenmenge pro Nachrichtetwa 64 GiB (2³² − 2 Blöcke)256 GiB (2³² 64-Byte-Blöcke)
Budget an Zufalls-Nonces pro Schlüssel2³² Nachrichten (SP 800-38D)Gleiche Größenordnung bei 96-Bit-Nonces; mit XChaCha20 praktisch unbegrenzt
Nonce-WiederverwendungGibt das XOR der Klartexte und den GHASH-Schlüssel preis und ermöglicht FälschungenGibt das XOR der Klartexte preis und ermöglicht Fälschungen
Durchsatz, 16 KiB, OpenSSL 3.6.510,4 GB/s (AES-128), 8,8 GB/s (AES-256)2,1 GB/s
Durchsatz, 16-Byte-Nachrichten0,14 GB/s (AES-256)0,52 GB/s
Zeitkonstant ohne Hardware-UnterstützungSchwierig (tabellenbasiertes AES gibt über den Cache Informationen preis)Von Haus aus (Addieren, Rotieren, XOR)
Zugelassen nach FIPS 140-3JaNein
TLS 1.3TLS_AES_128_GCM_SHA256 (Pflicht), TLS_AES_256_GCM_SHA384 (empfohlen)TLS_CHACHA20_POLY1305_SHA256 (empfohlen)
Weitere EinsatzgebieteJWE A128GCM und A256GCM, IPsec, SSH aes256-gcm@openssh.com, Festplatten- und Cloud-VerschlüsselungWireGuard, SSH chacha20-poly1305@openssh.com, age, libsodium

Durchsatz gemessen mit openssl speed -evp auf einem Kern eines Apple M4 Max, der Befehle für AES und Polynommultiplikation besitzt.

Die Leistung hängt von der CPU ab

AES-GCM ist für Hardware gebaut: AES-Runden laufen als einzelne Befehle (AES-NI auf x86, die Kryptografie-Erweiterungen von ARMv8), und GHASH nutzt die übertragslose Multiplikation. Stehen beide zur Verfügung, erreicht es hier etwa 10 GB/s pro Kern, rund das Fünffache von ChaCha20-Poly1305. Ohne sie muss AES entweder Lookup-Tabellen verwenden, die langsam sind und über das Cache-Timing Schlüsselbits verraten, oder Bitslicing-Code, der zeitkonstant, aber langsam ist. ChaCha20 braucht nur 32-Bit-Additionen, Rotationen und XORs und läuft daher auf jeder CPU schnell und zeitkonstant, auch auf einfachen Smartphones und Mikrocontrollern.

Bei kleinen Nachrichten schrumpft der Abstand oder kehrt sich um: Mit 16-Byte-Eingaben erreichte ChaCha20-Poly1305 0,52 GB/s gegenüber 0,14 GB/s für AES-256-GCM, weil die Initialisierungskosten von GCM überwiegen. Bei typischen TLS-Records (bis 16 KiB) auf Servern ist AES-GCM schneller; bei vielen winzigen Paketen ist der Unterschied so oder so gering.

Nonces und Grenzen

Beide sind Verschlüsselungsverfahren im Zählermodus mit Einmal-Authentifikatoren, daher darf sich das Paar (Schlüssel, Nonce) nie wiederholen. Eine Wiederholung legt das XOR der beiden Klartexte offen. Bei GCM kann ein Angreifer außerdem den Authentifizierungs-Teilschlüssel ermitteln und unter diesem Schlüssel Nachrichten fälschen; bei Poly1305 wird der Einmalschlüssel offengelegt, was Fälschungen für diese Nonce erlaubt. NIST SP 800-38D begrenzt zufällig erzeugte 96-Bit-IVs auf 2³² Aufrufe pro Schlüssel, damit die Kollisionswahrscheinlichkeit vernachlässigbar bleibt; TLS umgeht das Problem, indem es Nonces aus den Sequenznummern der Records ableitet und die Schlüssel erneuert.

Erzeugt dein System für viele Nachrichten unter einem Schlüssel zufällige Nonces, verwende eine Konstruktion mit größerem Nonce-Raum oder mit Resistenz gegen Nonce-Missbrauch:

  • XChaCha20-Poly1305 (192-Bit-Nonces, beschrieben in einem Internet-Draft der IRTF und unter anderem in libsodium implementiert), bei dem zufällige Nonces für praktisch unbegrenzt viele Nachrichten sicher sind;
  • AES-GCM-SIV (RFC 8452), bei dem eine Nonce-Wiederverwendung nur verrät, ob zwei Nachrichten identisch waren;
  • oder Schlüsselableitung pro Nachricht oder pro Sitzung, wie es TLS, age und HPKE tun.

Keiner der beiden Algorithmen bindet das Chiffrat an einen bestimmten Schlüssel (kein Key Commitment): Ein Chiffrat lässt sich so konstruieren, dass es unter zwei verschiedenen Schlüsseln gültig entschlüsselt wird. Das spielt bei Verfahren mit mehreren Empfängern oder mit Passwörtern eine Rolle (das Problem der „Invisible Salamanders“). Ergänze ein Key Commitment, wenn Angreifer Schlüssel wählen können.

Node.js 26: dieselbe AEAD-Schnittstelle für beide Algorithmen
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";

const plaintext = Buffer.from("card ending 4242, amount 19.99");
const aad = Buffer.from("order=7781");

for (const algorithm of ["aes-256-gcm", "chacha20-poly1305"]) {
  const key = randomBytes(32);
  const nonce = randomBytes(12); // 96-bit nonce for both; never reuse with the same key
  const cipher = createCipheriv(algorithm, key, nonce, { authTagLength: 16 });
  cipher.setAAD(aad);
  const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
  const tag = cipher.getAuthTag();

  const decipher = createDecipheriv(algorithm, key, nonce, { authTagLength: 16 });
  decipher.setAAD(aad);
  decipher.setAuthTag(tag);
  const roundTrip = Buffer.concat([decipher.update(ciphertext), decipher.final()]);

  console.log(algorithm.padEnd(18), "ciphertext", ciphertext.length, "bytes + tag", tag.length, "bytes, decrypts:", roundTrip.equals(plaintext));
}
Ausgabe
aes-256-gcm        ciphertext 30 bytes + tag 16 bytes, decrypts: true
chacha20-poly1305  ciphertext 30 bytes + tag 16 bytes, decrypts: true

Wie TLS zwischen beiden wählt

TLS 1.3 verlangt von jeder Implementierung Unterstützung für TLS_AES_128_GCM_SHA256 und empfiehlt AES-256-GCM und ChaCha20-Poly1305. Clients ohne AES-Hardware führen ChaCha20 an erster Stelle auf; Server, die diese Präferenz respektieren, liefern jedem Client das für ihn schnellere Verschlüsselungsverfahren. OpenSSL setzt das mit der Option PrioritizeChaCha (SSL_OP_PRIORITIZE_CHACHA) um, die ChaCha20 nur dann bevorzugt, wenn der Client es zuerst aufgeführt hat; BoringSSL nutzt für denselben Zweck Gruppen gleicher Präferenz. Der TLS-Konfigurationsgenerator erzeugt Servereinstellungen, die beide Cipher Suites beibehalten.

Wann welches Verfahren passt

  • TLS- und QUIC-Server: Aktiviere beide; bevorzuge AES-GCM, aber gib Clients, die ChaCha20 an die erste Stelle setzen, auch ChaCha20.
  • Umgebungen mit FIPS 140-3: AES-GCM; ChaCha20-Poly1305 ist kein zugelassener Algorithmus.
  • Mobilgeräte, IoT und Mikrocontroller ohne AES-Beschleunigung: ChaCha20-Poly1305.
  • Verschlüsselung auf Anwendungsebene mit zufälligen Nonces und langlebigen Schlüsseln: XChaCha20-Poly1305 oder AES-GCM-SIV.
  • JWE: A256GCM (oder A128GCM); ChaCha20 steht nicht in der Kern-Registry von JWA.
  • Sehr große Einzelnachrichten (über 64 GiB): Teile sie in Chunks mit je eigener Nonce auf (wie age es mit ChaCha20-Poly1305-Chunks von 64 KiB tut); verlass dich nicht auf die Grenzen pro Nachricht.

Hinweise zur Migration

In einem gut entworfenen System ändert der Wechsel des AEAD-Verfahrens das Format des Chiffrats, aber sonst nichts.

  1. Versioniere dein Format: Speichere mit jedem Chiffrat einen Algorithmusbezeichner und eine Schlüssel-ID, damit alte Daten lesbar bleiben.
  2. Trenne die Schlüssel nach Algorithmus: Leite unterschiedliche Schlüssel ab (zum Beispiel mit HKDF und verschiedenen info-Strings), statt einen Schlüssel für beide zu verwenden.
  3. Prüfe die Nonce-Erzeugung erneut: Zähler müssen Neustarts überdauern; zufällige Nonces müssen innerhalb der oben genannten Grenzen bleiben, sonst steht der Wechsel zu XChaCha20 an.
  4. Verschlüssle nach und nach neu: Entschlüssle mit dem alten Algorithmus und schreibe mit dem neuen, sobald Datensätze ohnehin angefasst werden – es sei denn, eine Compliance-Frist erfordert eine Massenmigration.
  5. Miss auf der echten Hardware: Die Rangfolge bei der Geschwindigkeit kehrt sich zwischen Server-CPUs und kleinen Geräten um.

Quellen

Alle Vergleiche