/** * Performs the first step of a Diffie-Hellman key exchange by generating * private and public DH values based on given prime number $p and * generator $g. Both sides of key exchange MUST have the same prime number * and generator. In this case they will able to create a random shared * secret that is never send from one to the other. * * @param string $p prime number in binary representation * @param string $g generator in binary representation * @param string $priv_key private key in binary representation * @return mixed */ public static function createDhKey($p, $g, $priv_key = null) { if (function_exists('openssl_dh_compute_key')) { $dh_details = array('p' => $p, 'g' => $g); if ($priv_key !== null) { $dh_details['priv_key'] = $priv_key; } return openssl_pkey_new(array('dh' => $dh_details)); } else { $bn_p = self::binToBigNum($p); $bn_g = self::binToBigNum($g); if ($priv_key === null) { $priv_key = self::randomBytes(OpenID::strlen($p)); } $bn_priv_key = self::binToBigNum($priv_key); if (extension_loaded('gmp')) { $bn_pub_key = gmp_powm($bn_g, $bn_priv_key, $bn_p); } else { if (extension_loaded('bcmath')) { $bn_pub_key = bcpowmod($bn_g, $bn_priv_key, $bn_p); } } $pub_key = self::bigNumToBin($bn_pub_key); return array('p' => $bn_p, 'g' => $bn_g, 'priv_key' => $bn_priv_key, 'pub_key' => $bn_pub_key, 'details' => array('p' => $p, 'g' => $g, 'priv_key' => $priv_key, 'pub_key' => $pub_key)); } }