// Purpose: Provide a working example of Diffie-Hellman, entirely in php.
// This function generates a configuration for Diffie-Hellman keypair
// We start with an empty config and have openssl_pkey_new create
// a prime and a generator. This is a time consuming step.
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,
];
}
// Now Alice and Bob can create their respective keypairs
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');
}
// Now Alice and Bob can create a mutual secret
function get_DH_mutualsecret($peers_public, $my_private)
{
return bin2hex(openssl_dh_compute_key($peers_public, $my_private));
}
// Usage
>>> $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 generate their keys from the same dh_params.
// Binary values truncated.
>>> $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
// Now Alice and Bob have a shared secret which they can use as a symmetric key. The key will be 2048 bits long (same as the DH key length parameter). They can hash it to get a shorter key if they want.
// A third person, Charlie, can also create a key pair like Alice and Bob.
// And Charlie and Alice can create their own Alice and Bob did.
// And Charlie and Bob can create their own (separate) secret.
//openssl_dh_compute_key
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
openssl_dh_compute_key
Референца за `function.openssl-dh-compute-key.php` со подобрена типографија и навигација.
openssl_dh_compute_key
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
openssl_dh_compute_key — Пресметува заедничка тајна за јавната вредност на далечинскиот DH јавен клуч и локалниот DH клуч
= NULL
$public_key, Иницијализира контекст за инкрементално хеширање OpenSSLAsymmetricKey $private_key): string|falseЗаедничката тајна вратена од openssl_dh_compute_key() често се користи како шифриран клуч за тајна комуникација со оддалечена страна. Ова е познато како Diffie-Hellman размена на клучеви.
Важно е да се користат исти DH параметри за далечински и локални парови клучеви; инаку, генерираната тајна помеѓу двете страни нема да се совпаѓа.
Забелешка: ECDH е поддржано само од PHP 8.1.0 and OpenSSL 3.0.0.
Параметри
public_key-
DH јавен клуч на оддалечената страна.
private_key-
Локален DH приватен клуч, што одговара на јавниот клуч што треба да се сподели со оддалечената страна.
Вратени вредности
Враќа заедничка тајна при успех или false при неуспех.
Дневник на промени
| Верзија | = NULL |
|---|---|
| 8.0.0 |
private_key прифаќа OpenSSLAsymmetricKey сега; претходно, а resource од тип OpenSSL key беше прифатено.
|
Примери
Пример #1 Пресметај заедничка тајна
Прво генерирајте локален DH пар јавен/приватен клуч, и нека оддалечената страна го стори истото. Треба да го користиме openssl
алатката од командната линија.
# generate private/public key keypair openssl dhparam -out dhparam.pem 2048 openssl genpkey -paramfile dhparam.pem -out privatekey.pem # extract public key only openssl pkey -in privatekey.pem -pubout -out publickey.pem
Следно, испратете го вашиот јавен клуч до оддалечената страна. Користете ја openssl
pkey командата за да го видите јавниот клуч што ќе ви биде испратен од оддалечената страна.
openssl pkey -pubin -in remotepublickey.pem -text -noout
Горниот пример ќе прикаже нешто слично на:
PKCS#3 DH Public-Key: (2048 bit)
public-key:
67:e5:e5:fa:e0:7b:0f:96:2c:dc:96:44:5f:50:02:
9e:8d:c2:6c:04:68:b0:d1:1d:75:66:fc:63:f5:e3:
42:30:b8:96:c1:45:cc:08:60:b4:21:3b:dd:ee:66:
88:db:77:d9:1e:11:89:d4:5c:f2:7a:f2:f1:fe:1c:
77:9d:6f:13:b8:b2:56:00:ef:cb:3b:60:79:74:02:
98:f5:f9:8e:3e:b5:62:08:de:ca:8c:c3:40:4a:80:
79:d5:43:06:17:a8:19:56:af:cc:95:5e:e2:32:2d:
d2:14:7b:76:5a:9a:f1:3c:76:76:35:cc:7b:c1:a5:
f4:39:e5:b6:ca:71:3f:7c:3f:97:e5:ab:86:c1:cd:
0e:e6:ee:04:c9:e6:2d:80:7e:59:c0:49:eb:b6:64:
4f:a8:f9:bb:a3:87:b3:3d:76:01:9e:2b:16:94:a4:
37:30:fb:35:e2:63:be:23:90:b9:ef:3f:46:46:04:
94:8f:60:79:7a:51:55:d6:1a:1d:f5:d9:7f:4a:3e:
aa:ac:b0:d0:82:cc:c2:e0:94:e0:54:c1:17:83:0b:
74:08:4d:5a:79:ae:ff:7f:1c:04:ab:23:39:4a:ae:
87:83:55:43:ab:7a:7c:04:9d:20:80:bb:af:5f:16:
a3:e3:20:b9:21:47:8c:f8:7f:a8:60:80:9e:61:77:
36
[...abbreviated...]
Користете го овој јавен клуч како параметар за openssl_dh_compute_key() за да ја пресметате заедничката тајна.
<?php
$remote_public_key = '67e5e5fae07b0f962cdc96445f50029e8dc26c0468b0d11d7566fc63f5e34230b896c145cc0860b4213bddee6688db77d91e1189d45cf27af2f1fe1c779d6f13b8b25600efcb3b6079740298f5f98e3eb56208deca8cc3404a8079d5430617a81956afcc955ee2322dd2147b765a9af13c767635cc7bc1a5f439e5b6ca713f7c3f97e5ab86c1cd0ee6ee04c9e62d807e59c049ebb6644fa8f9bba387b33d76019e2b1694a43730fb35e263be2390b9ef3f464604948f60797a5155d61a1df5d97f4a3eaaacb0d082ccc2e094e054c117830b74084d5a79aeff7f1c04ab23394aae87835543ab7a7c049d2080bbaf5f16a3e320b921478cf87fa860809e617736';
$local_priv_key = openssl_pkey_get_private('file://privatekey.pem');
$shared_secret = openssl_dh_compute_key(hex2bin($remote_public_key), $local_priv_key);
echo bin2hex($shared_secret)."\n";
?>
Пример #2 Генерирај DH пар јавен/приватен клуч во php
Прво, генерирајте го DH простиот број
openssl dhparam -out dhparam.pem 2048 openssl dh -in dhparam.pem -noout -text
Горниот пример ќе прикаже нешто слично на:
PKCS#3 DH Parameters: (2048 bit)
prime:
00:a3:25:1e:73:3f:44:b9:2b:ee:f4:9d:9f:37:6a:
4b:fd:1d:bd:f4:af:da:c8:10:77:59:41:c6:5f:73:
d2:88:29:39:cd:1c:5f:c3:9f:0f:22:d2:9c:20:c1:
e4:c0:18:03:b8:b6:d8:da:ad:3b:39:a6:da:8e:fe:
12:30:e9:03:5d:22:ba:ef:18:d2:7b:69:f9:5b:cb:
78:c6:0c:8c:6b:f2:49:92:c2:49:e0:45:77:72:b3:
55:36:30:f2:40:17:89:18:50:03:fa:2d:54:7a:7f:
34:4c:73:32:b6:88:14:51:14:be:80:57:95:e6:a3:
f6:51:ff:17:47:4f:15:d6:0e:6c:47:53:72:2c:2a:
4c:21:cb:7d:f3:49:97:c9:47:5e:40:33:7b:99:52:
7e:7a:f3:52:27:80:de:1b:26:6b:40:bb:14:11:0b:
fb:e6:d8:2f:cf:a0:06:2f:96:b9:1c:0b:b4:cb:d3:
a6:62:9c:48:67:f6:81:f2:c6:ff:45:03:0a:9d:67:
9d:ce:27:d9:6b:48:5d:ca:fb:c2:5d:84:9b:8b:cb:
40:c7:a4:0c:8a:6e:f4:ab:ba:b6:10:c3:b8:25:4d:
cf:60:96:f4:db:e8:00:1c:58:47:7a:fb:51:86:d1:
22:d7:4e:94:31:7a:d5:da:3d:53:de:da:bb:64:8d:
62:6b
generator: 2 (0x2)
Вредностите на простиот број и генераторот се предаваат како p и g во openssl_pkey_new()
<?php
$configargs = array();
$configargs['p'] = hex2bin('00a3251e733f44b92beef49d9f376a4bfd1dbdf4afdac810775941c65f73d2882939cd1c5fc39f0f22d29c20c1e4c01803b8b6d8daad3b39a6da8efe1230e9035d22baef18d27b69f95bcb78c60c8c6bf24992c249e0457772b3553630f2401789185003fa2d547a7f344c7332b688145114be805795e6a3f651ff17474f15d60e6c4753722c2a4c21cb7df34997c9475e40337b99527e7af3522780de1b266b40bb14110bfbe6d82fcfa0062f96b91c0bb4cbd3a6629c4867f681f2c6ff45030a9d679dce27d96b485dcafbc25d849b8bcb40c7a40c8a6ef4abbab610c3b8254dcf6096f4dbe8001c58477afb5186d122d74e94317ad5da3d53dedabb648d626b');
$configargs['g'] = hex2bin('02');
$private_key = openssl_pkey_new(array('dh' => $configargs));
openssl_pkey_export_to_file($private_key,'privatekey.pem',$passphrase='y0urp@s5phr@se');
$details = openssl_pkey_get_details($private_key);
$local_pub_key = $details['dh']['pub_key'];
echo bin2hex($local_pub_key)."\n";//you can send your public key to the remote party
$details = openssl_pkey_get_details(openssl_pkey_get_public("file://remotepublickey.pem"));
$remote_public_key = $details['dh']['pub_key'];
$shared_secret = openssl_dh_compute_key($remote_public_key, $private_key);
echo bin2hex($shared_secret)."\n";
?>Види Исто така
- openssl_pkey_new() - Генерира нов приватен клуч
- openssl_pkey_get_details() - Враќа низа со детали за клучот
- openssl_pkey_get_private() - Враќа низа со клучните детали
- openssl_pkey_get_public() - Земете приватен клуч
Белешки од корисници 4 белешки
A working example. After some study and reading I finally get how this method is working.
You need to follow the below 4 steps;
1. You create a public key which is known to 1:n parties.
2. Each party creates their own keypair.
2a. Each party shared their public key with the members.
3. Each user can re-create the shared secret by using his Private Key and the Public Key of the other parties.
4. Compare the secrets as a handshake
/* 1. Create the first, global known public key. */
/**
* Get DH public/private keys
* @return array
*/
public static function get_keypair()
{
$keys = [];
$config = [
"digest_alg" => "sha512",
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_DH,
];
// Create the private and public key
$res = openssl_pkey_new($config);
$pubKey = openssl_pkey_get_details($res);
$keys["public"] = $pubKey["key"];
openssl_pkey_export($res, $privKey);
$keys["private"] = $privKey;
return $keys;
}
Now you share the Public Key with every member of the party.
/* 2. Each user creates a new Key Pair with the P,G from the global public key info */
$key = openssl_get_publickey(base64_decode($publicKey));
$info = openssl_pkey_get_details($key);
$params = $info["dh"];
Now you have the P,G from the public key. Use it;
/**
* Create keypair from Prime and Generator for KeyExchange
* @param $prime
* @param $generator
*/
public static function create_keypair_from_pg($prime, $generator)
{
$config = [
"digest_alg" => "sha512",
"private_key_bits" => 2048,
"dh" => [
"p" => $prime,
"g" => $generator
],
"private_key_type" => OPENSSL_KEYTYPE_DH,
];
return openssl_pkey_new($config);
}
/* 3. Create a shared secret with your Private Key, and User 1:n's Public Key */
$privateKey = openssl_get_publickey(base64_decode($privateKeyData));
$secret1 = openssl_dh_compute_key($user1PublicKey, $privateKey);
if($secret !== false) {
return bin2hex($secret);
}else{
print_r(openssl_error_string());
}
$secret2 = openssl_dh_compute_key($user2PublicKey, $privateKey);
if($secret !== false) {
return bin2hex($secret);
}else{
print_r(openssl_error_string());
}
/* 4. Compare the secrets as a handshake method */
if(strcmp($secret1, $secret2) === 0) {
return true;
}
return false;
Good luck, enjoy!. Keep me posted about improvements and updates. vangelier AT hotmail DOT comIs it possible for someone to post a working example? I have written many test and examples, and I just can't seem to get 2 secrets that are alike with this method.
I am following this; https://sandilands.info/sgordon/diffie-hellman-secret-key-exchange-with-openssl
With the console, it works great. With openssl_dh_compute_key it does not work.After some challenges I decided to write a C++ and PHP code samples.
As it can be very tricky to get a grib on how the Diffie and Hellman algoritm work. The code samples are cross compatible.
Gist with PHP code and C++ code:
https://gist.github.com/digitalhuman/2a2b85d61672e4bf83596d41351723ba
Enjoy!