Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 www 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace LeadersLinked\Library;
6
 
7
 
8
/*
9
 *v.1.3 [2 Sep 2002]
10
 
11
 9-8-2002: very simple conversion of example to class form <chucks <at> arizona <dot> edu>
12
 
13
 * Rivest/Shamir/Adelman (RSA) compatible functions
14
 * to generate keys and encode/decode plaintext messages.
15
 * Plaintext must contain only ASCII(32) - ASCII(126) characters.
16
 
17
 *Send questions and suggestions to Ilya Rudev <www <at> polar-lights <dot> com> (Polar Lights Labs)
18
 
19
 *most part of code ported from different
20
 *C++, JS and Flash
21
 *RSA examples found in books and in the net :)
22
 
23
 *supplied with Hacker Hunter authentication system.
24
 *http://www.polar-lights.com/hackerhunter/
25
 
26
 *It is distributed in the hope that it will be useful, but
27
 *WITHOUT ANY WARRANTY; without even the implied warranty of
28
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
29
 *See the GNU General Public License for more details.
30
 
31
 *With a great thanks to:
32
 *Glenn Haecker <ghaecker <at> idworld <dot> net>
33
 *Segey Semenov <sergei2002 <at> mail <dot> ru>
34
 *Suivan <ssuuii <at> gmx <dot> net>
35
 */
36
 
37
class Rsa {
38
    /**
39
     *
40
     * @var array
41
     */
42
    private $primes;
43
 
44
    /**
45
     *
46
     * @var int
47
     */
48
    private $maxprimes;
49
 
50
    /**
51
     *
52
     * @var Rsa
53
     */
54
    private static $_instance;
55
 
56
    /**
57
     *
58
     * @var int
59
     */
60
    private $n;
61
 
62
    /**
63
     *
64
     * @var int
65
     */
66
    private $e;
67
 
68
    /**
69
     *
70
     * @var int
71
     */
72
    private $d;
73
 
74
    /**
75
     *
76
     * @return Rsa
77
     */
78
    public static function getInstance()
79
    {
80
        if(!self::$_instance) {
81
            self::$_instance = new Rsa();
82
        }
83
 
84
 
85
 
86
        return self::$_instance;
87
    }
88
 
89
    private function __construct($n = 0, $d = 0)
90
    {
91
        /*random generator seed */
92
        //mt_srand((double)microtime()*1000000);
93
        mt_srand((int)microtime()*1000000);
94
        /*
95
         * Prime numbers table
96
         * 570 prime numbers (Array can not be be enlarged)
97
         * 4507, 4513 is the smallest and 9521, 9533 is the largest pair
98
         * Still have no time to find why 9521, 9533 is the largest - sorry :)
99
         */
100
        $this->primes = array (4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597,
101
            4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
102
            4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931,
103
            4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051,
104
            5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227,
105
            5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399,
106
            5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
107
            5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683,
108
            5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839,
109
            5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007,
110
            6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151,
111
            6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
112
            6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451,
113
            6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637,
114
            6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791,
115
            6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949,
116
            6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
117
            7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253,
118
            7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477,
119
            7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589,
120
            7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741,
121
            7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
122
            7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093,
123
            8101, 8111, 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243, 8263,
124
            8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429,
125
            8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609,
126
            8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
127
            8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893,
128
            8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029, 9041, 9043, 9049, 9059,
129
            9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227,
130
            9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391, 9397,
131
            9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533);
132
 
133
        $this->maxprimes = count($this->primes) - 1;
134
 
135
 
136
        $this->n = isset($_SESSION['n']) ? $_SESSION['n'] : 0;
137
        $this->e = isset($_SESSION['e']) ? $_SESSION['e'] : 0;
138
        $this->d = isset($_SESSION['d']) ? $_SESSION['d'] : 0;
139
 
140
        if(!$this->n || !$this->e || !$this->d) {
141
            $keys = $this->generateKeys();
142
            $this->n = $keys['n'];
143
            $this->e = $keys['e'];
144
            $this->d = $keys['d'];
145
 
146
            $_SESSION['n'] = $this->n;
147
            $_SESSION['e'] = $this->e;
148
            $_SESSION['d'] = $this->d;
149
        }
150
    }
151
 
152
    /*
153
     Function for generating keys. Return array where
154
     $array[0] -> modulo N
155
     $array[1] ->  key E
156
     $array[2] ->  key D
157
     Public key pair is N and E
158
     Private key pair is N and D
159
     */
160
    private function generateKeys()
161
    {
162
        list($usec, $sec) = explode(' ', microtime());
163
        $seed = intval($sec + ((float) $usec * 100000));
164
        mt_srand($seed, MT_RAND_MT19937);
165
 
166
        $e = 0;
167
        $q = 0;
168
        $q = 0;
169
 
170
        //class-ify: global $primes, $maxprimes;
171
        while (empty($e) || empty($d)) {
172
            /* finding 2 small prime numbers $p and $q
173
             $p and $q must be different*/
174
            $p = $this->primes[mt_rand(0, $this->maxprimes)];
175
            while (empty($q) || ($p==$q)) {
176
                $q = $this->primes[mt_rand(0, $this->maxprimes)];
177
            }
178
            //second part of  and  pairs - N
179
            $n = $p*$q;
180
 
181
            //$pi (we need it to calculate D and E)
182
            $pi = ($p - 1) * ($q - 1);
183
 
184
            // Public key  E
185
            $e = $this->tofindE($pi, $p, $q);
186
 
187
            // Private key D
188
            $d = $this->extend($e, $pi);
189
 
190
            $keys = array ('n' => $n, 'd' => $d, 'e' => $e);
191
        }
192
        return $keys;
193
    }
194
 
195
    /* modulus function */
196
    private function mo($g, $l)
197
    {
198
        $result = $g - ($l * floor ($g/$l));
199
 
200
        return $result;
201
    }
202
 
203
    /*
204
     * Standard method of calculating D
205
     * D = E-1 (mod N)
206
     * It's presumed D will be found in less then 16 iterations
207
     */
208
    private function extend($Ee, $Epi) {
209
        $u1 = 1;
210
        $u2 = 0;
211
        $u3 = $Epi;
212
        $v1 = 0;
213
        $v2 = 1;
214
        $v3 = $Ee;
215
        while ($v3 != 0) {
216
            $qq = floor($u3/$v3);
217
            $t1 = $u1 - $qq * $v1;
218
            $t2 = $u2 - $qq * $v2;
219
            $t3 = $u3 - $qq * $v3;
220
            $u1 = $v1;
221
            $u2 = $v2;
222
            $u3 = $v3;
223
            $v1 = $t1;
224
            $v2 = $t2;
225
            $v3 = $t3;
226
            $z = 1;
227
        }
228
        $uu = $u1;
229
        $vv = $u2;
230
        if ($vv < 0) {
231
            $inverse = $vv + $Epi;
232
        } else {
233
            $inverse = $vv;
234
        }
235
        return $inverse;
236
    }
237
 
238
    /* This function return Greatest Common Divisor for $e and $pi numbers */
239
    private function GCD($e, $pi)
240
    {
241
        $y = $e;
242
        $x = $pi;
243
        while ($y != 0) {
244
            $w =  $this->mo($x , $y);
245
            $x = $y;
246
            $y = $w;
247
        }
248
        return $x;
249
    }
250
 
251
    /*function for calculating E under conditions:
252
     GCD(N, E) = 1 and 1<E<N
253
     If each test E is prime, there will be much less loops in that fuction
254
     and smaller E means less JS calculations on client side */
255
    /*
256
     * Calculating E under conditions:
257
     * GCD(N, E) = 1 and 1<E<N
258
     * If E is prime, there will be fewer loops in the function.
259
     * Smaller E also means reduced JS calculations on client side.
260
     */
261
    private function tofindE($pi)
262
    {
263
        //class-ify: global $primes, $maxprimes;
264
        $great = 0;
265
        $cc = mt_rand (0, $this->maxprimes);
266
        $startcc = $cc;
267
        while ($cc >= 0) {
268
            $se = $this->primes[$cc];
269
            $great = $this->GCD($se, $pi);
270
            $cc--;
271
            if ($great == 1) { break; }
272
        }
273
        if ($great == 0) {
274
            $cc = $startcc + 1;
275
            while ($cc <= $this->maxprimes) {
276
                $se = $this->primes[$cc];
277
                $great = $this->GCD($se, $pi);
278
                $cc++;
279
                if ($great == 1) { break; }
280
            }
281
        }
282
        return $se;
283
    }
284
 
285
    /*
286
     * ENCRYPT function returns
287
     *, X = M^E (mod N)
288
     * Please check http://www.ge.kochi-ct.ac.jp/cgi-bin-takagi/calcmodp
289
     * and Flash5 RSA .fla by R.Vijay <rveejay0 <at> hotmail <dot> com> at
290
     * http://www.digitalillusion.co.in/lab/rsaencyp.htm
291
     * It is one of the simplest examples for binary RSA calculations
292
     *
293
     * Each letter in the message is represented as its ASCII code number - 30
294
     * 3 letters in each block with 1 in the beginning and end.
295
     * For example string
296
     *, AAA
297
     * will become
298
     *, 13535351 (A = ASCII 65-30 = 35)
299
     * we can build these blocks because the smalest prime available is 4507
300
     *, 4507^2 = 20313049
301
     * This means that
302
     *, 1. Modulo N will always be < 19999991
303
     *, 2. Letters > ASCII 128 must not occur in plain text message
304
     */
305
 
306
    public function encrypt($m, $e = 0, $n = 0)
307
    {
308
        $e = $e ? $e : $this->e;
309
        $n = $n ? $n : $this->n;
310
 
311
        $m = strval($m);
312
 
313
        $asci = array ();
314
        for ($i=0, $max = strlen($m); $i<$max; $i+=3) {
315
            $tmpasci='1';
316
            for ($h=0; $h<3; $h++)
317
            {
318
                if ($i+$h <strlen($m)) {
319
                    $tmpstr = strval((ord (substr ($m, $i+$h, 1)) - 30));
320
                    if (strlen($tmpstr) < 2) {
321
                        $tmpstr ='0'.$tmpstr;
322
                    }
323
                } else {
324
                    break;
325
                }
326
                $tmpasci .=$tmpstr;
327
            }
328
            array_push($asci, $tmpasci.'1');
329
        }
330
        //Each number is then encrypted using the RSA formula: block ^E mod N
331
        $coded = null;
332
        for ($k=0, $max = count($asci) ; $k < $max; $k++)
333
        {
334
            $resultmod = $this->powmod($asci[$k], $e, $n);
335
            $coded .= $resultmod." ";
336
        }
337
        return strval($coded);
338
    }
339
 
340
    /*Russian Peasant method for exponentiation */
341
    private function powmod($base, $exp, $modulus)
342
    {
343
        $accum = 1;
344
        $i = 0;
345
        $basepow2 = $base;
346
        while (($exp >> $i)>0) {
347
            if ((($exp >> $i) & 1) == 1) {
348
                $accum = $this->mo(($accum * $basepow2) , $modulus);
349
            }
350
            $basepow2 = $this->mo(($basepow2 * $basepow2) , $modulus);
351
            $i++;
352
        }
353
        return $accum;
354
    }
355
 
356
    /*
357
     ENCRYPT function returns
358
     M = X^D (mod N)
359
     */
360
    public function decrypt($c, $d = 0, $n = 0) {
361
        $d = $d ? $d : $this->d;
362
        $n = $n ? $n : $this->n;
363
 
364
        $c = strval($c);
365
 
366
        //Strip the blank spaces from the ecrypted text and store it in an array
367
        $decryptarray = explode(' ', $c);
368
        for ($u=0; $u<count ($decryptarray); $u++)
369
        {
370
            if ($decryptarray[$u] == '') {
371
                array_splice($decryptarray, $u, 1);
372
            }
373
        }
374
        //Each number is then decrypted using the RSA formula: block ^D mod N
375
        $deencrypt = '';
376
        for ($u=0, $max = count($decryptarray); $u < $max; $u++)
377
        {
378
            $resultmod = strval($this->powmod($decryptarray[$u], $d, $n));
379
            //remove leading and trailing '1' digits
380
            $deencrypt.= substr ($resultmod, 1, strlen($resultmod)-2);
381
        }
382
        //Each ASCII code number + 30 in the message is represented as its letter
383
        $resultd = '';
384
        for ($u=0; $u<strlen($deencrypt); $u+=2) {
385
            $resultd .= chr(substr ($deencrypt, $u, 2) + 30);
386
        }
387
        return $resultd;
388
    }
389
 
390
    /**
391
     *
392
     * @return int
393
     */
394
    public function getN()
395
    {
396
        return $this->n;
397
    }
398
 
399
 
400
    /**
401
     *
402
     * @return int
403
     */
404
    public function getE()
405
    {
406
        return $this->e;
407
    }
408
 
409
 
410
 
411
    /**
412
     *
413
     * @return int
414
     */
415
    public function getD()
416
    {
417
        return $this->d;
418
    }
419
 
420
}
421
 
422
?>