Signatur
Beschreibung
openssl_pkey_derive implementiert den Diffie-Hellman-Schlüsselaustausch (DH) und dessen elliptische-Kurven-Variante (ECDH). Die Funktion erwartet den öffentlichen Schlüssel der Gegenseite und den eigenen privaten Schlüssel und leitet daraus ein gemeinsames Geheimnis ab, das beiden Parteien bekannt ist, ohne es jemals übertragen zu müssen.
Das zurückgegebene Shared Secret ist ein rohes Byte-Array und sollte niemals direkt als Verschlüsselungsschlüssel verwendet werden. Stattdessen muss es durch eine geeignete Key-Derivation-Function (KDF) wie hash_hkdf() oder hash_pbkdf2() geleitet werden, um daraus einen sicheren symmetrischen Schlüssel abzuleiten.
Die Funktion unterstützt sowohl klassische DH-Parameter-Schlüssel als auch ECDH-Schlüssel auf benannten Kurven (z. B. prime256v1, secp384r1, X25519). Der optionale Parameter key_length erlaubt es, die Länge des zurückgegebenen Geheimnisses zu begrenzen, sofern die zugrundeliegende Implementierung dies unterstützt.
Typische Einsatzgebiete sind der Schlüsselaustausch in sicheren Kommunikationsprotokollen, Ende-zu-Ende-Verschlüsselung und hybride Kryptosysteme, bei denen asymmetrische Verfahren nur zur Aushandlung eines symmetrischen Sitzungsschlüssels genutzt werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $public_key Pflicht | OpenSSLAsymmetricKey|array|string | Der öffentliche Schlüssel der Gegenseite als OpenSSLAsymmetricKey-Ressource, als Array mit Schlüsselparametern oder als PEM-kodierter String. |
|
| $private_key Pflicht | OpenSSLAsymmetricKey|array|string | Der eigene private Schlüssel als OpenSSLAsymmetricKey-Ressource, als Array mit Schlüsselparametern oder als PEM-kodierter String. |
|
| $key_length | int | 0 | Gewünschte Länge des abgeleiteten Geheimnisses in Bytes. Bei 0 wird die volle, vom Algorithmus bestimmte Länge zurückgegeben. |
Rückgabewert
false zurückgegeben.Beispiele
ECDH-Schlüsselaustausch mit X25519
<?php
// Alice generiert ihr Schlüsselpaar
$aliceKey = openssl_pkey_new([
'curve_name' => 'X25519',
'private_key_type' => OPENSSL_KEYTYPE_EC,
]);
$alicePublic = openssl_pkey_get_details($aliceKey)['key']; // PEM-öffentlicher Schlüssel
// Bob generiert sein Schlüsselpaar
$bobKey = openssl_pkey_new([
'curve_name' => 'X25519',
'private_key_type' => OPENSSL_KEYTYPE_EC,
]);
$bobPublic = openssl_pkey_get_details($bobKey)['key']; // PEM-öffentlicher Schlüssel
// Beide Seiten berechnen unabhängig dasselbe Shared Secret
$aliceShared = openssl_pkey_derive($bobPublic, $aliceKey);
$bobShared = openssl_pkey_derive($alicePublic, $bobKey);
// Das Ergebnis muss auf beiden Seiten identisch sein
var_dump($aliceShared === $bobShared); // bool(true)
// Sicheren Schlüssel ableiten (niemals das Rohgeheimnis direkt verwenden!)
$sessionKey = hash_hkdf('sha256', $aliceShared, 32, 'aes-key', '');
echo bin2hex($sessionKey) . PHP_EOL;
ECDH-Schlüsselaustausch mit prime256v1 und anschließender AES-Verschlüsselung
<?php
// Schlüsselpaar für Partei A
$partyA = openssl_pkey_new([
'curve_name' => 'prime256v1',
'private_key_type' => OPENSSL_KEYTYPE_EC,
]);
// Schlüsselpaar für Partei B
$partyB = openssl_pkey_new([
'curve_name' => 'prime256v1',
'private_key_type' => OPENSSL_KEYTYPE_EC,
]);
$pubA = openssl_pkey_get_details($partyA)['key'];
$pubB = openssl_pkey_get_details($partyB)['key'];
// Shared Secret berechnen
$sharedSecret = openssl_pkey_derive($pubB, $partyA);
if ($sharedSecret === false) {
throw new RuntimeException('Schlüsselableitung fehlgeschlagen.');
}
// KDF: HKDF mit SHA-256, 256-Bit-Schlüssel für AES-256-GCM
$aesKey = hash_hkdf('sha256', $sharedSecret, 32, 'encryption');
$iv = random_bytes(12);
$plaintext = 'Geheime Nachricht';
$ciphertext = openssl_encrypt($plaintext, 'aes-256-gcm', $aesKey, OPENSSL_RAW_DATA, $iv, $tag);
echo 'Verschlüsselt: ' . bin2hex($ciphertext) . PHP_EOL;
echo 'Tag: ' . bin2hex($tag) . PHP_EOL;
// Entschlüsseln (Gegenseite würde denselben $aesKey ableiten)
$decrypted = openssl_decrypt($ciphertext, 'aes-256-gcm', $aesKey, OPENSSL_RAW_DATA, $iv, $tag);
echo 'Entschlüsselt: ' . $decrypted . PHP_EOL;
// Wichtig · Fallstricke
Sicherheitshinweise:
- Das von
openssl_pkey_derivezurückgegebene Rohgeheimnis darf niemals direkt als Verschlüsselungsschlüssel verwendet werden. Leite daraus immer mit einer KDF wiehash_hkdf()einen Schlüssel ab. - Stelle sicher, dass der öffentliche Schlüssel der Gegenseite authentifiziert ist (z. B. durch ein Zertifikat oder einen separaten Authentifizierungskanal), da ECDH ohne Authentifizierung anfällig für Man-in-the-Middle-Angriffe ist.
- Verwende moderne, sichere Kurven wie
X25519,X448,prime256v1odersecp384r1. Veraltete Kurven (z. B.secp112r1) bieten keine ausreichende Sicherheit. - Die Funktion gibt
falsezurück und erzeugt keine Exception — prüfe den Rückgabewert immer explizit. - Klassisches DH (nicht EC) ist möglich, aber ECDH ist in der Regel effizienter und wird bevorzugt.