Project

General

Profile

Statistics
| Branch: | Revision:

colonymech / docs / www / colonyscout / internal / includes / jCryption-1.1.php @ f59acf11

History | View | Annotate | Download (15.6 KB)

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  2009 Daniel Griesser
21
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
22
 * @version    1.0.1
23
 * @link       http://jcryption.org/
24
 */
25
class jCryption {
26
        
27
        var $_key_len;
28
        var $_e;
29

    
30
        /**
31
     * Constructor
32
     *
33
     * @access public
34
     */
35
        function jCryption($e = "\x01\x00\x01") {
36
                $this->_e = $e;
37
        }
38
        
39
        /**
40
     * Generates the Keypair with the given keyLength the encryption key e ist set staticlly
41
         * set to 65537 for faster encryption.
42
     *
43
     * @param int $keyLength
44
     * @return array
45
     * @access public
46
     */
47
        function generateKeypair($keyLength) {
48
                $this->_key_len = intval($keyLength);
49
                if ($this->_key_len < 8) {
50
                        $this->_key_len = 8;
51
                }
52

    
53
                // set [e] to 0x10001 (65537)
54
                $e = $this->bin2int($this->_e);
55

    
56
                // generate [p], [q] and [n]
57
                $p_len = intval(($this->_key_len + 1) / 2);
58
                $q_len = $this->_key_len - $p_len;
59
                $p1 = $q1 = 0;
60
                do {
61
                        // generate prime number [$p] with length [$p_len] with the following condition:
62
                        // GCD($e, $p - 1) = 1
63

    
64
                        do {
65
                                $p = $this->getPrime($p_len);
66
                                $p1 = $this->dec($p);
67
                                $tmp = $this->GCD($e, $p1);
68
                        } while (!$this->isOne($tmp));
69
                        // generate prime number [$q] with length [$q_len] with the following conditions:
70
                        // GCD($e, $q - 1) = 1
71
                        // $q != $p
72

    
73
                        do {
74
                                $q = $this->getPrime($q_len);
75
                                //$q = 102238965184417281201422828818276460200050705922822343263269460146519295919831;
76
                                $q1 = $this->dec($q);
77
                                $tmp = $this->GCD($e, $q1);
78
                        } while (!$this->isOne($tmp) && !$this->cmpAbs($q, $p));
79

    
80
                        // if (p < q), then exchange them
81
                        if ($this->cmpAbs($p, $q) < 0) {
82
                                $tmp = $p;
83
                                $p = $q;
84
                                $q = $tmp;
85
                                $tmp = $p1;
86
                                $p1 = $q1;
87
                                $q1 = $tmp;
88
                        }
89
                        // calculate n = p * q
90
                        $n = $this->mul($p, $q);
91

    
92
                } while ($this->bitLen($n) != $this->_key_len);
93

    
94
                // calculate d = 1/e mod (p - 1) * (q - 1)
95
                $pq = $this->mul($p1, $q1);
96
                $d = $this->invmod($e, $pq);
97

    
98
                // store RSA keypair attributes
99
                $keypair = array('n'=>$n, 'e'=>$e, 'd'=>$d, 'p'=>$p, 'q'=>$q);
100

    
101
                return $keypair;
102
        }
103
        
104
        function useKeys($keys,$keyLength) {
105
                $this->_key_len = intval($keyLength);
106
                if ($this->_key_len < 8) {
107
                        $this->_key_len = 8;
108
                }
109

    
110
                // set [e] to 0x10001 (65537)
111
                $e = $this->bin2int($this->_e);
112

    
113
                // generate [p], [q] and [n]
114
                $p_len = intval(($this->_key_len + 1) / 2);
115
                $q_len = $this->_key_len - $p_len;
116
                $p1 = $q1 = 0;
117
                do {
118
                        do {
119
                                $q = $keys[rand(0,count($keys))];
120
                                $p = $keys[rand(0,count($keys))];
121
                                $p1 = $this->dec($p);
122
                                $q1 = $this->dec($q);
123
                        } while (!$this->cmpAbs($q, $p));
124

    
125

    
126
                        // if (p < q), then exchange them
127
                        if ($this->cmpAbs($p, $q) < 0) {
128
                                $tmp = $p;
129
                                $p = $q;
130
                                $q = $tmp;
131
                                $tmp = $p1;
132
                                $p1 = $q1;
133
                                $q1 = $tmp;
134
                        }
135
                        // calculate n = p * q
136
                        $n = $this->mul($p, $q);
137

    
138
                } while ($this->bitLen($n) != $this->_key_len);
139

    
140
                // calculate d = 1/e mod (p - 1) * (q - 1)
141
                $pq = $this->mul($p1, $q1);
142
                $d = $this->invmod($e, $pq);
143

    
144
                // store RSA keypair attributes
145
                $keypair = array('n'=>$n, 'e'=>$e, 'd'=>$d, 'p'=>$p, 'q'=>$q);
146

    
147
                return $keypair;
148
        }
149

    
150
        /**
151
     * Finds greatest common divider (GCD) of $num1 and $num2
152
     *
153
     * @param string $num1
154
     * @param string $num2
155
     * @return string
156
     * @access public
157
     */
158
        function GCD($num1, $num2) {
159
                do {
160
                        $tmp = bcmod($num1, $num2);
161
                        $num1 = $num2;
162
                        $num2 = $tmp;
163
                } while (bccomp($num2, '0'));
164
                return $num1;
165
        }
166

    
167
        /**
168
     * Performs Miller-Rabin primality test for number $num
169
     * with base $base. Returns true, if $num is strong pseudoprime
170
     * by base $base. Else returns false.
171
     *
172
     * @param string $num
173
     * @param string $base
174
     * @return bool
175
     * @access private
176
     */
177
        function _millerTest($num, $base) {
178
                if (!bccomp($num, '1')) {
179
                        // 1 is not prime ;)
180
                        return false;
181
                }
182
                $tmp = bcsub($num, '1');
183

    
184
                $zero_bits = 0;
185
                while (!bccomp(bcmod($tmp, '2'), '0')) {
186
                        $zero_bits++;
187
                        $tmp = bcdiv($tmp, '2');
188
                }
189

    
190
                $tmp = $this->powmod($base, $tmp, $num);
191
                if (!bccomp($tmp, '1')) {
192
                        // $num is probably prime
193
                        return true;
194
                }
195

    
196
                while ($zero_bits--) {
197
                        if (!bccomp(bcadd($tmp, '1'), $num)) {
198
                                // $num is probably prime
199
                                return true;
200
                        }
201
                        $tmp = $this->powmod($tmp, '2', $num);
202
                }
203
                // $num is composite
204
                return false;
205
        }
206

    
207
        /**
208
     * Transforms binary representation of large integer into its native form.
209
     *
210
     * Example of transformation:
211
     *    $str = "\x12\x34\x56\x78\x90";
212
     *    $num = 0x9078563412;
213
     *
214
     * @param string $str
215
     * @return string
216
     * @access public
217
     */
218
        function bin2int($str) {
219
                $result = '0';
220
                $n = strlen($str);
221
                do {
222
                        $result = bcadd(bcmul($result, '256'), ord($str {--$n} ));
223
                } while ($n > 0);
224
                return $result;
225
        }
226

    
227
        /**
228
     * Transforms large integer into binary representation.
229
     *
230
     * Example of transformation:
231
     *    $num = 0x9078563412;
232
     *    $str = "\x12\x34\x56\x78\x90";
233
     *
234
     * @param string $num
235
     * @return string
236
     * @access public
237
     */
238
        function int2bin($num) {
239
                $result = '';
240
                do {
241
                        $result .= chr(bcmod($num, '256'));
242
                        $num = bcdiv($num, '256');
243
                } while (bccomp($num, '0'));
244
                return $result;
245
        }
246

    
247
        /**
248
     * Calculates pow($num, $pow) (mod $mod)
249
     *
250
     * @param string $num
251
     * @param string $pow
252
     * @param string $mod
253
     * @return string
254
     * @access public
255
     */
256
        function powmod($num, $pow, $mod) {
257
                if (function_exists('bcpowmod')) {
258
                        // bcpowmod is only available under PHP5
259
                        return bcpowmod($num, $pow, $mod);
260
                }
261

    
262
                // emulate bcpowmod
263
                $result = '1';
264
                do {
265
                        if (!bccomp(bcmod($pow, '2'), '1')) {
266
                                $result = bcmod(bcmul($result, $num), $mod);
267
                        }
268
                        $num = bcmod(bcpow($num, '2'), $mod);
269
                        $pow = bcdiv($pow, '2');
270
                } while (bccomp($pow, '0'));
271
                return $result;
272
        }
273

    
274
        /**
275
     * Calculates $num1 * $num2
276
     *
277
     * @param string $num1
278
     * @param string $num2
279
     * @return string
280
     * @access public
281
     */
282
        function mul($num1, $num2) {
283
                return bcmul($num1, $num2);
284
        }
285

    
286
        /**
287
     * Calculates $num1 % $num2
288
     *
289
     * @param string $num1
290
     * @param string $num2
291
     * @return string
292
     * @access public
293
     */
294
        function mod($num1, $num2) {
295
                return bcmod($num1, $num2);
296
        }
297

    
298
        /**
299
     * Compares abs($num1) to abs($num2).
300
     * Returns:
301
     *   -1, if abs($num1) < abs($num2)
302
     *   0, if abs($num1) == abs($num2)
303
     *   1, if abs($num1) > abs($num2)
304
     *
305
     * @param string $num1
306
     * @param string $num2
307
     * @return int
308
     * @access public
309
     */
310
        function cmpAbs($num1, $num2) {
311
                return bccomp($num1, $num2);
312
        }
313

    
314
        /**
315
     * Tests $num on primality. Returns true, if $num is strong pseudoprime.
316
     * Else returns false.
317
     *
318
     * @param string $num
319
     * @return bool
320
     * @access private
321
     */
322
        function isPrime($num) {
323
                static $primes = null;
324
                static $primes_cnt = 0;
325
                if (is_null($primes)) {
326
                        // generate all primes up to 10000
327
                        $primes = array();
328
                        for ($i = 0; $i < 10000; $i++) {
329
                                $primes[] = $i;
330
                        }
331
                        $primes[0] = $primes[1] = 0;
332
                        for ($i = 2; $i < 100; $i++) {
333
                                while (!$primes[$i]) {
334
                                        $i++;
335
                                }
336
                                $j = $i;
337
                                for ($j += $i; $j < 10000; $j += $i) {
338
                                        $primes[$j] = 0;
339
                                }
340
                        }
341
                        $j = 0;
342
                        for ($i = 0; $i < 10000; $i++) {
343
                                if ($primes[$i]) {
344
                                        $primes[$j++] = $primes[$i];
345
                                }
346
                        }
347
                        $primes_cnt = $j;
348
                }
349

    
350
                // try to divide number by small primes
351
                for ($i = 0; $i < $primes_cnt; $i++) {
352
                        if (bccomp($num, $primes[$i]) <= 0) {
353
                                // number is prime
354
                                return true;
355
                        }
356
                        if (!bccomp(bcmod($num, $primes[$i]), '0')) {
357
                                // number divides by $primes[$i]
358
                                return false;
359
                        }
360
                }
361

    
362
                /*
363
                try Miller-Rabin's probable-primality test for first
364
                7 primes as bases
365
                */
366
                for ($i = 0; $i < 7; $i++) {
367
                        if (!$this->_millerTest($num, $primes[$i])) {
368
                                // $num is composite
369
                                return false;
370
                        }
371
                }
372
                // $num is strong pseudoprime
373
                return true;
374
        }
375
        
376
        /**
377
     * Produces a better random number
378
         * for seeding mt_rand()
379
     *
380
     * @access private
381
     */
382
        function _makeSeed() {
383
                return hexdec(sha1(sha1(microtime()*mt_rand()).md5(microtime()*mt_rand())));
384
        }
385

    
386
        /**
387
     * Generates prime number with length $bits_cnt
388
     *
389
     * @param int $bits_cnt
390
     * @access public
391
     */
392
        function getPrime($bits_cnt) {
393
                $bytes_n = intval($bits_cnt / 8);
394
                $bits_n = $bits_cnt % 8;
395
                do {
396
                        $str = '';
397
                        mt_srand($this->_makeSeed());
398
                        for ($i = 0; $i < $bytes_n; $i++) {
399
                                $str .= chr(sha1(mt_rand() * microtime()) & 0xff);
400
                        }
401
                        $n = mt_rand() * microtime() & 0xff;
402

    
403
                        $n |= 0x80;
404
                        $n >>= 8 - $bits_n;
405
                        $str .= chr($n);
406
                        $num = $this->bin2int($str);
407

    
408
                        // search for the next closest prime number after [$num]
409
                        if (!bccomp(bcmod($num, '2'), '0')) {
410
                                $num = bcadd($num, '1');
411
                        }
412
                        while (!$this->isPrime($num)) {
413
                                $num = bcadd($num, '2');
414
                        }
415

    
416
                } while ($this->bitLen($num) != $bits_cnt);
417
                return $num;
418
        }
419

    
420
        /**
421
     * Calculates $num - 1
422
     *
423
     * @param string $num
424
     * @return string
425
     * @access public
426
     */
427
        function dec($num) {
428
                return bcsub($num, '1');
429
        }
430

    
431
        /**
432
     * Returns true, if $num is equal to one. Else returns false
433
     *
434
     * @param string $num
435
     * @return bool
436
     * @access public
437
     */
438
        function isOne($num) {
439
                return !bccomp($num, '1');
440
        }
441

    
442
        /**
443
     * Finds inverse number $inv for $num by modulus $mod, such as:
444
     *     $inv * $num = 1 (mod $mod)
445
     *
446
     * @param string $num
447
     * @param string $mod
448
     * @return string
449
     * @access public
450
     */
451
        function invmod($num, $mod) {
452
                $x = '1';
453
                $y = '0';
454
                $num1 = $mod;
455
                do {
456
                        $tmp = bcmod($num, $num1);
457
                        $q = bcdiv($num, $num1);
458
                        $num = $num1;
459
                        $num1 = $tmp;
460

    
461
                        $tmp = bcsub($x, bcmul($y, $q));
462
                        $x = $y;
463
                        $y = $tmp;
464
                } while (bccomp($num1, '0'));
465
                if (bccomp($x, '0') < 0) {
466
                        $x = bcadd($x, $mod);
467
                }
468
                return $x;
469
        }
470

    
471
        /**
472
     * Returns bit length of number $num
473
     *
474
     * @param string $num
475
     * @return int
476
     * @access public
477
     */
478
        function bitLen($num) {
479
                $tmp = $this->int2bin($num);
480
                $bit_len = strlen($tmp) * 8;
481
                $tmp = ord($tmp {strlen($tmp) - 1} );
482
                if (!$tmp) {
483
                        $bit_len -= 8;
484
                } else {
485
                        while (!($tmp & 0x80)) {
486
                                $bit_len--;
487
                                $tmp <<= 1;
488
                        }
489
                }
490
                return $bit_len;
491
        }
492

    
493
        /**
494
     * Calculates bitwise or of $num1 and $num2,
495
     * starting from bit $start_pos for number $num1
496
     *
497
     * @param string $num1
498
     * @param string $num2
499
     * @param int $start_pos
500
     * @return string
501
     * @access public
502
     */
503
        function bitOr($num1, $num2, $start_pos) {
504
                $start_byte = intval($start_pos / 8);
505
                $start_bit = $start_pos % 8;
506
                $tmp1 = $this->int2bin($num1);
507

    
508
                $num2 = bcmul($num2, 1 << $start_bit);
509
                $tmp2 = $this->int2bin($num2);
510
                if ($start_byte < strlen($tmp1)) {
511
                        $tmp2 |= substr($tmp1, $start_byte);
512
                        $tmp1 = substr($tmp1, 0, $start_byte).$tmp2;
513
                } else {
514
                        $tmp1 = str_pad($tmp1, $start_byte, "\0").$tmp2;
515
                }
516
                return $this->bin2int($tmp1);
517
        }
518

    
519
        /**
520
     * Returns part of number $num, starting at bit
521
     * position $start with length $length
522
     *
523
     * @param string $num
524
     * @param int start
525
     * @param int length
526
     * @return string
527
     * @access public
528
     */
529
        function subint($num, $start, $length) {
530
                $start_byte = intval($start / 8);
531
                $start_bit = $start % 8;
532
                $byte_length = intval($length / 8);
533
                $bit_length = $length % 8;
534
                if ($bit_length) {
535
                        $byte_length++;
536
                }
537
                $num = bcdiv($num, 1 << $start_bit);
538
                $tmp = substr($this->int2bin($num), $start_byte, $byte_length);
539
                $tmp = str_pad($tmp, $byte_length, "\0");
540
                $tmp = substr_replace($tmp, $tmp {$byte_length - 1} & chr(0xff >> (8 - $bit_length)), $byte_length - 1, 1);
541
                return $this->bin2int($tmp);
542
        }
543

    
544
        /**
545
     * Converts a hex string to bigint string
546
     *
547
     * @param string $hex
548
     * @return string
549
     * @access public
550
     */
551
        function hex2bint($hex) {
552
                $result = '0';
553
                for ($i = 0; $i < strlen($hex); $i++) {
554
                        $result = bcmul($result, '16');
555
                        if ($hex[$i] >= '0' && $hex[$i] <= '9') {
556
                                $result = bcadd($result, $hex[$i]);
557
                        } else if ($hex[$i] >= 'a' && $hex[$i] <= 'f') {
558
                                $result = bcadd($result, '1'.('0' + (ord($hex[$i]) - ord('a'))));
559
                        } else if ($hex[$i] >= 'A' && $hex[$i] <= 'F') {
560
                                $result = bcadd($result, '1'.('0' + (ord($hex[$i]) - ord('A'))));
561
                        }
562
                }
563
                return $result;
564
        }
565

    
566
        /**
567
         * Converts a hex string to int
568
         *
569
         * @param string $hex
570
         * @return int
571
         * @access public
572
         */
573
        function hex2int($hex) {
574
                $result = 0;
575
                for ($i = 0; $i < strlen($hex); $i++) {
576
                        $result *= 16;
577
                        if ($hex[$i] >= '0' && $hex[$i] <= '9') {
578
                                $result += ord($hex[$i]) - ord('0');
579
                        } else if ($hex[$i] >= 'a' && $hex[$i] <= 'f') {
580
                                $result += 10 + (ord($hex[$i]) - ord('a'));
581
                        } else if ($hex[$i] >= 'A' && $hex[$i] <= 'F') {
582
                                $result += 10 + (ord($hex[$i]) - ord('A'));
583
                        }
584
                }
585
                return $result;
586
        }
587

    
588
        /**
589
         * Converts a bigint string to the ascii code
590
         *
591
         * @param string $bigint
592
         * @return string
593
         * @access public
594
         */
595
        function bint2char($bigint) {
596
                $message = '';
597
                while (bccomp($bigint, '0') != 0) {
598
                        $ascii = bcmod($bigint, '256');
599
                        $bigint = bcdiv($bigint, '256', 0);
600
                        $message .= chr($ascii);
601
                }
602
                return $message;
603
        }
604

    
605
        /**
606
         * Removes the redundacy in den encrypted string
607
         *
608
         * @param string $string
609
         * @return mixed
610
         * @access public
611
         */
612
        function redundacyCheck($string) {
613
                $r1 = substr($string, 0, 2);
614
                $r2 = substr($string, 2);
615
                $check = $this->hex2int($r1);
616
                $value = $r2;
617
                $sum = 0;
618
                for ($i = 0; $i < strlen($value); $i++) {
619
                        $sum += ord($value[$i]);
620
                }
621
                if ($check == ($sum & 0xFF)) {
622
                        return $value;
623
                } else {
624
                        return NULL;
625
                }
626
        }
627

    
628
        /**
629
         * Decrypts a given string with the $dec_key and the $enc_mod
630
         *
631
         * @param string $encrypted
632
         * @param int $dec_key
633
         * @param int $enc_mod
634
         * @return string
635
         * @access public
636
         */
637
        function decrypt($encrypted, $dec_key, $enc_mod) {
638
                $blocks = explode(' ', $encrypted);
639
                $result = "";
640
                $max = count($blocks);
641
                for ($i = 0; $i < $max; $i++) {
642
                        $dec = $this->hex2bint($blocks[$i]);
643
                        $dec = $this->powmod($dec, $dec_key, $enc_mod);
644
                        $ascii = $this->bint2char($dec);
645
                        $result .= $ascii;
646
                }
647
                return $this->redundacyCheck($result);
648
        }
649

    
650
        /**
651
         * Converts a given decimal string to any base between 2 and 36
652
         *
653
         * @param string $decimal
654
         * @param int $base
655
         * @return string
656
         */
657
        function dec2string($decimal, $base) {
658

    
659
                $string = null;
660

    
661
                $base = (int) $base;
662
                if ($base < 2 | $base > 36 | $base == 10) {
663
                        echo 'BASE must be in the range 2-9 or 11-36';
664
                        exit;
665
                }
666

    
667
                $charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
668

    
669
                $charset = substr($charset, 0, $base);
670

    
671
                do {
672
                        $remainder = bcmod($decimal, $base);
673
                        $char = substr($charset, $remainder, 1);
674
                        $string = "$char$string";
675
                        $decimal = bcdiv(bcsub($decimal, $remainder), $base);
676
                } while ($decimal > 0);
677

    
678
                return strtolower($string);
679
        }
680
        
681
        function getE() {
682
                return $this->_e;
683
        }
684
        
685
        function generatePrime($length) {
686
                $this->_key_len = intval($length);
687
                if ($this->_key_len < 8) {
688
                        $this->_key_len = 8;
689
                }
690
                
691
                $e = $this->bin2int("\x01\x00\x01");
692

    
693
                $p_len = intval(($this->_key_len + 1) / 2);
694
                do {
695
                                $p = $this->getPrime($p_len);
696
                                $p1 = $this->dec($p);
697
                                $tmp = $this->GCD($e, $p1);
698
                } while (!$this->isOne($tmp));
699
                
700
                return $p;
701
        }
702

    
703
}
704

    
705
?>