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 |
?>
|