Rev 258 | Blame | Last modification | View Log | RSS feed
<?php/*** Classe utilitaire proposant des fonctions permettant la réalisation d'un* échange de clé Diffie Hellman** "En cryptographie, l'échange de clés Diffie-Hellman, du nom de ses auteurs* Whitfield Diffie et Martin Hellman, est une méthode par laquelle deux* personnes peuvent se mettre d'accord sur un nombre (qu'ils peuvent utiliser* comme clé pour chiffrer la conversation suivante) sans qu'une troisième* personne appelée Ève puisse découvrir le nombre, même en ayant écouté tous* leurs échanges."** Voir http://fr.wikipedia.org/wiki/%C3%89change_de_cl%C3%A9s_Diffie-Hellman** */class DiffieHellmanUtil {// Default Diffie-Hellman key generator (1024 bit)const DH_P = 'dcf93a0b883972ec0e19989ac5a2ce310e1d37717e8d9571bb7623731866e61ef75a2e27898b057f9891c2e27a639c3f29b60814581cd3b2ca3986d2683705577d45c2e7e52dc81c7a171876e5cea74b1448bfdfaf18828efd2519f14e45e3826634af1949e5b535cc829a483b8a76223e5d490a257f05bdff16f2fb22c583ab';//Default Diffie-Hellman prime number (should be 2 or 5)const DH_G = '02';/*** 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(self::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));}}/*** Returns an associative array with Diffie-Hellman key components in* binary representation. The array includes original prime number 'p' and* generator 'g', random private key 'priv_key' and corresponding public* key 'pub_key'.** @param mixed $dh Diffie-Hellman key* @return array*/public static function getDhKeyDetails($dh){if (function_exists('openssl_dh_compute_key')) {$details = openssl_pkey_get_details($dh);if (isset($details['dh'])) {return $details['dh'];}} else {return $dh['details'];}}// Depuis OpenId.php, les fonctions de Diffie-Hellman// TODO : voir si ça peut être externaliser pour être réutilisé ? => dans utilitaires/*** Computes the shared secret from the private DH value $dh and the other* party's public value in $pub_key** @param string $pub_key other party's public value* @param mixed $dh Diffie-Hellman key* @return string* @throws Zend_OpenId_Exception*/public function computeDhSecret($pub_key, $dh){if (function_exists('openssl_dh_compute_key')) {$ret = openssl_dh_compute_key($pub_key, $dh);if (ord($ret[0]) > 127) {$ret = "\0" . $ret;}return $ret;} else if (extension_loaded('gmp')) {$bn_pub_key = self::binToBigNum($pub_key);$bn_secret = gmp_powm($bn_pub_key, $dh['priv_key'], $dh['p']);return self::bigNumToBin($bn_secret);} else if (extension_loaded('bcmath')) {$bn_pub_key = self::binToBigNum($pub_key);$bn_secret = bcpowmod($bn_pub_key, $dh['priv_key'], $dh['p']);return self::bigNumToBin($bn_secret);}/*require_once "Zend/OpenId/Exception.php";throw new Zend_OpenId_Exception('The system doesn\'t have proper big integer extension',Zend_OpenId_Exception::UNSUPPORTED_LONG_MATH);*/trigger_error('Le système ne gère pas les nombre de taille arbitraire', E_STRICT);}/*** Takes an arbitrary precision integer and returns its shortest big-endian* two's complement representation.** Arbitrary precision integers MUST be encoded as big-endian signed two's* complement binary strings. Henceforth, "btwoc" is a function that takes* an arbitrary precision integer and returns its shortest big-endian two's* complement representation. All integers that are used with* Diffie-Hellman Key Exchange are positive. This means that the left-most* bit of the two's complement representation MUST be zero. If it is not,* implementations MUST add a zero byte at the front of the string.** @param string $str binary representation of arbitrary precision integer* @return string big-endian signed representation*/public function btwoc($str){if (ord($str[0]) > 127) {return "\0" . $str;}return $str;}/*** Produces string of random byte of given length.** @param integer $len length of requested string* @return string RAW random binary string*/public function randomBytes($len){$key = '';for($i=0; $i < $len; $i++) {$key .= chr(mt_rand(0, 255));}return $key;}/*** Returns lenght of binary string in bytes** @param string $str* @return int the string lenght*/static public function strlen($str){if (extension_loaded('mbstring') &&(((int)ini_get('mbstring.func_overload')) & 2)) {return mb_strlen($str, 'latin1');} else {return strlen($str);}}/*** Converts binary representation into ext/gmp or ext/bcmath big integer* representation.** @param string $bin binary representation of big number* @return mixed* @throws Zend_OpenId_Exception*/protected function binToBigNum($bin){if (extension_loaded('gmp')) {return gmp_init(bin2hex($bin), 16);} else if (extension_loaded('bcmath')) {$bn = 0;$len = self::strlen($bin);for ($i = 0; $i < $len; $i++) {$bn = bcmul($bn, 256);$bn = bcadd($bn, ord($bin[$i]));}return $bn;}/*require_once "Zend/OpenId/Exception.php";throw new Zend_OpenId_Exception('The system doesn\'t have proper big integer extension',Zend_OpenId_Exception::UNSUPPORTED_LONG_MATH);*/trigger_error('Le système ne gère pas les nombre de taille arbitraire', E_STRICT);}}?>