// 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. 
//