Start · Sprachen · PHP · Referenz · sodium_crypto_aead_chacha20poly1305_encrypt

sodium_crypto_aead_chacha20poly1305_encrypt

Funktion

Verschlüsselt und authentifiziert eine Nachricht mit dem AEAD-Algorithmus ChaCha20-Poly1305 (IETF-Variante mit 64-Bit-Nonce).

seit PHP 7.2.0 Kategorie: crypto

Signatur

sodium_crypto_aead_chacha20poly1305_encrypt(string $message, string $additional_data, string $nonce, string $key): string

Beschreibung

Diese Funktion implementiert Authenticated Encryption with Associated Data (AEAD) auf Basis von ChaCha20 (Stromchiffre) und Poly1305 (MAC). Das bedeutet: Die Nachricht wird verschlüsselt und gleichzeitig mit einem Authentifizierungs-Tag versehen, das sicherstellt, dass weder der Geheimtext noch die zusätzlichen Daten ($additional_data) unbemerkt verändert werden können.

$additional_data (auch associated data genannt) werden nicht verschlüsselt, sondern nur authentifiziert. Dies eignet sich z. B. für Protokoll-Header oder Versions-Informationen, die im Klartext mitgesendet werden sollen, aber vor Manipulation geschützt sein müssen.

Der Rückgabewert enthält den Geheimtext gefolgt von einem 16-Byte-Poly1305-Tag als binären String. Diese Variante verwendet eine 64-Bit-Nonce (8 Byte) und ist für Umgebungen gedacht, in denen die originale ChaCha20-Poly1305-Spezifikation (nicht die IETF-Variante mit 96-Bit-Nonce) benötigt wird. Für die meisten neuen Projekte empfiehlt sich sodium_crypto_aead_chacha20poly1305_ietf_encrypt().

Ein kryptografisch zufälliger und eindeutiger Nonce je Nachricht ist zwingend erforderlich. Die Wiederverwendung eines Nonce mit demselben Schlüssel bricht die Sicherheit vollständig. Schlüssel und Nonce sollten ausschließlich über die entsprechenden Sodium-Hilfsfunktionen erzeugt werden.

Parameter

Name Typ Default Beschreibung
$message Pflicht string Die zu verschlüsselnde Klartextnachricht als binärer String beliebiger Länge.
$additional_data Pflicht string Zusätzliche Daten, die authentifiziert, aber nicht verschlüsselt werden (z. B. Header-Felder). Kann ein leerer String '' sein, wenn keine zusätzlichen Daten benötigt werden.
$nonce Pflicht string Einmalig zu verwendender Nonce als binärer String der Länge SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES (8 Byte). Muss für jede Verschlüsselung mit demselben Schlüssel einzigartig sein.
$key Pflicht string Geheimer Schlüssel der Länge SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES (32 Byte), idealer Weise erzeugt mit sodium_crypto_aead_chacha20poly1305_keygen().

Rückgabewert

Typ
string
Beschreibung
Binärer String bestehend aus dem Geheimtext (gleiche Länge wie $message) gefolgt von einem 16-Byte-Poly1305-Authentifizierungs-Tag. Die Gesamtlänge beträgt also strlen($message) + SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_ABYTES.

Beispiele

Nachricht verschlüsseln und anschließend entschlüsseln

<?php
// Schlüssel und Nonce erzeugen
$key   = sodium_crypto_aead_chacha20poly1305_keygen();
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES);

$message         = 'Geheime Nachricht';
$additional_data = 'v1'; // z. B. Protokoll-Version, wird nicht verschlüsselt

// Verschlüsseln
$ciphertext = sodium_crypto_aead_chacha20poly1305_encrypt(
    $message,
    $additional_data,
    $nonce,
    $key
);

echo 'Geheimtext (hex): ' . bin2hex($ciphertext) . PHP_EOL;

// Entschlüsseln und verifizieren
$plaintext = sodium_crypto_aead_chacha20poly1305_decrypt(
    $ciphertext,
    $additional_data,
    $nonce,
    $key
);

if ($plaintext === false) {
    echo 'Authentifizierung fehlgeschlagen!' . PHP_EOL;
} else {
    echo 'Entschlüsselt: ' . $plaintext . PHP_EOL;
}

// Schlüssel sicher aus dem Speicher löschen
sodium_memzero($key);
Geheimtext (hex): <zufälliger Hex-String> Entschlüsselt: Geheime Nachricht

Schutz von API-Tokens mit zusätzlichen Metadaten

<?php
// Einmalige Erzeugung und sichere Speicherung des Schlüssels
$key = sodium_crypto_aead_chacha20poly1305_keygen();
// $key würde in der Praxis aus einem sicheren Schlüssel-Speicher geladen

$nonce = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES);

$token           = 'supersecret-api-token-12345';
$additional_data = json_encode(['user_id' => 42, 'issued_at' => time()]);

$encrypted = sodium_crypto_aead_chacha20poly1305_encrypt(
    $token,
    $additional_data,
    $nonce,
    $key
);

// Nonce + verschlüsselte Daten zusammen speichern/übertragen
$payload = base64_encode($nonce . $encrypted);
echo 'Payload (Base64): ' . $payload . PHP_EOL;

// Beim Empfang: Nonce extrahieren und entschlüsseln
$decoded    = base64_decode($payload);
$nonce_len  = SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES;
$nonce_recv = substr($decoded, 0, $nonce_len);
$cipher     = substr($decoded, $nonce_len);

$decrypted = sodium_crypto_aead_chacha20poly1305_decrypt(
    $cipher,
    $additional_data,
    $nonce_recv,
    $key
);

echo 'Token: ' . ($decrypted !== false ? $decrypted : 'Fehler') . PHP_EOL;

sodium_memzero($key);
Payload (Base64): <zufälliger Base64-String> Token: supersecret-api-token-12345

// Wichtig · Fallstricke

Nonce-Einzigartigkeit ist kritisch: Wird derselbe Nonce mit demselben Schlüssel für zwei verschiedene Nachrichten verwendet, kann ein Angreifer den Schlüsselstrom ableiten und beide Klartexte sowie zukünftige Nachrichten entschlüsseln. Verwende immer random_bytes() oder einen sicheren Zähler zur Nonce-Erzeugung.

Varianten-Unterschied: Diese Funktion (ohne _ietf) verwendet eine 64-Bit-Nonce (8 Byte). Die IETF-Variante sodium_crypto_aead_chacha20poly1305_ietf_encrypt() verwendet eine 96-Bit-Nonce (12 Byte) und ist RFC 8439-konform. Für neue Projekte wird die IETF-Variante empfohlen, da sie mit mehr Bibliotheken interoperabel ist.

Schlüsselverwaltung: Schlüssel sollten nach Verwendung mit sodium_memzero() aus dem Speicher gelöscht werden, um das Risiko von Speicher-Dumps zu minimieren.

Kein Passwort als Schlüssel: Verwende niemals direkt ein Passwort als $key. Leite stattdessen mit sodium_crypto_pwhash() einen kryptografisch starken Schlüssel ab.