PageRenderTime 56ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/php4/jCryption.php

https://github.com/madhavvyas/jCryption
PHP | 706 lines | 375 code | 68 blank | 263 comment | 78 complexity | 2a1f708239b1d33f26613822cc4def51 MD5 | raw file
  1. <?php
  2. /**
  3. * jCryption
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * LICENSE: This source file is subject to version 3.0 of the PHP license
  8. * that is available through the world-wide-web at the following URI:
  9. * http://www.php.net/license/3_0.txt. If you did not receive a copy of
  10. * the PHP License and are unable to obtain it through the web, please
  11. * send a note to license@php.net so we can mail you a copy immediately.
  12. *
  13. * Many of the functions in this class are from the PEAR Crypt_RSA package ...
  14. * So most of the credits goes to the original creator of this package Alexander Valyalkin
  15. * you can get the package under http://pear.php.net/package/Crypt_RSA
  16. *
  17. * I just changed, added, removed and improved some functions to fit the needs of jCryption
  18. *
  19. * @author Daniel Griesser <daniel.griesser@jcryption.org>
  20. * @copyright 2010 Daniel Griesser
  21. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  22. * @version 1.1
  23. * @link http://jcryption.org/
  24. */
  25. class jCryption {
  26. var $_key_len;
  27. var $_e;
  28. /**
  29. * Constructor
  30. *
  31. * @access public
  32. */
  33. function jCryption($e = "\x01\x00\x01") {
  34. $this->_e = $e;
  35. }
  36. /**
  37. * Generates the Keypair with the given keyLength the encryption key e ist set staticlly
  38. * set to 65537 for faster encryption.
  39. *
  40. * @param int $keyLength
  41. * @return array
  42. * @access public
  43. */
  44. function generateKeypair($keyLength) {
  45. $this->_key_len = intval($keyLength);
  46. if ($this->_key_len < 8) {
  47. $this->_key_len = 8;
  48. }
  49. // set [e] to 0x10001 (65537)
  50. $e = $this->bin2int($this->_e);
  51. // generate [p], [q] and [n]
  52. $p_len = intval(($this->_key_len + 1) / 2);
  53. $q_len = $this->_key_len - $p_len;
  54. $p1 = $q1 = 0;
  55. do {
  56. // generate prime number [$p] with length [$p_len] with the following condition:
  57. // GCD($e, $p - 1) = 1
  58. do {
  59. $p = $this->getPrime($p_len);
  60. $p1 = $this->dec($p);
  61. $tmp = $this->GCD($e, $p1);
  62. } while (!$this->isOne($tmp));
  63. // generate prime number [$q] with length [$q_len] with the following conditions:
  64. // GCD($e, $q - 1) = 1
  65. // $q != $p
  66. do {
  67. $q = $this->getPrime($q_len);
  68. //$q = 102238965184417281201422828818276460200050705922822343263269460146519295919831;
  69. $q1 = $this->dec($q);
  70. $tmp = $this->GCD($e, $q1);
  71. } while (!$this->isOne($tmp) && !$this->cmpAbs($q, $p));
  72. // if (p < q), then exchange them
  73. if ($this->cmpAbs($p, $q) < 0) {
  74. $tmp = $p;
  75. $p = $q;
  76. $q = $tmp;
  77. $tmp = $p1;
  78. $p1 = $q1;
  79. $q1 = $tmp;
  80. }
  81. // calculate n = p * q
  82. $n = $this->mul($p, $q);
  83. } while ($this->bitLen($n) != $this->_key_len);
  84. // calculate d = 1/e mod (p - 1) * (q - 1)
  85. $pq = $this->mul($p1, $q1);
  86. $d = $this->invmod($e, $pq);
  87. // store RSA keypair attributes
  88. $keypair = array('n'=>$n, 'e'=>$e, 'd'=>$d, 'p'=>$p, 'q'=>$q);
  89. return $keypair;
  90. }
  91. function useKeys($keys,$keyLength) {
  92. $this->_key_len = intval($keyLength);
  93. if ($this->_key_len < 8) {
  94. $this->_key_len = 8;
  95. }
  96. // set [e] to 0x10001 (65537)
  97. $e = $this->bin2int($this->_e);
  98. // generate [p], [q] and [n]
  99. $p_len = intval(($this->_key_len + 1) / 2);
  100. $q_len = $this->_key_len - $p_len;
  101. $p1 = $q1 = 0;
  102. do {
  103. do {
  104. $q = $keys[rand(0,count($keys))];
  105. $p = $keys[rand(0,count($keys))];
  106. $p1 = $this->dec($p);
  107. $q1 = $this->dec($q);
  108. } while (!$this->cmpAbs($q, $p));
  109. // if (p < q), then exchange them
  110. if ($this->cmpAbs($p, $q) < 0) {
  111. $tmp = $p;
  112. $p = $q;
  113. $q = $tmp;
  114. $tmp = $p1;
  115. $p1 = $q1;
  116. $q1 = $tmp;
  117. }
  118. // calculate n = p * q
  119. $n = $this->mul($p, $q);
  120. } while ($this->bitLen($n) != $this->_key_len);
  121. // calculate d = 1/e mod (p - 1) * (q - 1)
  122. $pq = $this->mul($p1, $q1);
  123. $d = $this->invmod($e, $pq);
  124. // store RSA keypair attributes
  125. $keypair = array('n'=>$n, 'e'=>$e, 'd'=>$d, 'p'=>$p, 'q'=>$q);
  126. return $keypair;
  127. }
  128. /**
  129. * Finds greatest common divider (GCD) of $num1 and $num2
  130. *
  131. * @param string $num1
  132. * @param string $num2
  133. * @return string
  134. * @access public
  135. */
  136. function GCD($num1, $num2) {
  137. do {
  138. $tmp = bcmod($num1, $num2);
  139. $num1 = $num2;
  140. $num2 = $tmp;
  141. } while (bccomp($num2, '0'));
  142. return $num1;
  143. }
  144. /**
  145. * Performs Miller-Rabin primality test for number $num
  146. * with base $base. Returns true, if $num is strong pseudoprime
  147. * by base $base. Else returns false.
  148. *
  149. * @param string $num
  150. * @param string $base
  151. * @return bool
  152. * @access private
  153. */
  154. function _millerTest($num, $base) {
  155. if (!bccomp($num, '1')) {
  156. // 1 is not prime ;)
  157. return false;
  158. }
  159. $tmp = bcsub($num, '1');
  160. $zero_bits = 0;
  161. while (!bccomp(bcmod($tmp, '2'), '0')) {
  162. $zero_bits++;
  163. $tmp = bcdiv($tmp, '2');
  164. }
  165. $tmp = $this->powmod($base, $tmp, $num);
  166. if (!bccomp($tmp, '1')) {
  167. // $num is probably prime
  168. return true;
  169. }
  170. while ($zero_bits--) {
  171. if (!bccomp(bcadd($tmp, '1'), $num)) {
  172. // $num is probably prime
  173. return true;
  174. }
  175. $tmp = $this->powmod($tmp, '2', $num);
  176. }
  177. // $num is composite
  178. return false;
  179. }
  180. /**
  181. * Transforms binary representation of large integer into its native form.
  182. *
  183. * Example of transformation:
  184. * $str = "\x12\x34\x56\x78\x90";
  185. * $num = 0x9078563412;
  186. *
  187. * @param string $str
  188. * @return string
  189. * @access public
  190. */
  191. function bin2int($str) {
  192. $result = '0';
  193. $n = strlen($str);
  194. do {
  195. $result = bcadd(bcmul($result, '256'), ord($str {--$n} ));
  196. } while ($n > 0);
  197. return $result;
  198. }
  199. /**
  200. * Transforms large integer into binary representation.
  201. *
  202. * Example of transformation:
  203. * $num = 0x9078563412;
  204. * $str = "\x12\x34\x56\x78\x90";
  205. *
  206. * @param string $num
  207. * @return string
  208. * @access public
  209. */
  210. function int2bin($num) {
  211. $result = '';
  212. do {
  213. $result .= chr(bcmod($num, '256'));
  214. $num = bcdiv($num, '256');
  215. } while (bccomp($num, '0'));
  216. return $result;
  217. }
  218. /**
  219. * Calculates pow($num, $pow) (mod $mod)
  220. *
  221. * @param string $num
  222. * @param string $pow
  223. * @param string $mod
  224. * @return string
  225. * @access public
  226. */
  227. function powmod($num, $pow, $mod) {
  228. if (function_exists('bcpowmod')) {
  229. // bcpowmod is only available under PHP5
  230. return bcpowmod($num, $pow, $mod);
  231. }
  232. // emulate bcpowmod
  233. $result = '1';
  234. do {
  235. if (!bccomp(bcmod($pow, '2'), '1')) {
  236. $result = bcmod(bcmul($result, $num), $mod);
  237. }
  238. $num = bcmod(bcpow($num, '2'), $mod);
  239. $pow = bcdiv($pow, '2');
  240. } while (bccomp($pow, '0'));
  241. return $result;
  242. }
  243. /**
  244. * Calculates $num1 * $num2
  245. *
  246. * @param string $num1
  247. * @param string $num2
  248. * @return string
  249. * @access public
  250. */
  251. function mul($num1, $num2) {
  252. return bcmul($num1, $num2);
  253. }
  254. /**
  255. * Calculates $num1 % $num2
  256. *
  257. * @param string $num1
  258. * @param string $num2
  259. * @return string
  260. * @access public
  261. */
  262. function mod($num1, $num2) {
  263. return bcmod($num1, $num2);
  264. }
  265. /**
  266. * Compares abs($num1) to abs($num2).
  267. * Returns:
  268. * -1, if abs($num1) < abs($num2)
  269. * 0, if abs($num1) == abs($num2)
  270. * 1, if abs($num1) > abs($num2)
  271. *
  272. * @param string $num1
  273. * @param string $num2
  274. * @return int
  275. * @access public
  276. */
  277. function cmpAbs($num1, $num2) {
  278. return bccomp($num1, $num2);
  279. }
  280. /**
  281. * Tests $num on primality. Returns true, if $num is strong pseudoprime.
  282. * Else returns false.
  283. *
  284. * @param string $num
  285. * @return bool
  286. * @access private
  287. */
  288. function isPrime($num) {
  289. static $primes = null;
  290. static $primes_cnt = 0;
  291. if (is_null($primes)) {
  292. // generate all primes up to 10000
  293. $primes = array();
  294. for ($i = 0; $i < 10000; $i++) {
  295. $primes[] = $i;
  296. }
  297. $primes[0] = $primes[1] = 0;
  298. for ($i = 2; $i < 100; $i++) {
  299. while (!$primes[$i]) {
  300. $i++;
  301. }
  302. $j = $i;
  303. for ($j += $i; $j < 10000; $j += $i) {
  304. $primes[$j] = 0;
  305. }
  306. }
  307. $j = 0;
  308. for ($i = 0; $i < 10000; $i++) {
  309. if ($primes[$i]) {
  310. $primes[$j++] = $primes[$i];
  311. }
  312. }
  313. $primes_cnt = $j;
  314. }
  315. // try to divide number by small primes
  316. for ($i = 0; $i < $primes_cnt; $i++) {
  317. if (bccomp($num, $primes[$i]) <= 0) {
  318. // number is prime
  319. return true;
  320. }
  321. if (!bccomp(bcmod($num, $primes[$i]), '0')) {
  322. // number divides by $primes[$i]
  323. return false;
  324. }
  325. }
  326. /*
  327. try Miller-Rabin's probable-primality test for first
  328. 7 primes as bases
  329. */
  330. for ($i = 0; $i < 7; $i++) {
  331. if (!$this->_millerTest($num, $primes[$i])) {
  332. // $num is composite
  333. return false;
  334. }
  335. }
  336. // $num is strong pseudoprime
  337. return true;
  338. }
  339. /**
  340. * Produces a better random number
  341. * for seeding mt_rand()
  342. *
  343. * @access private
  344. */
  345. function _makeSeed() {
  346. return hexdec(sha1(sha1(microtime()*mt_rand()).md5(microtime()*mt_rand())));
  347. }
  348. /**
  349. * Generates prime number with length $bits_cnt
  350. *
  351. * @param int $bits_cnt
  352. * @access public
  353. */
  354. function getPrime($bits_cnt) {
  355. $bytes_n = intval($bits_cnt / 8);
  356. $bits_n = $bits_cnt % 8;
  357. do {
  358. $str = '';
  359. mt_srand($this->_makeSeed());
  360. for ($i = 0; $i < $bytes_n; $i++) {
  361. $str .= chr(sha1(mt_rand() * microtime()) & 0xff);
  362. }
  363. $n = mt_rand() * microtime() & 0xff;
  364. $n |= 0x80;
  365. $n >>= 8 - $bits_n;
  366. $str .= chr($n);
  367. $num = $this->bin2int($str);
  368. // search for the next closest prime number after [$num]
  369. if (!bccomp(bcmod($num, '2'), '0')) {
  370. $num = bcadd($num, '1');
  371. }
  372. while (!$this->isPrime($num)) {
  373. $num = bcadd($num, '2');
  374. }
  375. } while ($this->bitLen($num) != $bits_cnt);
  376. return $num;
  377. }
  378. /**
  379. * Calculates $num - 1
  380. *
  381. * @param string $num
  382. * @return string
  383. * @access public
  384. */
  385. function dec($num) {
  386. return bcsub($num, '1');
  387. }
  388. /**
  389. * Returns true, if $num is equal to one. Else returns false
  390. *
  391. * @param string $num
  392. * @return bool
  393. * @access public
  394. */
  395. function isOne($num) {
  396. return !bccomp($num, '1');
  397. }
  398. /**
  399. * Finds inverse number $inv for $num by modulus $mod, such as:
  400. * $inv * $num = 1 (mod $mod)
  401. *
  402. * @param string $num
  403. * @param string $mod
  404. * @return string
  405. * @access public
  406. */
  407. function invmod($num, $mod) {
  408. $x = '1';
  409. $y = '0';
  410. $num1 = $mod;
  411. do {
  412. $tmp = bcmod($num, $num1);
  413. $q = bcdiv($num, $num1);
  414. $num = $num1;
  415. $num1 = $tmp;
  416. $tmp = bcsub($x, bcmul($y, $q));
  417. $x = $y;
  418. $y = $tmp;
  419. } while (bccomp($num1, '0'));
  420. if (bccomp($x, '0') < 0) {
  421. $x = bcadd($x, $mod);
  422. }
  423. return $x;
  424. }
  425. /**
  426. * Returns bit length of number $num
  427. *
  428. * @param string $num
  429. * @return int
  430. * @access public
  431. */
  432. function bitLen($num) {
  433. $tmp = $this->int2bin($num);
  434. $bit_len = strlen($tmp) * 8;
  435. $tmp = ord($tmp {strlen($tmp) - 1} );
  436. if (!$tmp) {
  437. $bit_len -= 8;
  438. } else {
  439. while (!($tmp & 0x80)) {
  440. $bit_len--;
  441. $tmp <<= 1;
  442. }
  443. }
  444. return $bit_len;
  445. }
  446. /**
  447. * Calculates bitwise or of $num1 and $num2,
  448. * starting from bit $start_pos for number $num1
  449. *
  450. * @param string $num1
  451. * @param string $num2
  452. * @param int $start_pos
  453. * @return string
  454. * @access public
  455. */
  456. function bitOr($num1, $num2, $start_pos) {
  457. $start_byte = intval($start_pos / 8);
  458. $start_bit = $start_pos % 8;
  459. $tmp1 = $this->int2bin($num1);
  460. $num2 = bcmul($num2, 1 << $start_bit);
  461. $tmp2 = $this->int2bin($num2);
  462. if ($start_byte < strlen($tmp1)) {
  463. $tmp2 |= substr($tmp1, $start_byte);
  464. $tmp1 = substr($tmp1, 0, $start_byte).$tmp2;
  465. } else {
  466. $tmp1 = str_pad($tmp1, $start_byte, "\0").$tmp2;
  467. }
  468. return $this->bin2int($tmp1);
  469. }
  470. /**
  471. * Returns part of number $num, starting at bit
  472. * position $start with length $length
  473. *
  474. * @param string $num
  475. * @param int start
  476. * @param int length
  477. * @return string
  478. * @access public
  479. */
  480. function subint($num, $start, $length) {
  481. $start_byte = intval($start / 8);
  482. $start_bit = $start % 8;
  483. $byte_length = intval($length / 8);
  484. $bit_length = $length % 8;
  485. if ($bit_length) {
  486. $byte_length++;
  487. }
  488. $num = bcdiv($num, 1 << $start_bit);
  489. $tmp = substr($this->int2bin($num), $start_byte, $byte_length);
  490. $tmp = str_pad($tmp, $byte_length, "\0");
  491. $tmp = substr_replace($tmp, $tmp {$byte_length - 1} & chr(0xff >> (8 - $bit_length)), $byte_length - 1, 1);
  492. return $this->bin2int($tmp);
  493. }
  494. /**
  495. * Converts a hex string to bigint string
  496. *
  497. * @param string $hex
  498. * @return string
  499. * @access public
  500. */
  501. function hex2bint($hex) {
  502. $result = '0';
  503. for ($i = 0; $i < strlen($hex); $i++) {
  504. $result = bcmul($result, '16');
  505. if ($hex[$i] >= '0' && $hex[$i] <= '9') {
  506. $result = bcadd($result, $hex[$i]);
  507. } else if ($hex[$i] >= 'a' && $hex[$i] <= 'f') {
  508. $result = bcadd($result, '1'.('0' + (ord($hex[$i]) - ord('a'))));
  509. } else if ($hex[$i] >= 'A' && $hex[$i] <= 'F') {
  510. $result = bcadd($result, '1'.('0' + (ord($hex[$i]) - ord('A'))));
  511. }
  512. }
  513. return $result;
  514. }
  515. /**
  516. * Converts a hex string to int
  517. *
  518. * @param string $hex
  519. * @return int
  520. * @access public
  521. */
  522. function hex2int($hex) {
  523. $result = 0;
  524. for ($i = 0; $i < strlen($hex); $i++) {
  525. $result *= 16;
  526. if ($hex[$i] >= '0' && $hex[$i] <= '9') {
  527. $result += ord($hex[$i]) - ord('0');
  528. } else if ($hex[$i] >= 'a' && $hex[$i] <= 'f') {
  529. $result += 10 + (ord($hex[$i]) - ord('a'));
  530. } else if ($hex[$i] >= 'A' && $hex[$i] <= 'F') {
  531. $result += 10 + (ord($hex[$i]) - ord('A'));
  532. }
  533. }
  534. return $result;
  535. }
  536. /**
  537. * Converts a bigint string to the ascii code
  538. *
  539. * @param string $bigint
  540. * @return string
  541. * @access public
  542. */
  543. function bint2char($bigint) {
  544. $message = '';
  545. while (bccomp($bigint, '0') != 0) {
  546. $ascii = bcmod($bigint, '256');
  547. $bigint = bcdiv($bigint, '256', 0);
  548. $message .= chr($ascii);
  549. }
  550. return $message;
  551. }
  552. /**
  553. * Removes the redundacy in den encrypted string
  554. *
  555. * @param string $string
  556. * @return mixed
  557. * @access public
  558. */
  559. function redundacyCheck($string) {
  560. $r1 = substr($string, 0, 2);
  561. $r2 = substr($string, 2);
  562. $check = $this->hex2int($r1);
  563. $value = $r2;
  564. $sum = 0;
  565. for ($i = 0; $i < strlen($value); $i++) {
  566. $sum += ord($value[$i]);
  567. }
  568. if ($check == ($sum & 0xFF)) {
  569. return $value;
  570. } else {
  571. return NULL;
  572. }
  573. }
  574. /**
  575. * Decrypts a given string with the $dec_key and the $enc_mod
  576. *
  577. * @param string $encrypted
  578. * @param int $dec_key
  579. * @param int $enc_mod
  580. * @return string
  581. * @access public
  582. */
  583. function decrypt($encrypted, $dec_key, $enc_mod) {
  584. //replaced split with explode
  585. $blocks = explode(' ', $encrypted);
  586. $result = "";
  587. $max = count($blocks);
  588. for ($i = 0; $i < $max; $i++) {
  589. $dec = $this->hex2bint($blocks[$i]);
  590. $dec = $this->powmod($dec, $dec_key, $enc_mod);
  591. $ascii = $this->bint2char($dec);
  592. $result .= $ascii;
  593. }
  594. return $this->redundacyCheck($result);
  595. }
  596. /**
  597. * Converts a given decimal string to any base between 2 and 36
  598. *
  599. * @param string $decimal
  600. * @param int $base
  601. * @return string
  602. */
  603. function dec2string($decimal, $base) {
  604. $string = null;
  605. $base = (int) $base;
  606. if ($base < 2 | $base > 36 | $base == 10) {
  607. echo 'BASE must be in the range 2-9 or 11-36';
  608. exit;
  609. }
  610. $charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  611. $charset = substr($charset, 0, $base);
  612. do {
  613. $remainder = bcmod($decimal, $base);
  614. $char = substr($charset, $remainder, 1);
  615. $string = "$char$string";
  616. $decimal = bcdiv(bcsub($decimal, $remainder), $base);
  617. } while ($decimal > 0);
  618. return strtolower($string);
  619. }
  620. function getE() {
  621. return $this->_e;
  622. }
  623. function generatePrime($length) {
  624. $this->_key_len = intval($length);
  625. if ($this->_key_len < 8) {
  626. $this->_key_len = 8;
  627. }
  628. $e = $this->bin2int("\x01\x00\x01");
  629. $p_len = intval(($this->_key_len + 1) / 2);
  630. do {
  631. $p = $this->getPrime($p_len);
  632. $p1 = $this->dec($p);
  633. $tmp = $this->GCD($e, $p1);
  634. } while (!$this->isOne($tmp));
  635. return $p;
  636. }
  637. }
  638. ?>