PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/htdocs/zend/1.10.2-minapp/library/Zend/Crypt/DiffieHellman.php

http://github.com/pmjones/php-framework-benchmarks
PHP | 380 lines | 168 code | 26 blank | 186 comment | 35 complexity | df0c0d3f7e242fa7c1a7a01afe028430 MD5 | raw file
Possible License(s): LGPL-3.0, Apache-2.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Crypt
  17. * @subpackage DiffieHellman
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: DiffieHellman.php 20096 2010-01-06 02:05:09Z bkarwin $
  21. */
  22. /**
  23. * PHP implementation of the Diffie-Hellman public key encryption algorithm.
  24. * Allows two unassociated parties to establish a joint shared secret key
  25. * to be used in encrypting subsequent communications.
  26. *
  27. * @category Zend
  28. * @package Zend_Crypt
  29. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  30. * @license http://framework.zend.com/license/new-bsd New BSD License
  31. */
  32. class Zend_Crypt_DiffieHellman
  33. {
  34. /**
  35. * Static flag to select whether to use PHP5.3's openssl extension
  36. * if available.
  37. *
  38. * @var boolean
  39. */
  40. public static $useOpenssl = true;
  41. /**
  42. * Default large prime number; required by the algorithm.
  43. *
  44. * @var string
  45. */
  46. private $_prime = null;
  47. /**
  48. * The default generator number. This number must be greater than 0 but
  49. * less than the prime number set.
  50. *
  51. * @var string
  52. */
  53. private $_generator = null;
  54. /**
  55. * A private number set by the local user. It's optional and will
  56. * be generated if not set.
  57. *
  58. * @var string
  59. */
  60. private $_privateKey = null;
  61. /**
  62. * BigInteger support object courtesy of Zend_Crypt_Math
  63. *
  64. * @var Zend_Crypt_Math_BigInteger
  65. */
  66. private $_math = null;
  67. /**
  68. * The public key generated by this instance after calling generateKeys().
  69. *
  70. * @var string
  71. */
  72. private $_publicKey = null;
  73. /**
  74. * The shared secret key resulting from a completed Diffie Hellman
  75. * exchange
  76. *
  77. * @var string
  78. */
  79. private $_secretKey = null;
  80. /**
  81. * Constants
  82. */
  83. const BINARY = 'binary';
  84. const NUMBER = 'number';
  85. const BTWOC = 'btwoc';
  86. /**
  87. * Constructor; if set construct the object using the parameter array to
  88. * set values for Prime, Generator and Private.
  89. * If a Private Key is not set, one will be generated at random.
  90. *
  91. * @param string $prime
  92. * @param string $generator
  93. * @param string $privateKey
  94. * @param string $privateKeyType
  95. * @return void
  96. */
  97. public function __construct($prime, $generator, $privateKey = null, $privateKeyType = self::NUMBER)
  98. {
  99. $this->setPrime($prime);
  100. $this->setGenerator($generator);
  101. if (!is_null($privateKey)) {
  102. $this->setPrivateKey($privateKey, $privateKeyType);
  103. }
  104. $this->setBigIntegerMath();
  105. }
  106. /**
  107. * Generate own public key. If a private number has not already been
  108. * set, one will be generated at this stage.
  109. *
  110. * @return Zend_Crypt_DiffieHellman
  111. */
  112. public function generateKeys()
  113. {
  114. if (function_exists('openssl_dh_compute_key') && self::$useOpenssl !== false) {
  115. $details = array();
  116. $details['p'] = $this->getPrime();
  117. $details['g'] = $this->getGenerator();
  118. if ($this->hasPrivateKey()) {
  119. $details['priv_key'] = $this->getPrivateKey();
  120. }
  121. $opensslKeyResource = openssl_pkey_new( array('dh' => $details) );
  122. $data = openssl_pkey_get_details($opensslKeyResource);
  123. $this->setPrivateKey($data['dh']['priv_key'], self::BINARY);
  124. $this->setPublicKey($data['dh']['pub_key'], self::BINARY);
  125. } else {
  126. // Private key is lazy generated in the absence of PHP 5.3's ext/openssl
  127. $publicKey = $this->_math->powmod($this->getGenerator(), $this->getPrivateKey(), $this->getPrime());
  128. $this->setPublicKey($publicKey);
  129. }
  130. return $this;
  131. }
  132. /**
  133. * Setter for the value of the public number
  134. *
  135. * @param string $number
  136. * @param string $type
  137. * @return Zend_Crypt_DiffieHellman
  138. */
  139. public function setPublicKey($number, $type = self::NUMBER)
  140. {
  141. if ($type == self::BINARY) {
  142. $number = $this->_math->fromBinary($number);
  143. }
  144. if (!preg_match("/^\d+$/", $number)) {
  145. require_once('Zend/Crypt/DiffieHellman/Exception.php');
  146. throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number');
  147. }
  148. $this->_publicKey = (string) $number;
  149. return $this;
  150. }
  151. /**
  152. * Returns own public key for communication to the second party to this
  153. * transaction.
  154. *
  155. * @param string $type
  156. * @return string
  157. */
  158. public function getPublicKey($type = self::NUMBER)
  159. {
  160. if (is_null($this->_publicKey)) {
  161. require_once 'Zend/Crypt/DiffieHellman/Exception.php';
  162. throw new Zend_Crypt_DiffieHellman_Exception('A public key has not yet been generated using a prior call to generateKeys()');
  163. }
  164. if ($type == self::BINARY) {
  165. return $this->_math->toBinary($this->_publicKey);
  166. } elseif ($type == self::BTWOC) {
  167. return $this->_math->btwoc($this->_math->toBinary($this->_publicKey));
  168. }
  169. return $this->_publicKey;
  170. }
  171. /**
  172. * Compute the shared secret key based on the public key received from the
  173. * the second party to this transaction. This should agree to the secret
  174. * key the second party computes on our own public key.
  175. * Once in agreement, the key is known to only to both parties.
  176. * By default, the function expects the public key to be in binary form
  177. * which is the typical format when being transmitted.
  178. *
  179. * If you need the binary form of the shared secret key, call
  180. * getSharedSecretKey() with the optional parameter for Binary output.
  181. *
  182. * @param string $publicKey
  183. * @param string $type
  184. * @return mixed
  185. */
  186. public function computeSecretKey($publicKey, $type = self::NUMBER, $output = self::NUMBER)
  187. {
  188. if ($type == self::BINARY) {
  189. $publicKey = $this->_math->fromBinary($publicKey);
  190. }
  191. if (!preg_match("/^\d+$/", $publicKey)) {
  192. require_once('Zend/Crypt/DiffieHellman/Exception.php');
  193. throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number');
  194. }
  195. if (function_exists('openssl_dh_compute_key') && self::$useOpenssl !== false) {
  196. $this->_secretKey = openssl_dh_compute_key($publicKey, $this->getPublicKey());
  197. } else {
  198. $this->_secretKey = $this->_math->powmod($publicKey, $this->getPrivateKey(), $this->getPrime());
  199. }
  200. return $this->getSharedSecretKey($output);
  201. }
  202. /**
  203. * Return the computed shared secret key from the DiffieHellman transaction
  204. *
  205. * @param string $type
  206. * @return string
  207. */
  208. public function getSharedSecretKey($type = self::NUMBER)
  209. {
  210. if (!isset($this->_secretKey)) {
  211. require_once('Zend/Crypt/DiffieHellman/Exception.php');
  212. throw new Zend_Crypt_DiffieHellman_Exception('A secret key has not yet been computed; call computeSecretKey()');
  213. }
  214. if ($type == self::BINARY) {
  215. return $this->_math->toBinary($this->_secretKey);
  216. } elseif ($type == self::BTWOC) {
  217. return $this->_math->btwoc($this->_math->toBinary($this->_secretKey));
  218. }
  219. return $this->_secretKey;
  220. }
  221. /**
  222. * Setter for the value of the prime number
  223. *
  224. * @param string $number
  225. * @return Zend_Crypt_DiffieHellman
  226. */
  227. public function setPrime($number)
  228. {
  229. if (!preg_match("/^\d+$/", $number) || $number < 11) {
  230. require_once('Zend/Crypt/DiffieHellman/Exception.php');
  231. throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number or too small: should be a large natural number prime');
  232. }
  233. $this->_prime = (string) $number;
  234. return $this;
  235. }
  236. /**
  237. * Getter for the value of the prime number
  238. *
  239. * @return string
  240. */
  241. public function getPrime()
  242. {
  243. if (!isset($this->_prime)) {
  244. require_once('Zend/Crypt/DiffieHellman/Exception.php');
  245. throw new Zend_Crypt_DiffieHellman_Exception('No prime number has been set');
  246. }
  247. return $this->_prime;
  248. }
  249. /**
  250. * Setter for the value of the generator number
  251. *
  252. * @param string $number
  253. * @return Zend_Crypt_DiffieHellman
  254. */
  255. public function setGenerator($number)
  256. {
  257. if (!preg_match("/^\d+$/", $number) || $number < 2) {
  258. require_once('Zend/Crypt/DiffieHellman/Exception.php');
  259. throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number greater than 1');
  260. }
  261. $this->_generator = (string) $number;
  262. return $this;
  263. }
  264. /**
  265. * Getter for the value of the generator number
  266. *
  267. * @return string
  268. */
  269. public function getGenerator()
  270. {
  271. if (!isset($this->_generator)) {
  272. require_once('Zend/Crypt/DiffieHellman/Exception.php');
  273. throw new Zend_Crypt_DiffieHellman_Exception('No generator number has been set');
  274. }
  275. return $this->_generator;
  276. }
  277. /**
  278. * Setter for the value of the private number
  279. *
  280. * @param string $number
  281. * @param string $type
  282. * @return Zend_Crypt_DiffieHellman
  283. */
  284. public function setPrivateKey($number, $type = self::NUMBER)
  285. {
  286. if ($type == self::BINARY) {
  287. $number = $this->_math->fromBinary($number);
  288. }
  289. if (!preg_match("/^\d+$/", $number)) {
  290. require_once('Zend/Crypt/DiffieHellman/Exception.php');
  291. throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number');
  292. }
  293. $this->_privateKey = (string) $number;
  294. return $this;
  295. }
  296. /**
  297. * Getter for the value of the private number
  298. *
  299. * @param string $type
  300. * @return string
  301. */
  302. public function getPrivateKey($type = self::NUMBER)
  303. {
  304. if (!$this->hasPrivateKey()) {
  305. $this->setPrivateKey($this->_generatePrivateKey());
  306. }
  307. if ($type == self::BINARY) {
  308. return $this->_math->toBinary($this->_privateKey);
  309. } elseif ($type == self::BTWOC) {
  310. return $this->_math->btwoc($this->_math->toBinary($this->_privateKey));
  311. }
  312. return $this->_privateKey;
  313. }
  314. /**
  315. * Check whether a private key currently exists.
  316. *
  317. * @return boolean
  318. */
  319. public function hasPrivateKey()
  320. {
  321. return isset($this->_privateKey);
  322. }
  323. /**
  324. * Setter to pass an extension parameter which is used to create
  325. * a specific BigInteger instance for a specific extension type.
  326. * Allows manual setting of the class in case of an extension
  327. * problem or bug.
  328. *
  329. * @param string $extension
  330. * @return void
  331. */
  332. public function setBigIntegerMath($extension = null)
  333. {
  334. /**
  335. * @see Zend_Crypt_Math
  336. */
  337. require_once 'Zend/Crypt/Math.php';
  338. $this->_math = new Zend_Crypt_Math($extension);
  339. }
  340. /**
  341. * In the event a private number/key has not been set by the user,
  342. * or generated by ext/openssl, a best attempt will be made to
  343. * generate a random key. Having a random number generator installed
  344. * on linux/bsd is highly recommended! The alternative is not recommended
  345. * for production unless without any other option.
  346. *
  347. * @return string
  348. */
  349. protected function _generatePrivateKey()
  350. {
  351. $rand = $this->_math->rand($this->getGenerator(), $this->getPrime());
  352. return $rand;
  353. }
  354. }