PageRenderTime 62ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/s3db3.5.10/pearlib/phpseclib/Crypt/RSA.php

https://code.google.com/p/s3db/
PHP | 1929 lines | 900 code | 192 blank | 837 comment | 124 complexity | b4597a346141062c92db528c4fc37f3c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * Pure-PHP PKCS#1 (v2.1) compliant implementation of RSA.
  5. *
  6. * PHP versions 4 and 5
  7. *
  8. * Here's an example of how to encrypt and decrypt text with this library:
  9. * <code>
  10. * <?php
  11. * include('Crypt/RSA.php');
  12. *
  13. * $rsa = new Crypt_RSA();
  14. * extract($rsa->createKey());
  15. *
  16. * $plaintext = 'terrafrost';
  17. *
  18. * $rsa->loadKey($privatekey);
  19. * $ciphertext = $rsa->encrypt($plaintext);
  20. *
  21. * $rsa->loadKey($publickey);
  22. * echo $rsa->decrypt($ciphertext);
  23. *
  24. * </code>
  25. *
  26. * Here's an example of how to create signatures and verify signatures with this library:
  27. * <code>
  28. * <?php
  29. * include('Crypt/RSA.php');
  30. *
  31. * $rsa = new Crypt_RSA();
  32. * extract($rsa->createKey());
  33. *
  34. * $plaintext = 'terrafrost';
  35. *
  36. * $rsa->loadKey($privatekey);
  37. * $signature = $rsa->sign($plaintext);
  38. *
  39. * $rsa->loadKey($publickey);
  40. * echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified';
  41. *
  42. * </code>
  43. *
  44. * LICENSE: This library is free software; you can redistribute it and/or
  45. * modify it under the terms of the GNU Lesser General Public
  46. * License as published by the Free Software Foundation; either
  47. * version 2.1 of the License, or (at your option) any later version.
  48. *
  49. * This library is distributed in the hope that it will be useful,
  50. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  51. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  52. * Lesser General Public License for more details.
  53. *
  54. * You should have received a copy of the GNU Lesser General Public
  55. * License along with this library; if not, write to the Free Software
  56. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  57. * MA 02111-1307 USA
  58. *
  59. * @category Crypt
  60. * @package Crypt_RSA
  61. * @author Jim Wigginton <terrafrost@php.net>
  62. * @copyright MMIX Jim Wigginton
  63. * @license http://www.gnu.org/licenses/lgpl.txt
  64. * @version $Id: RSA.php,v 1.3 2009/12/04 21:05:32 terrafrost Exp $
  65. * @link http://phpseclib.sourceforge.net
  66. */
  67. /**
  68. * Include Math_BigInteger
  69. */
  70. require_once('Math/BigInteger.php');
  71. /**
  72. * Include Crypt_Random
  73. */
  74. require_once('Crypt/Random.php');
  75. /**
  76. * Include Crypt_Hash
  77. */
  78. require_once('Crypt/Hash.php');
  79. /**#@+
  80. * @access public
  81. * @see Crypt_RSA::encrypt()
  82. * @see Crypt_RSA::decrypt()
  83. */
  84. /**
  85. * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
  86. * (OAEP) for encryption / decryption.
  87. *
  88. * Uses sha1 by default.
  89. *
  90. * @see Crypt_RSA::setHash()
  91. * @see Crypt_RSA::setMGFHash()
  92. */
  93. define('CRYPT_RSA_ENCRYPTION_OAEP', 1);
  94. /**
  95. * Use PKCS#1 padding.
  96. *
  97. * Although CRYPT_RSA_ENCRYPTION_OAEP offers more security, including PKCS#1 padding is necessary for purposes of backwards
  98. * compatability with protocols (like SSH-1) written before OAEP's introduction.
  99. */
  100. define('CRYPT_RSA_ENCRYPTION_PKCS1', 2);
  101. /**#@-*/
  102. /**#@+
  103. * @access public
  104. * @see Crypt_RSA::sign()
  105. * @see Crypt_RSA::verify()
  106. * @see Crypt_RSA::setHash()
  107. */
  108. /**
  109. * Use the Probabilistic Signature Scheme for signing
  110. *
  111. * Uses sha1 by default.
  112. *
  113. * @see Crypt_RSA::setSaltLength()
  114. * @see Crypt_RSA::setMGFHash()
  115. */
  116. define('CRYPT_RSA_SIGNATURE_PSS', 1);
  117. /**
  118. * Use the PKCS#1 scheme by default.
  119. *
  120. * Although CRYPT_RSA_SIGNATURE_PSS offers more security, including PKCS#1 signing is necessary for purposes of backwards
  121. * compatability with protocols (like SSH-2) written before PSS's introduction.
  122. */
  123. define('CRYPT_RSA_SIGNATURE_PKCS1', 2);
  124. /**#@-*/
  125. /**#@+
  126. * @access private
  127. * @see Crypt_RSA::createKey()
  128. */
  129. /**
  130. * ASN1 Integer
  131. */
  132. define('CRYPT_RSA_ASN1_INTEGER', 2);
  133. /**
  134. * ASN1 Sequence (with the constucted bit set)
  135. */
  136. define('CRYPT_RSA_ASN1_SEQUENCE', 48);
  137. /**#@-*/
  138. /**#@+
  139. * @access private
  140. * @see Crypt_RSA::Crypt_RSA()
  141. */
  142. /**
  143. * To use the pure-PHP implementation
  144. */
  145. define('CRYPT_RSA_MODE_INTERNAL', 1);
  146. /**
  147. * To use the OpenSSL library
  148. *
  149. * (if enabled; otherwise, the internal implementation will be used)
  150. */
  151. define('CRYPT_RSA_MODE_OPENSSL', 2);
  152. /**#@-*/
  153. /**#@+
  154. * @access public
  155. * @see Crypt_RSA::createKey()
  156. * @see Crypt_RSA::setPrivateKeyFormat()
  157. */
  158. /**
  159. * PKCS#1 formatted private key
  160. *
  161. * Used by OpenSSH
  162. */
  163. define('CRYPT_RSA_PRIVATE_FORMAT_PKCS1', 0);
  164. /**#@-*/
  165. /**#@+
  166. * @access public
  167. * @see Crypt_RSA::createKey()
  168. * @see Crypt_RSA::setPublicKeyFormat()
  169. */
  170. /**
  171. * Raw public key
  172. *
  173. * An array containing two Math_BigInteger objects.
  174. *
  175. * The exponent can be indexed with any of the following:
  176. *
  177. * 0, e, exponent, publicExponent
  178. *
  179. * The modulus can be indexed with any of the following:
  180. *
  181. * 1, n, modulo, modulus
  182. */
  183. define('CRYPT_RSA_PUBLIC_FORMAT_RAW', 1);
  184. /**
  185. * PKCS#1 formatted public key
  186. */
  187. define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 2);
  188. /**
  189. * OpenSSH formatted public key
  190. *
  191. * Place in $HOME/.ssh/authorized_keys
  192. */
  193. define('CRYPT_RSA_PUBLIC_FORMAT_OPENSSH', 3);
  194. /**#@-*/
  195. /**
  196. * Pure-PHP PKCS#1 compliant implementation of RSA.
  197. *
  198. * @author Jim Wigginton <terrafrost@php.net>
  199. * @version 0.1.0
  200. * @access public
  201. * @package Crypt_RSA
  202. */
  203. class Crypt_RSA {
  204. /**
  205. * Precomputed Zero
  206. *
  207. * @var Array
  208. * @access private
  209. */
  210. var $zero;
  211. /**
  212. * Precomputed One
  213. *
  214. * @var Array
  215. * @access private
  216. */
  217. var $one;
  218. /**
  219. * Private Key Format
  220. *
  221. * @var Integer
  222. * @access private
  223. */
  224. var $privateKeyFormat = CRYPT_RSA_PRIVATE_FORMAT_PKCS1;
  225. /**
  226. * Public Key Format
  227. *
  228. * @var Integer
  229. * @access public
  230. */
  231. var $publicKeyFormat = CRYPT_RSA_PUBLIC_FORMAT_PKCS1;
  232. /**
  233. * Modulus (ie. n)
  234. *
  235. * @var Math_BigInteger
  236. * @access private
  237. */
  238. var $modulus;
  239. /**
  240. * Modulus length
  241. *
  242. * @var Math_BigInteger
  243. * @access private
  244. */
  245. var $k;
  246. /**
  247. * Exponent (ie. e or d)
  248. *
  249. * @var Math_BigInteger
  250. * @access private
  251. */
  252. var $exponent;
  253. /**
  254. * Primes for Chinese Remainder Theorem (ie. p and q)
  255. *
  256. * @var Array
  257. * @access private
  258. */
  259. var $primes;
  260. /**
  261. * Exponents for Chinese Remainder Theorem (ie. dP and dQ)
  262. *
  263. * @var Array
  264. * @access private
  265. */
  266. var $exponents;
  267. /**
  268. * Coefficients for Chinese Remainder Theorem (ie. qInv)
  269. *
  270. * @var Array
  271. * @access private
  272. */
  273. var $coefficients;
  274. /**
  275. * Hash name
  276. *
  277. * @var String
  278. * @access private
  279. */
  280. var $hashName;
  281. /**
  282. * Hash function
  283. *
  284. * @var Crypt_Hash
  285. * @access private
  286. */
  287. var $hash;
  288. /**
  289. * Length of hash function output
  290. *
  291. * @var Integer
  292. * @access private
  293. */
  294. var $hLen;
  295. /**
  296. * Length of salt
  297. *
  298. * @var Integer
  299. * @access private
  300. */
  301. var $sLen;
  302. /**
  303. * Hash function for the Mask Generation Function
  304. *
  305. * @var Crypt_Hash
  306. * @access private
  307. */
  308. var $mgfHash;
  309. /**
  310. * Encryption mode
  311. *
  312. * @var Integer
  313. * @access private
  314. */
  315. var $encryptionMode = CRYPT_RSA_ENCRYPTION_OAEP;
  316. /**
  317. * Signature mode
  318. *
  319. * @var Integer
  320. * @access private
  321. */
  322. var $signatureMode = CRYPT_RSA_SIGNATURE_PSS;
  323. /**
  324. * Public Exponent
  325. *
  326. * @var Mixed
  327. * @access private
  328. */
  329. var $publicExponent = false;
  330. /**
  331. * Password
  332. *
  333. * @var String
  334. * @access private
  335. */
  336. var $password = '';
  337. /**
  338. * The constructor
  339. *
  340. * If you want to make use of the openssl extension, you'll need to set the mode manually, yourself. The reason
  341. * Crypt_RSA doesn't do it is because OpenSSL doesn't fail gracefully. openssl_pkey_new(), in particular, requires
  342. * openssl.cnf be present somewhere and, unfortunately, the only real way to find out is too late.
  343. *
  344. * @return Crypt_RSA
  345. * @access public
  346. */
  347. function Crypt_RSA()
  348. {
  349. if ( !defined('CRYPT_RSA_MODE') ) {
  350. switch (true) {
  351. //case extension_loaded('openssl') && version_compare(PHP_VERSION, '4.2.0', '>='):
  352. // define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_OPENSSL);
  353. // break;
  354. default:
  355. define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
  356. }
  357. }
  358. $this->zero = new Math_BigInteger();
  359. $this->one = new Math_BigInteger(1);
  360. $this->hash = new Crypt_Hash('sha1');
  361. $this->hLen = $this->hash->getLength();
  362. $this->hashName = 'sha1';
  363. $this->mgfHash = new Crypt_Hash('sha1');
  364. }
  365. /**
  366. * Create public / private key pair
  367. *
  368. * Returns an array with the following three elements:
  369. * - 'privatekey': The private key.
  370. * - 'publickey': The public key.
  371. * - 'partialkey': A partially computed key (if the execution time exceeded $timeout).
  372. * Will need to be passed back to Crypt_RSA::createKey() as the third parameter for further processing.
  373. *
  374. * @access public
  375. * @param optional Integer $bits
  376. * @param optional Integer $timeout
  377. * @param optional Math_BigInteger $p
  378. */
  379. function createKey($bits = 1024, $timeout = false, $primes = array())
  380. {
  381. if ( CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL ) {
  382. $rsa = openssl_pkey_new(array('private_key_bits' => $bits));
  383. openssl_pkey_export($rsa, $privatekey);
  384. $publickey = openssl_pkey_get_details($rsa);
  385. $publickey = $publickey['key'];
  386. if ($this->privateKeyFormat != CRYPT_RSA_PRIVATE_FORMAT_PKCS1) {
  387. $privatekey = call_user_func_array(array($this, '_convertPrivateKey'), array_values($this->_parseKey($privatekey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1)));
  388. $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, CRYPT_RSA_PUBLIC_FORMAT_PKCS1)));
  389. }
  390. return array(
  391. 'privatekey' => $privatekey,
  392. 'publickey' => $publickey,
  393. 'partialkey' => false
  394. );
  395. }
  396. static $e;
  397. if (!isset($e)) {
  398. if (!defined('CRYPT_RSA_EXPONENT')) {
  399. // http://en.wikipedia.org/wiki/65537_%28number%29
  400. define('CRYPT_RSA_EXPONENT', '65537');
  401. }
  402. if (!defined('CRYPT_RSA_COMMENT')) {
  403. define('CRYPT_RSA_COMMENT', 'phpseclib-generated-key');
  404. }
  405. // per <http://cseweb.ucsd.edu/~hovav/dist/survey.pdf#page=5>, this number ought not result in primes smaller
  406. // than 256 bits.
  407. if (!defined('CRYPT_RSA_SMALLEST_PRIME')) {
  408. define('CRYPT_RSA_SMALLEST_PRIME', 4096);
  409. }
  410. $e = new Math_BigInteger(CRYPT_RSA_EXPONENT);
  411. }
  412. extract($this->_generateMinMax($bits));
  413. $absoluteMin = $min;
  414. $temp = $bits >> 1;
  415. if ($temp > CRYPT_RSA_SMALLEST_PRIME) {
  416. $num_primes = floor($bits / CRYPT_RSA_SMALLEST_PRIME);
  417. $temp = CRYPT_RSA_SMALLEST_PRIME;
  418. } else {
  419. $num_primes = 2;
  420. }
  421. extract($this->_generateMinMax($temp + $bits % $temp));
  422. $finalMax = $max;
  423. extract($this->_generateMinMax($temp));
  424. $exponents = $coefficients = array();
  425. $generator = new Math_BigInteger();
  426. $generator->setRandomGenerator('crypt_random');
  427. $n = $this->one->copy();
  428. $lcm = array(
  429. 'top' => $this->one->copy(),
  430. 'bottom' => false
  431. );
  432. $start = time();
  433. $i0 = count($primes) + 1;
  434. do {
  435. for ($i = $i0; $i <= $num_primes; $i++) {
  436. if ($timeout !== false) {
  437. $timeout-= time() - $start;
  438. $start = time();
  439. if ($timeout <= 0) {
  440. return array(
  441. 'privatekey' => '',
  442. 'publickey' => '',
  443. 'partialkey' => $primes
  444. );
  445. }
  446. }
  447. if ($i == $num_primes) {
  448. list($min, $temp) = $absoluteMin->divide($n);
  449. if (!$temp->equals($this->zero)) {
  450. $min = $min->add($this->one); // ie. ceil()
  451. }
  452. $primes[$i] = $generator->randomPrime($min, $finalMax, $timeout);
  453. } else {
  454. $primes[$i] = $generator->randomPrime($min, $max, $timeout);
  455. }
  456. if ($primes[$i] === false) { // if we've reached the timeout
  457. return array(
  458. 'privatekey' => '',
  459. 'publickey' => '',
  460. 'partialkey' => array_slice($primes, 0, $i - 1)
  461. );
  462. }
  463. // the first coefficient is calculated differently from the rest
  464. // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1])
  465. if ($i > 2) {
  466. $coefficients[$i] = $n->modInverse($primes[$i]);
  467. }
  468. $n = $n->multiply($primes[$i]);
  469. $temp = $primes[$i]->subtract($this->one);
  470. // textbook RSA implementations use Euler's totient function instead of the least common multiple.
  471. // see http://en.wikipedia.org/wiki/Euler%27s_totient_function
  472. $lcm['top'] = $lcm['top']->multiply($temp);
  473. $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp);
  474. $exponents[$i] = $e->modInverse($temp);
  475. }
  476. list($lcm) = $lcm['top']->divide($lcm['bottom']);
  477. $gcd = $lcm->gcd($e);
  478. $i0 = 1;
  479. } while (!$gcd->equals($this->one));
  480. $d = $e->modInverse($lcm);
  481. $coefficients[2] = $primes[2]->modInverse($primes[1]);
  482. // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.2>:
  483. // RSAPrivateKey ::= SEQUENCE {
  484. // version Version,
  485. // modulus INTEGER, -- n
  486. // publicExponent INTEGER, -- e
  487. // privateExponent INTEGER, -- d
  488. // prime1 INTEGER, -- p
  489. // prime2 INTEGER, -- q
  490. // exponent1 INTEGER, -- d mod (p-1)
  491. // exponent2 INTEGER, -- d mod (q-1)
  492. // coefficient INTEGER, -- (inverse of q) mod p
  493. // otherPrimeInfos OtherPrimeInfos OPTIONAL
  494. // }
  495. return array(
  496. 'privatekey' => $this->_convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients),
  497. 'publickey' => $this->_convertPublicKey($n, $e),
  498. 'partialkey' => false
  499. );
  500. }
  501. /**
  502. * Convert a private key to the appropriate format.
  503. *
  504. * @access private
  505. * @see setPrivateKeyFormat()
  506. * @param String $RSAPrivateKey
  507. * @return String
  508. */
  509. function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
  510. {
  511. $num_primes = count($primes);
  512. $raw = array(
  513. 'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
  514. 'modulus' => $n->toBytes(true),
  515. 'publicExponent' => $e->toBytes(true),
  516. 'privateExponent' => $d->toBytes(true),
  517. 'prime1' => $primes[1]->toBytes(true),
  518. 'prime2' => $primes[2]->toBytes(true),
  519. 'exponent1' => $exponents[1]->toBytes(true),
  520. 'exponent2' => $exponents[2]->toBytes(true),
  521. 'coefficient' => $coefficients[2]->toBytes(true)
  522. );
  523. // if the format in question does not support multi-prime rsa and multi-prime rsa was used,
  524. // call _convertPublicKey() instead.
  525. switch ($this->privateKeyFormat) {
  526. default: // eg. CRYPT_RSA_PRIVATE_FORMAT_PKCS1
  527. $components = array();
  528. foreach ($raw as $name => $value) {
  529. $components[$name] = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($value)), $value);
  530. }
  531. $RSAPrivateKey = implode('', $components);
  532. if ($num_primes > 2) {
  533. $OtherPrimeInfos = '';
  534. for ($i = 3; $i <= $num_primes; $i++) {
  535. // OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
  536. //
  537. // OtherPrimeInfo ::= SEQUENCE {
  538. // prime INTEGER, -- ri
  539. // exponent INTEGER, -- di
  540. // coefficient INTEGER -- ti
  541. // }
  542. $OtherPrimeInfo = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
  543. $OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
  544. $OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
  545. $OtherPrimeInfos.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
  546. }
  547. $RSAPrivateKey.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
  548. }
  549. $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
  550. if (!empty($this->password)) {
  551. $iv = $this->_random(8);
  552. $symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
  553. $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
  554. if (!class_exists('Crypt_TripleDES')) {
  555. require_once('Crypt/TripleDES.php');
  556. }
  557. $des = new Crypt_TripleDES();
  558. $des->setKey($symkey);
  559. $des->setIV($iv);
  560. $iv = strtoupper(bin2hex($iv));
  561. $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
  562. "Proc-Type: 4,ENCRYPTED\r\n" .
  563. "DEK-Info: DES-EDE3-CBC,$iv\r\n" .
  564. "\r\n" .
  565. chunk_split(base64_encode($des->encrypt($RSAPrivateKey))) .
  566. '-----END RSA PRIVATE KEY-----';
  567. } else {
  568. $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
  569. chunk_split(base64_encode($RSAPrivateKey)) .
  570. '-----END RSA PRIVATE KEY-----';
  571. }
  572. return $RSAPrivateKey;
  573. }
  574. }
  575. /**
  576. * Convert a public key to the appropriate format
  577. *
  578. * @access private
  579. * @see setPublicKeyFormat()
  580. * @param String $RSAPrivateKey
  581. * @return String
  582. */
  583. function _convertPublicKey($n, $e)
  584. {
  585. $modulus = $n->toBytes(true);
  586. $publicExponent = $e->toBytes(true);
  587. switch ($this->publicKeyFormat) {
  588. case CRYPT_RSA_PUBLIC_FORMAT_RAW:
  589. return array('e' => $e->copy(), 'n' => $n->copy());
  590. case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
  591. // from <http://tools.ietf.org/html/rfc4253#page-15>:
  592. // string "ssh-rsa"
  593. // mpint e
  594. // mpint n
  595. $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
  596. $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . CRYPT_RSA_COMMENT;
  597. return $RSAPublicKey;
  598. default: // eg. CRYPT_RSA_PUBLIC_FORMAT_PKCS1
  599. // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.1>:
  600. // RSAPublicKey ::= SEQUENCE {
  601. // modulus INTEGER, -- n
  602. // publicExponent INTEGER -- e
  603. // }
  604. $components = array(
  605. 'modulus' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus),
  606. 'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
  607. );
  608. $RSAPublicKey = pack('Ca*a*a*',
  609. CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
  610. $components['modulus'], $components['publicExponent']
  611. );
  612. $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
  613. chunk_split(base64_encode($RSAPublicKey)) .
  614. '-----END PUBLIC KEY-----';
  615. return $RSAPublicKey;
  616. }
  617. }
  618. /**
  619. * Break a public or private key down into its constituant components
  620. *
  621. * @access private
  622. * @see _convertPublicKey()
  623. * @see _convertPrivateKey()
  624. * @param String $key
  625. * @param Integer $type
  626. * @return Array
  627. */
  628. function _parseKey($key, $type)
  629. {
  630. switch ($type) {
  631. case CRYPT_RSA_PUBLIC_FORMAT_RAW:
  632. if (!is_array($key)) {
  633. return false;
  634. }
  635. $components = array();
  636. switch (true) {
  637. case isset($key['e']):
  638. $components['publicExponent'] = $key['e']->copy();
  639. break;
  640. case isset($key['exponent']):
  641. $components['publicExponent'] = $key['exponent']->copy();
  642. break;
  643. case isset($key['publicExponent']):
  644. $components['publicExponent'] = $key['publicExponent']->copy();
  645. break;
  646. case isset($key[0]):
  647. $components['publicExponent'] = $key[0]->copy();
  648. }
  649. switch (true) {
  650. case isset($key['n']):
  651. $components['modulus'] = $key['n']->copy();
  652. break;
  653. case isset($key['modulo']):
  654. $components['modulus'] = $key['modulo']->copy();
  655. break;
  656. case isset($key['modulus']):
  657. $components['modulus'] = $key['modulus']->copy();
  658. break;
  659. case isset($key[1]):
  660. $components['modulus'] = $key[1]->copy();
  661. }
  662. return $components;
  663. case CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
  664. case CRYPT_RSA_PUBLIC_FORMAT_PKCS1:
  665. /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
  666. "outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
  667. protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding
  668. two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here:
  669. http://tools.ietf.org/html/rfc1421#section-4.6.1.1
  670. http://tools.ietf.org/html/rfc1421#section-4.6.1.3
  671. DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell.
  672. DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation
  673. function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's
  674. own implementation. ie. the implementation *is* the standard and any bugs that may exist in that
  675. implementation are part of the standard, as well.
  676. * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */
  677. if (preg_match('#DEK-Info: DES-EDE3-CBC,(.+)#', $key, $matches)) {
  678. $iv = pack('H*', trim($matches[1]));
  679. $symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
  680. $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
  681. $ciphertext = base64_decode(preg_replace('#.+(\r|\n|\r\n)\1|[\r\n]|-.+-#s', '', $key));
  682. if ($ciphertext === false) {
  683. return false;
  684. }
  685. if (!class_exists('Crypt_TripleDES')) {
  686. require_once('Crypt/TripleDES.php');
  687. }
  688. $des = new Crypt_TripleDES();
  689. $des->setKey($symkey);
  690. $des->setIV($iv);
  691. $key = $des->decrypt($ciphertext);
  692. } else {
  693. $key = base64_decode(preg_replace('#-.+-|[\r\n]#', '', $key));
  694. if ($key === false) {
  695. return false;
  696. }
  697. }
  698. $private = false;
  699. $components = array();
  700. $this->_string_shift($key); // skip over CRYPT_RSA_ASN1_SEQUENCE
  701. $this->_decodeLength($key); // skip over the length of the above sequence
  702. $this->_string_shift($key); // skip over CRYPT_RSA_ASN1_INTEGER
  703. $length = $this->_decodeLength($key);
  704. $temp = $this->_string_shift($key, $length);
  705. if (strlen($temp) != 1 || ord($temp) > 2) {
  706. $components['modulus'] = new Math_BigInteger($temp, -256);
  707. $this->_string_shift($key); // skip over CRYPT_RSA_ASN1_INTEGER
  708. $length = $this->_decodeLength($key);
  709. $components[$type == CRYPT_RSA_PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  710. return $components;
  711. }
  712. $this->_string_shift($key); // skip over CRYPT_RSA_ASN1_INTEGER
  713. $length = $this->_decodeLength($key);
  714. $components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  715. $this->_string_shift($key);
  716. $length = $this->_decodeLength($key);
  717. $components['publicExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  718. $this->_string_shift($key);
  719. $length = $this->_decodeLength($key);
  720. $components['privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  721. $this->_string_shift($key);
  722. $length = $this->_decodeLength($key);
  723. $components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), -256));
  724. $this->_string_shift($key);
  725. $length = $this->_decodeLength($key);
  726. $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  727. $this->_string_shift($key);
  728. $length = $this->_decodeLength($key);
  729. $components['exponents'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), -256));
  730. $this->_string_shift($key);
  731. $length = $this->_decodeLength($key);
  732. $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  733. $this->_string_shift($key);
  734. $length = $this->_decodeLength($key);
  735. $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), -256));
  736. if (!empty($key)) {
  737. $key = substr($key, 1); // skip over CRYPT_RSA_ASN1_SEQUENCE
  738. $this->_decodeLength($key);
  739. while (!empty($key)) {
  740. $key = substr($key, 1); // skip over CRYPT_RSA_ASN1_SEQUENCE
  741. $this->_decodeLength($key);
  742. $key = substr($key, 1);
  743. $length = $this->_decodeLength($key);
  744. $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  745. $this->_string_shift($key);
  746. $length = $this->_decodeLength($key);
  747. $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  748. $this->_string_shift($key);
  749. $length = $this->_decodeLength($key);
  750. $components['coefficients'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  751. }
  752. }
  753. return $components;
  754. case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
  755. $key = base64_decode(preg_replace('#^ssh-rsa | .+$#', '', $key));
  756. if ($key === false) {
  757. return false;
  758. }
  759. $components = array();
  760. extract(unpack('Nlength', $this->_string_shift($key, 4)));
  761. $components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  762. extract(unpack('Nlength', $this->_string_shift($key, 4)));
  763. $components['publicExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
  764. return $components;
  765. }
  766. }
  767. /**
  768. * Loads a public or private key
  769. *
  770. * @access public
  771. * @param String $key
  772. * @param Integer $type optional
  773. */
  774. function loadKey($key, $type = CRYPT_RSA_PRIVATE_FORMAT_PKCS1)
  775. {
  776. $components = $this->_parseKey($key, $type);
  777. $this->modulus = $components['modulus'];
  778. $this->k = strlen($this->modulus->toBytes());
  779. $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
  780. if (isset($components['primes'])) {
  781. $this->primes = $components['primes'];
  782. $this->exponents = $components['exponents'];
  783. $this->coefficients = $components['coefficients'];
  784. $this->publicExponent = $components['publicExponent'];
  785. } else {
  786. $this->primes = array();
  787. $this->exponents = array();
  788. $this->coefficients = array();
  789. $this->publicExponent = false;
  790. }
  791. }
  792. /**
  793. * Sets the password
  794. *
  795. * Private keys can be encrypted with a password. To unset the password, pass in the empty string or false.
  796. * Or rather, pass in $password such that empty($password) is true.
  797. *
  798. * @see createKey()
  799. * @see loadKey()
  800. * @access public
  801. * @param String $password
  802. */
  803. function setPassword($password)
  804. {
  805. $this->password = $password;
  806. }
  807. /**
  808. * Defines the public key
  809. *
  810. * Some private key formats define the public exponent and some don't. Those that don't define it are problematic when
  811. * used in certain contexts. For example, in SSH-2, RSA authentication works by sending the public key along with a
  812. * message signed by the private key to the server. The SSH-2 server looks the public key up in an index of public keys
  813. * and if it's present then proceeds to verify the signature. Problem is, if your private key doesn't include the public
  814. * exponent this won't work unless you manually add the public exponent.
  815. *
  816. * Do note that when a new key is loaded the index will be cleared.
  817. *
  818. * Returns true on success, false on failure
  819. *
  820. * @see getPublicKey()
  821. * @access public
  822. * @param String $key
  823. * @param Integer $type optional
  824. * @return Boolean
  825. */
  826. function setPublicKey($key, $type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
  827. {
  828. $components = $this->_parseKey($key, $type);
  829. if (!$this->modulus->equals($components['modulus'])) {
  830. return false;
  831. }
  832. $this->publicExponent = $components['publicExponent'];
  833. }
  834. /**
  835. * Returns the public key
  836. *
  837. * The public key is only returned under two circumstances - if the private key had the public key embedded within it
  838. * or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this
  839. * function won't return it since this library, for the most part, doesn't distinguish between public and private keys.
  840. *
  841. * @see getPublicKey()
  842. * @access public
  843. * @param String $key
  844. * @param Integer $type optional
  845. */
  846. function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
  847. {
  848. $oldFormat = $this->publicKeyFormat;
  849. $this->publicKeyFormat = $type;
  850. $temp = $this->_convertPublicKey($this->modulus, $this->publicExponent);
  851. $this->publicKeyFormat = $oldFormat;
  852. return $temp;
  853. }
  854. /**
  855. * Generates the smallest and largest numbers requiring $bits bits
  856. *
  857. * @access private
  858. * @param Integer $bits
  859. * @return Array
  860. */
  861. function _generateMinMax($bits)
  862. {
  863. $bytes = $bits >> 3;
  864. $min = str_repeat(chr(0), $bytes);
  865. $max = str_repeat(chr(0xFF), $bytes);
  866. $msb = $num_bits & 7;
  867. if ($msb) {
  868. $min = chr(1 << ($msb - 1)) . $min;
  869. $max = chr((1 << $msb) - 1) . $max;
  870. } else {
  871. $min[0] = chr(0x80);
  872. }
  873. return array(
  874. 'min' => new Math_BigInteger($min, 256),
  875. 'max' => new Math_BigInteger($max, 256)
  876. );
  877. }
  878. /**
  879. * DER-decode the length
  880. *
  881. * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
  882. * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 Ā§ 8.1.3} for more information.
  883. *
  884. * @access private
  885. * @param String $string
  886. * @return Integer
  887. */
  888. function _decodeLength(&$string)
  889. {
  890. $length = ord($this->_string_shift($string));
  891. if ( $length & 0x80 ) { // definite length, long form
  892. $length&= 0x7F;
  893. $temp = $this->_string_shift($string, $length);
  894. $start+= $length;
  895. list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
  896. }
  897. return $length;
  898. }
  899. /**
  900. * DER-encode the length
  901. *
  902. * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
  903. * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 Ā§ 8.1.3} for more information.
  904. *
  905. * @access private
  906. * @param Integer $length
  907. * @return String
  908. */
  909. function _encodeLength($length)
  910. {
  911. if ($length <= 0x7F) {
  912. return chr($length);
  913. }
  914. $temp = ltrim(pack('N', $length), chr(0));
  915. return pack('Ca*', 0x80 | strlen($temp), $temp);
  916. }
  917. /**
  918. * String Shift
  919. *
  920. * Inspired by array_shift
  921. *
  922. * @param String $string
  923. * @param optional Integer $index
  924. * @return String
  925. * @access private
  926. */
  927. function _string_shift(&$string, $index = 1)
  928. {
  929. $substr = substr($string, 0, $index);
  930. $string = substr($string, $index);
  931. return $substr;
  932. }
  933. /**
  934. * Determines the private key format
  935. *
  936. * @see createKey()
  937. * @access public
  938. * @param Integer $format
  939. */
  940. function setPrivateKeyFormat($format)
  941. {
  942. $this->privateKeyFormat = $format;
  943. }
  944. /**
  945. * Determines the public key format
  946. *
  947. * @see createKey()
  948. * @access public
  949. * @param Integer $format
  950. */
  951. function setPublicKeyFormat($format)
  952. {
  953. $this->publicKeyFormat = $format;
  954. }
  955. /**
  956. * Determines which hashing function should be used
  957. *
  958. * Used with signature production / verification and (if the encryption mode is CRYPT_RSA_ENCRYPTION_OAEP) encryption and
  959. * decryption. If $hash isn't supported, sha1 is used.
  960. *
  961. * @access public
  962. * @param String $hash
  963. */
  964. function setHash($hash)
  965. {
  966. // Crypt_Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
  967. switch ($hash) {
  968. case 'md2':
  969. case 'md5':
  970. case 'sha1':
  971. case 'sha256':
  972. case 'sha384':
  973. case 'sha512':
  974. $this->hash = new Crypt_Hash($hash);
  975. $this->hLen = $this->hash->getLength();
  976. $this->hashName = $hash;
  977. break;
  978. default:
  979. $this->hash = new Crypt_Hash('sha1');
  980. $this->hLen = $this->hash->getLength();
  981. $this->hashName = 'sha1';
  982. }
  983. }
  984. /**
  985. * Determines which hashing function should be used for the mask generation function
  986. *
  987. * The mask generation function is used by CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_SIGNATURE_PSS and although it's
  988. * best if Hash and MGFHash are set to the same thing this is not a requirement.
  989. *
  990. * @access public
  991. * @param String $hash
  992. */
  993. function setMGFHash($hash)
  994. {
  995. // Crypt_Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
  996. switch ($hash) {
  997. case 'md2':
  998. case 'md5':
  999. case 'sha1':
  1000. case 'sha256':
  1001. case 'sha384':
  1002. case 'sha512':
  1003. $this->mgfHash = new Crypt_Hash($hash);
  1004. break;
  1005. default:
  1006. $this->mgfHash = new Crypt_Hash('sha1');
  1007. }
  1008. }
  1009. /**
  1010. * Determines the salt length
  1011. *
  1012. * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}:
  1013. *
  1014. * Typical salt lengths in octets are hLen (the length of the output
  1015. * of the hash function Hash) and 0.
  1016. *
  1017. * @access public
  1018. * @param Integer $format
  1019. */
  1020. function setSaltLength($sLen)
  1021. {
  1022. $this->sLen = $sLen;
  1023. }
  1024. /**
  1025. * Generates a random string x bytes long
  1026. *
  1027. * @access public
  1028. * @param Integer $bytes
  1029. * @param optional Integer $nonzero
  1030. * @return String
  1031. */
  1032. function _random($bytes, $nonzero = false)
  1033. {
  1034. $temp = '';
  1035. if ($nonzero) {
  1036. for ($i = 0; $i < $bytes; $i++) {
  1037. $temp.= chr(crypt_random(1, 255));
  1038. }
  1039. } else {
  1040. $ints = ($bytes + 1) >> 2;
  1041. for ($i = 0; $i < $ints; $i++) {
  1042. $temp.= pack('N', crypt_random());
  1043. }
  1044. $temp = substr($temp, 0, $bytes);
  1045. }
  1046. return $temp;
  1047. }
  1048. /**
  1049. * Integer-to-Octet-String primitive
  1050. *
  1051. * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}.
  1052. *
  1053. * @access private
  1054. * @param Math_BigInteger $x
  1055. * @param Integer $xLen
  1056. * @return String
  1057. */
  1058. function _i2osp($x, $xLen)
  1059. {
  1060. $x = $x->toBytes();
  1061. if (strlen($x) > $xLen) {
  1062. user_error('Integer too large', E_USER_NOTICE);
  1063. return false;
  1064. }
  1065. return str_pad($x, $xLen, chr(0), STR_PAD_LEFT);
  1066. }
  1067. /**
  1068. * Octet-String-to-Integer primitive
  1069. *
  1070. * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
  1071. *
  1072. * @access private
  1073. * @param String $x
  1074. * @return Math_BigInteger
  1075. */
  1076. function _os2ip($x)
  1077. {
  1078. return new Math_BigInteger($x, 256);
  1079. }
  1080. /**
  1081. * Exponentiate with or without Chinese Remainder Theorem
  1082. *
  1083. * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.2}.
  1084. *
  1085. * @access private
  1086. * @param Math_BigInteger $x
  1087. * @return Math_BigInteger
  1088. */
  1089. function _exponentiate($x)
  1090. {
  1091. if (empty($this->primes) || empty($this->coefficients) || empty($this->exponents)) {
  1092. return $x->modPow($this->exponent, $this->modulus);
  1093. }
  1094. $num_primes = count($this->primes);
  1095. $m_i = array(
  1096. 1 => $x->modPow($this->exponents[1], $this->primes[1]),
  1097. 2 => $x->modPow($this->exponents[2], $this->primes[2])
  1098. );
  1099. $h = $m_i[1]->subtract($m_i[2]);
  1100. $h = $h->multiply($this->coefficients[2]);
  1101. list(, $h) = $h->divide($this->primes[1]);
  1102. $m = $m_i[2]->add($h->multiply($this->primes[2]));
  1103. $r = $this->primes[1];
  1104. for ($i = 3; $i <= $num_primes; $i++) {
  1105. $m_i = $x->modPow($this->exponents[$i], $this->primes[$i]);
  1106. $r = $r->multiply($this->primes[$i - 1]);
  1107. $h = $m_i->subtract($m);
  1108. $h = $h->multiply($this->coefficients[$i]);
  1109. list(, $h) = $h->divide($this->primes[$i]);
  1110. $m = $m->add($r->multiply($h));
  1111. }
  1112. return $m;
  1113. }
  1114. /**
  1115. * RSAEP
  1116. *
  1117. * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}.
  1118. *
  1119. * @access private
  1120. * @param Math_BigInteger $m
  1121. * @return Math_BigInteger
  1122. */
  1123. function _rsaep($m)
  1124. {
  1125. if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) {
  1126. user_error('Message representative out of range', E_USER_NOTICE);
  1127. return false;
  1128. }
  1129. return $this->_exponentiate($m);
  1130. }
  1131. /**
  1132. * RSADP
  1133. *
  1134. * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}.
  1135. *
  1136. * @access private
  1137. * @param Math_BigInteger $c
  1138. * @return Math_BigInteger
  1139. */
  1140. function _rsadp($c)
  1141. {
  1142. if ($c->compare($this->zero) < 0 || $c->compare($this->modulus) > 0) {
  1143. user_error('Ciphertext representative out of range', E_USER_NOTICE);
  1144. return false;
  1145. }
  1146. return $this->_exponentiate($c);
  1147. }
  1148. /**
  1149. * RSASP1
  1150. *
  1151. * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}.
  1152. *
  1153. * @access private
  1154. * @param Math_BigInteger $m
  1155. * @return Math_BigInteger
  1156. */
  1157. function _rsasp1($m)
  1158. {
  1159. if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) {
  1160. user_error('Message representative out of range', E_USER_NOTICE);
  1161. return false;
  1162. }
  1163. return $this->_exponentiate($m);
  1164. }
  1165. /**
  1166. * RSAVP1
  1167. *
  1168. * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
  1169. *
  1170. * @access private
  1171. * @param Math_BigInteger $s
  1172. * @return Math_BigInteger
  1173. */
  1174. function _rsavp1($s)
  1175. {
  1176. if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) {
  1177. user_error('Signature representative out of range', E_USER_NOTICE);
  1178. return false;
  1179. }
  1180. return $this->_exponentiate($s);
  1181. }
  1182. /**
  1183. * MGF1
  1184. *
  1185. * See {@link http://tools.ietf.org/html/rfc3447#section-B.2.1 RFC3447#section-B.2.1}.
  1186. *
  1187. * @access private
  1188. * @param String $mgfSeed
  1189. * @param Integer $mgfLen
  1190. * @return String
  1191. */
  1192. function _mgf1($mgfSeed, $maskLen)
  1193. {
  1194. // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output.
  1195. $t = '';
  1196. $count = ceil($maskLen / $this->hLen);
  1197. for ($i = 0; $i < $count; $i++) {
  1198. $c = pack('N', $i);
  1199. $t.= $this->mgfHash->hash($mgfSeed . $c);
  1200. }
  1201. return substr($t, 0, $maskLen);
  1202. }
  1203. /**
  1204. * RSAES-OAEP-ENCRYPT
  1205. *
  1206. * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.1 RFC3447#section-7.1.1} and
  1207. * {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}.
  1208. *
  1209. * @access private
  1210. * @param String $m
  1211. * @param String $l
  1212. * @return String
  1213. */
  1214. function _rsaes_oaep_encrypt($m, $l = '')
  1215. {
  1216. $mLen = strlen($m);
  1217. // Length checking
  1218. // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
  1219. // be output.
  1220. if ($mLen > $this->k - 2 * $this->hLen - 2) {
  1221. user_error('Message too long', E_USER_NOTICE);
  1222. return false;
  1223. }
  1224. // EME-OAEP encoding
  1225. $lHash = $this->hash->hash($l);
  1226. $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2);
  1227. $db = $lHash . $ps . chr(1) . $m;
  1228. $seed = $this->_random($this->hLen);
  1229. $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1);
  1230. $maskedDB = $db ^ $dbMask;
  1231. $seedMask = $this->_mgf1($maskedDB, $this->hLen);
  1232. $maskedSeed = $seed ^ $seedMask;
  1233. $em = chr(0) . $maskedSeed . $maskedDB;
  1234. // RSA encryption
  1235. $m = $this->_os2ip($em);
  1236. $c = $this->_rsaep($m);
  1237. $c = $this->_i2osp($c, $this->k);
  1238. // Output the ciphertext C
  1239. return $c;
  1240. }
  1241. /**
  1242. * RSAES-OAEP-DECRYPT
  1243. *
  1244. * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}. The fact that the error
  1245. * messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2:
  1246. *
  1247. * Note. Care must be taken to ensure that an opponent cannot
  1248. * distinguish the different error conditions in Step 3.g, whether by
  1249. * error message or timing, or, more generally, learn partial
  1250. * information about the encoded message EM. Otherwise an opponent may
  1251. * be able to obtain useful information about the decryption of the
  1252. * ciphertext C, leading to a chosen-ciphertext attack such as the one
  1253. * observed by Manger [36].
  1254. *
  1255. * As for $l... to quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}:
  1256. *
  1257. * Both the encryption and the decryption operations of RSAES-OAEP take
  1258. * the value of a label L as input. In this version of PKCS #1, L is
  1259. * the empty string; other uses of the label are outside the scope of
  1260. * this document.
  1261. *
  1262. * @access private
  1263. * @param String $c
  1264. * @param String $l
  1265. * @return String
  1266. */
  1267. function _rsaes_oaep_decrypt($c, $l = '')
  1268. {
  1269. // Length checking
  1270. // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
  1271. // be output.
  1272. if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) {
  1273. user_error('Decryption error', E_USER_NOTICE);
  1274. return false;
  1275. }
  1276. // RSA decryption
  1277. $c = $this->_os2ip($c);
  1278. $m = $this->_rsadp($c);
  1279. if ($m === false) {
  1280. user_error('Decryption error', E_USER_NOTICE);
  1281. return false;
  1282. }
  1283. $em = $this->_i2osp($m, $this->k);
  1284. // EME-OAEP decoding
  1285. $lHash = $this->hash->hash($l);
  1286. $y = ord($em[0]);
  1287. $maskedSeed = substr($em, 1, $this->hLen);
  1288. $maskedDB = substr($em, $this->hLen + 1);
  1289. $seedMask = $this->_mgf1($maskedDB, $this->hLen);
  1290. $seed = $maskedSeed ^ $seedMask;
  1291. $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1);
  1292. $db = $maskedDB ^ $dbMask;
  1293. $lHash2 = substr($db, 0, $this->hLen);
  1294. $m = substr($db, $this->hLen);
  1295. if ($lHash != $lHash2) {
  1296. user_error('Decryption error', E_USER_NOTICE);
  1297. return false;
  1298. }
  1299. $m = ltrim($m, chr(0));
  1300. if (ord($m[0]) != 1) {
  1301. user_error('Decryption error', E_USER_NOTICE);
  1302. return false;
  1303. }
  1304. // Output the message M
  1305. return substr($m, 1);
  1306. }
  1307. /**
  1308. * RSAES-PKCS1-V1_5-ENCRYPT
  1309. *
  1310. * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}.
  1311. *
  1312. * @access private
  1313. * @param String $m
  1314. * @return Striā€¦

Large files files are truncated, but you can click here to view the full file