// 目的:提供一個完全使用 PHP 實現 Diffie-Hellman 的範例。
// 這個函式產生 Diffie-Hellman 金鑰對的組態。
// 我們從一個空的組態開始,並讓 openssl_pkey_new 建立
// 一個質數和一個產生器。這是一個耗時的步驟。
function get_DH_params ($keylength=2048, $digest_alg="sha512")
{
$pkey = openssl_pkey_new(["digest_alg" => $digest_alg,
"private_key_bits" => $keylength,
"private_key_type" => OPENSSL_KEYTYPE_DH]);
$details = openssl_pkey_get_details($pkey);
return [
"digest_alg" => $digest_alg,
"private_key_bits" => $keylength,
"dh" => array('p' => $details['dh']['p'], 'g' => $details['dh']['g']),
"private_key_type" => OPENSSL_KEYTYPE_DH,
];
}
// 現在 Alice 和 Bob 可以建立他們各自的金鑰對
function get_DH_keyPair ($DH_params)
{
$pkey = openssl_pkey_new($DH_params);
$privkey = openssl_pkey_get_private($pkey);
$pubkey = openssl_pkey_get_details($pkey)['dh']['pub_key'];
return (object) compact('pubkey','privkey');
}
// 現在 Alice 和 Bob 可以建立一個共同的秘密金鑰
function get_DH_mutualsecret($peers_public, $my_private)
{
return bin2hex(openssl_dh_compute_key($peers_public, $my_private));
}
// 用法
>>> $dh_params = get_DH_params();
=> [
"digest_alg" => "sha512",
"private_key_bits" => 2048,
"dh" => [
"p" => b"ó»¸'#ð\x18\x04Û_Ä\tõyÁZàx\x15\x14\x11ƒ┬l=Ü┤H\0",
"g" => "\x02",
],
"private_key_type" => 2,
]
// Alice & Bob 從相同的 dh_params 產生他們的金鑰。
// 二進位值已截斷。
>>> $alice = get_DH_keypair($dh_params);
=> {#3773
+"pubkey": b"""EØüÔSðÔîË╚ùà5ÜLÜ$┘▄±ü6]",
+"privkey": OpenSSLAsymmetricKey {#3771},
}
>>> $bob = get_DH_keypair($dh_params);
=> {#3774
+"pubkey": b"'ua¥ªo\ê\x11║OM©\vó╣ßÜWöíþ³e÷:\t9Ô\rB┌\x13",
+"privkey": OpenSSLAsymmetricKey {#3765},
}
>>> $alice_secret = get_DH_mutualsecret($bob->pubkey, $alice->privkey);
=> "5fbf9df2f13da103f106. ....."
>>> $bob_secret = get_DH_mutualsecret($alice->pubkey, $bob->privkey);
=> "5fbf9df2f13da103f106. ....."
>>> $bob_secret == $alice_secret;
=> true
// 現在 Alice 和 Bob 有一個共享的秘密金鑰,他們可以將其用作對稱金鑰。金鑰的長度將為 2048 位元(與 DH 金鑰長度參數相同)。如果他們想的話,可以雜湊它以獲得更短的金鑰。
// 第三個人 Charlie 也可以像 Alice 和 Bob 一樣建立金鑰對。
// 而 Charlie 和 Alice 可以建立他們自己的,就像 Alice 和 Bob 做的那樣。
// 而 Charlie 和 Bob 可以建立他們自己的(獨立的)秘密金鑰。
//