Start · Sprachen · PHP · Referenz · sodium_crypto_box

sodium_crypto_box

Funktion

Verschlüsselt und authentifiziert eine Nachricht mit Public-Key-Kryptographie (X25519 + XSalsa20-Poly1305).

seit PHP 7.2.0 Kategorie: crypto

Signatur

sodium_crypto_box(string $message, string $nonce, string $key_pair): string

Beschreibung

sodium_crypto_box implementiert das Box-Konstrukt aus libsodium: Es kombiniert Diffie-Hellman-Schlüsselaustausch (Curve25519), symmetrische Stromverschlüsselung (XSalsa20) und einen Nachrichten-Authentifizierungscode (Poly1305) in einem einzigen Aufruf. Das Ergebnis ist eine verschlüsselte und authentifizierte Nachricht, die nur der vorgesehene Empfänger entschlüsseln kann.

Für den Aufruf wird ein kombiniertes Schlüsselpaar benötigt, das aus dem geheimen Schlüssel des Senders und dem öffentlichen Schlüssel des Empfängers zusammengesetzt wird. Dieses Paar wird mit sodium_crypto_box_keypair_from_secretkey_and_publickey() erzeugt. Der Nonce muss exakt SODIUM_CRYPTO_BOX_NONCEBYTES (24 Byte) lang und für jede Nachricht einzigartig sein – typischerweise wird er zufällig mit random_bytes() generiert und zusammen mit der Chiffre übertragen.

Die Funktion ist ideal für Ende-zu-Ende-Kommunikation zwischen zwei Parteien: Alice verschlüsselt mit ihrem geheimen Schlüssel und Bobs öffentlichem Schlüssel; Bob entschlüsselt mit seinem geheimen Schlüssel und Alices öffentlichem Schlüssel. Zum Entschlüsseln dient sodium_crypto_box_open().

Im Gegensatz zu einfacher symmetrischer Verschlüsselung muss kein gemeinsames Geheimnis vorab ausgetauscht werden – lediglich die öffentlichen Schlüssel müssen bekannt sein.

Parameter

Name Typ Default Beschreibung
$message Pflicht string Die Klartextnachricht, die verschlüsselt werden soll. Beliebige Binärdaten sind erlaubt.
$nonce Pflicht string Ein kryptographisch zufälliger Nonce von exakt SODIUM_CRYPTO_BOX_NONCEBYTES (24 Byte) Länge. Darf für dasselbe Schlüsselpaar niemals zweimal verwendet werden.
$key_pair Pflicht string Das kombinierte Schlüsselpaar aus dem geheimen Schlüssel des Senders und dem öffentlichen Schlüssel des Empfängers, erzeugt mit sodium_crypto_box_keypair_from_secretkey_and_publickey().

Rückgabewert

Typ
string
Beschreibung
Die verschlüsselte Nachricht als Binärstring. Sie enthält den MAC (16 Byte) vorangestellt, gefolgt vom Chiffretext. Bei einem Fehler wird eine SodiumException geworfen.

Beispiele

Nachricht zwischen Alice und Bob verschlüsseln

<?php
// Schlüsselpaare für Alice und Bob generieren
$alice_keypair = sodium_crypto_box_keypair();
$alice_secretkey = sodium_crypto_box_secretkey($alice_keypair);
$alice_publickey = sodium_crypto_box_publickey($alice_keypair);

$bob_keypair = sodium_crypto_box_keypair();
$bob_secretkey = sodium_crypto_box_secretkey($bob_keypair);
$bob_publickey = sodium_crypto_box_publickey($bob_keypair);

// Alice verschlüsselt eine Nachricht an Bob
$nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
$message = 'Hallo Bob, das ist eine geheime Nachricht!';

// Kombiniertes Schlüsselpaar: Alice (geheim) + Bob (öffentlich)
$alice_to_bob_keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey(
    $alice_secretkey,
    $bob_publickey
);

$ciphertext = sodium_crypto_box($message, $nonce, $alice_to_bob_keypair);
echo 'Verschlüsselt: ' . base64_encode($ciphertext) . PHP_EOL;

// Bob entschlüsselt die Nachricht von Alice
$bob_from_alice_keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey(
    $bob_secretkey,
    $alice_publickey
);

$decrypted = sodium_crypto_box_open($ciphertext, $nonce, $bob_from_alice_keypair);
if ($decrypted === false) {
    echo 'Entschlüsselung fehlgeschlagen oder Nachricht manipuliert!';
} else {
    echo 'Entschlüsselt: ' . $decrypted . PHP_EOL;
}
Verschlüsselt: <base64-kodierter Chiffretext> Entschlüsselt: Hallo Bob, das ist eine geheime Nachricht!

Nonce zusammen mit dem Chiffretext übertragen

<?php
// Sender-Seite: Schlüssel laden (hier beispielhaft erzeugt)
$sender_keypair  = sodium_crypto_box_keypair();
$sender_secret   = sodium_crypto_box_secretkey($sender_keypair);
$receiver_public = sodium_crypto_box_publickey(sodium_crypto_box_keypair());

$nonce   = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
$message = json_encode(['action' => 'transfer', 'amount' => 100]);

$keypair    = sodium_crypto_box_keypair_from_secretkey_and_publickey($sender_secret, $receiver_public);
$ciphertext = sodium_crypto_box($message, $nonce, $keypair);

// Nonce + Chiffretext zusammen übertragen (Nonce ist nicht geheim)
$payload = base64_encode($nonce . $ciphertext);
echo 'Payload (Nonce + Chiffretext): ' . $payload . PHP_EOL;

// Empfänger trennt Nonce und Chiffretext wieder
$raw        = base64_decode($payload);
$recv_nonce = substr($raw, 0, SODIUM_CRYPTO_BOX_NONCEBYTES);
$recv_cipher = substr($raw, SODIUM_CRYPTO_BOX_NONCEBYTES);
echo 'Nonce-Länge: ' . strlen($recv_nonce) . ' Byte' . PHP_EOL;
Payload (Nonce + Chiffretext): <base64-kodierter String> Nonce-Länge: 24 Byte

// Wichtig · Fallstricke

Nonce-Wiederverwendung ist katastrophal: Wird derselbe Nonce mit demselben Schlüsselpaar zweimal verwendet, kann ein Angreifer beide Klartexte wiederherstellen. Verwende stets random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES) oder einen sicher inkrementierten Zähler.

Geheime Schlüssel schützen: Der geheime Schlüssel darf niemals übertragen oder gespeichert werden, ohne ihn vorher mit sodium_crypto_secretbox oder einem Passwort-Hashing-Verfahren (z. B. sodium_crypto_pwhash) zu sichern.

Speicher bereinigen: Nach der Verwendung sensitiver Schlüsseldaten sollte sodium_memzero() aufgerufen werden, um die Daten aus dem Arbeitsspeicher zu löschen.

Für Anwendungsfälle, bei denen der Sender anonym bleiben soll, steht sodium_crypto_box_seal zur Verfügung, das keinen geheimen Schlüssel des Senders benötigt.