Signatur
Beschreibung
openssl_dh_compute_key setzt das Diffie-Hellman-Schlüsselaustauschverfahren um: Beide Kommunikationspartner erzeugen unabhängig voneinander ein DH-Schlüsselpaar und tauschen anschließend nur die öffentlichen Anteile aus. Mit dieser Funktion berechnet jede Seite aus dem empfangenen öffentlichen Schlüssel der Gegenstelle und dem eigenen privaten Schlüssel ein identisches gemeinsames Geheimnis, ohne dass dieses jemals über das Netzwerk übertragen werden muss.
Das Ergebnis ist ein binärer String, der typischerweise als Eingabe für eine Schlüsselableitungsfunktion (KDF) wie hash_hkdf() oder hash_pbkdf2() verwendet wird, um daraus symmetrische Verschlüsselungs- oder HMAC-Schlüssel abzuleiten. Der Roh-Wert sollte niemals direkt als Verschlüsselungsschlüssel eingesetzt werden.
Der Parameter public_key ist der rohe binäre öffentliche Schlüsselwert der Gegenstelle (DH public value, nicht PEM-kodiert). Der private_key muss ein DH-Schlüsselobjekt sein, das z. B. mit openssl_pkey_new() erzeugt wurde und die gleichen DH-Parameter (Primzahl p und Generator g) wie der öffentliche Schlüssel der Gegenstelle teilt.
Die Funktion ist für klassische DH-Schlüsselaustauschszenarien gedacht. Für elliptische Kurven (ECDH) steht openssl_pkey_derive() zur Verfügung, das in modernen Anwendungen bevorzugt werden sollte.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $public_key Pflicht | string | Der rohe binäre öffentliche Schlüsselwert (DH public value) der Gegenstelle. Dies ist kein PEM- oder DER-kodiertes Zertifikat, sondern die reine Ganzzahl als binärer String, wie er z. B. durch openssl_pkey_get_details() im Feld dh['pub_key'] geliefert wird. |
|
| $private_key Pflicht | OpenSSLAsymmetricKey | Der lokale private DH-Schlüssel als OpenSSLAsymmetricKey-Objekt (vor PHP 8.0: resource). Er muss mit denselben DH-Parametern (p, g) erzeugt worden sein, die auch die Gegenstelle verwendet. |
Rückgabewert
false zurückgegeben.Beispiele
DH-Schlüsselaustausch zwischen zwei Parteien simulieren
<?php
// Gemeinsame DH-Parameter (Primzahl p und Generator g)
// In der Praxis werden diese vorab ausgehandelt oder aus einem Standard übernommen.
$dhParams = [
'private_key_type' => OPENSSL_KEYTYPE_DH,
'dh' => [
'p' => hex2bin(
'ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd1' .
'29024e088a67cc74020bbea63b139b22514a08798e3404dd' .
'ef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245' .
'e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed' .
'ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3d' .
'c2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f' .
'83655d23dca3ad961c62f356208552bb9ed529077096966d' .
'670c354e4abc9804f1746c08ca18217c32905e462e36ce3b' .
'e39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9' .
'de2bcbf6955817183995497cea956ae515d2261898fa0510' .
'15728e5a8aacaa68ffffffffffffffff'
),
'g' => hex2bin('02'),
],
];
// Alice erzeugt ihr Schlüsselpaar
$aliceKey = openssl_pkey_new($dhParams);
$aliceDetails = openssl_pkey_get_details($aliceKey);
// Bob erzeugt sein Schlüsselpaar mit denselben Parametern
$bobKey = openssl_pkey_new($dhParams);
$bobDetails = openssl_pkey_get_details($bobKey);
// Alice berechnet das Shared Secret mit Bobs öffentlichem Schlüssel
$aliceSecret = openssl_dh_compute_key($bobDetails['dh']['pub_key'], $aliceKey);
// Bob berechnet das Shared Secret mit Alices öffentlichem Schlüssel
$bobSecret = openssl_dh_compute_key($aliceDetails['dh']['pub_key'], $bobKey);
// Beide Secrets müssen identisch sein
if ($aliceSecret !== false && $bobSecret !== false && hash_equals($aliceSecret, $bobSecret)) {
echo 'Gemeinsames Geheimnis erfolgreich berechnet.' . PHP_EOL;
echo 'Länge (Bytes): ' . strlen($aliceSecret) . PHP_EOL;
echo 'Hex: ' . bin2hex($aliceSecret) . PHP_EOL;
} else {
echo 'Fehler beim Berechnen des gemeinsamen Geheimnisses.' . PHP_EOL;
}
Ableitung eines symmetrischen Schlüssels aus dem Shared Secret
<?php
// Annahme: $sharedSecret wurde bereits via openssl_dh_compute_key() berechnet
// und beide Parteien kennen denselben $salt-Wert (z. B. aus dem Protokoll).
$sharedSecret = '...'; // binärer String aus openssl_dh_compute_key()
$salt = random_bytes(32); // In der Praxis ausgetauscht oder aus Nonce abgeleitet
// AES-256-Schlüssel (32 Byte) mittels HKDF ableiten
$aesKey = hash_hkdf('sha256', $sharedSecret, 32, 'aes-256-cbc encryption', $salt);
echo 'AES-Schlüssel (hex): ' . bin2hex($aesKey) . PHP_EOL;
echo 'Länge: ' . strlen($aesKey) . ' Bytes' . PHP_EOL;
// Wichtig · Fallstricke
Sicherheitshinweise:
- Das Ergebnis von
openssl_dh_compute_keydarf niemals direkt als Verschlüsselungsschlüssel verwendet werden. Stets eine KDF (z. B.hash_hkdf()) nachschalten. - Klassisches DH (finite-field) gilt bei kleinen Gruppengrößen als schwach. Es wird empfohlen, mindestens 2048-Bit-Gruppen (RFC 3526) oder besser ECDH über
openssl_pkey_derive()zu verwenden. - Die DH-Parameter (p und g) beider Seiten müssen exakt übereinstimmen, sonst schlägt die Berechnung fehl oder liefert ein falsches Ergebnis.
- Der
public_key-Parameter ist ein roher binärer Wert, kein PEM/DER-Schlüssel. Verwechslungen hier sind eine häufige Fehlerquelle. - Ab PHP 8.0 wurde der Typ des zweiten Parameters von
resourceaufOpenSSLAsymmetricKeyumgestellt.