1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
17:
18: 19: 20:
21: require_once 'Auth/OpenID/CryptUtil.php';
22:
23: 24: 25:
26: require_once 'Auth/OpenID.php';
27:
28: 29: 30: 31: 32:
33: class Auth_OpenID_MathLibrary {
34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
45: function longToBinary($long)
46: {
47: $cmp = $this->cmp($long, 0);
48: if ($cmp < 0) {
49: $msg = __FUNCTION__ . " takes only positive integers.";
50: trigger_error($msg, E_USER_ERROR);
51: return null;
52: }
53:
54: if ($cmp == 0) {
55: return "\x00";
56: }
57:
58: $bytes = array();
59:
60: while ($this->cmp($long, 0) > 0) {
61: array_unshift($bytes, $this->mod($long, 256));
62: $long = $this->div($long, pow(2, 8));
63: }
64:
65: if ($bytes && ($bytes[0] > 127)) {
66: array_unshift($bytes, 0);
67: }
68:
69: $string = '';
70: foreach ($bytes as $byte) {
71: $string .= pack('C', $byte);
72: }
73:
74: return $string;
75: }
76:
77: 78: 79: 80: 81: 82: 83: 84: 85:
86: function binaryToLong($str)
87: {
88: if ($str === null) {
89: return null;
90: }
91:
92:
93:
94: $bytes = array_merge(unpack('C*', $str));
95:
96: $n = $this->init(0);
97:
98: if ($bytes && ($bytes[0] > 127)) {
99: trigger_error("bytesToNum works only for positive integers.",
100: E_USER_WARNING);
101: return null;
102: }
103:
104: foreach ($bytes as $byte) {
105: $n = $this->mul($n, pow(2, 8));
106: $n = $this->add($n, $byte);
107: }
108:
109: return $n;
110: }
111:
112: function base64ToLong($str)
113: {
114: $b64 = base64_decode($str);
115:
116: if ($b64 === false) {
117: return false;
118: }
119:
120: return $this->binaryToLong($b64);
121: }
122:
123: function longToBase64($str)
124: {
125: return base64_encode($this->longToBinary($str));
126: }
127:
128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141:
142: function rand($stop)
143: {
144: static $duplicate_cache = array();
145:
146:
147: $rbytes = $this->longToBinary($stop);
148:
149: if (array_key_exists($rbytes, $duplicate_cache)) {
150: list($duplicate, $nbytes) = $duplicate_cache[$rbytes];
151: } else {
152: if ($rbytes[0] == "\x00") {
153: $nbytes = Auth_OpenID::bytes($rbytes) - 1;
154: } else {
155: $nbytes = Auth_OpenID::bytes($rbytes);
156: }
157:
158: $mxrand = $this->pow(256, $nbytes);
159:
160:
161:
162: $duplicate = $this->mod($mxrand, $stop);
163:
164: if (count($duplicate_cache) > 10) {
165: $duplicate_cache = array();
166: }
167:
168: $duplicate_cache[$rbytes] = array($duplicate, $nbytes);
169: }
170:
171: do {
172: $bytes = "\x00" . Auth_OpenID_CryptUtil::getBytes($nbytes);
173: $n = $this->binaryToLong($bytes);
174:
175: } while ($this->cmp($n, $duplicate) < 0);
176:
177: return $this->mod($n, $stop);
178: }
179: }
180:
181: 182: 183: 184: 185: 186: 187: 188: 189:
190: class Auth_OpenID_BcMathWrapper extends Auth_OpenID_MathLibrary{
191: var $type = 'bcmath';
192:
193: function add($x, $y)
194: {
195: return bcadd($x, $y);
196: }
197:
198: function sub($x, $y)
199: {
200: return bcsub($x, $y);
201: }
202:
203: function pow($base, $exponent)
204: {
205: return bcpow($base, $exponent);
206: }
207:
208: function cmp($x, $y)
209: {
210: return bccomp($x, $y);
211: }
212:
213: function init($number, $base = 10)
214: {
215: return $number;
216: }
217:
218: function mod($base, $modulus)
219: {
220: return bcmod($base, $modulus);
221: }
222:
223: function mul($x, $y)
224: {
225: return bcmul($x, $y);
226: }
227:
228: function div($x, $y)
229: {
230: return bcdiv($x, $y);
231: }
232:
233: 234: 235: 236: 237:
238: function _powmod($base, $exponent, $modulus)
239: {
240: $square = $this->mod($base, $modulus);
241: $result = 1;
242: while($this->cmp($exponent, 0) > 0) {
243: if ($this->mod($exponent, 2)) {
244: $result = $this->mod($this->mul($result, $square), $modulus);
245: }
246: $square = $this->mod($this->mul($square, $square), $modulus);
247: $exponent = $this->div($exponent, 2);
248: }
249: return $result;
250: }
251:
252: function powmod($base, $exponent, $modulus)
253: {
254: if (function_exists('bcpowmod')) {
255: return bcpowmod($base, $exponent, $modulus);
256: } else {
257: return $this->_powmod($base, $exponent, $modulus);
258: }
259: }
260:
261: function toString($num)
262: {
263: return $num;
264: }
265: }
266:
267: 268: 269: 270: 271: 272: 273: 274: 275:
276: class Auth_OpenID_GmpMathWrapper extends Auth_OpenID_MathLibrary{
277: var $type = 'gmp';
278:
279: function add($x, $y)
280: {
281: return gmp_add($x, $y);
282: }
283:
284: function sub($x, $y)
285: {
286: return gmp_sub($x, $y);
287: }
288:
289: function pow($base, $exponent)
290: {
291: return gmp_pow($base, $exponent);
292: }
293:
294: function cmp($x, $y)
295: {
296: return gmp_cmp($x, $y);
297: }
298:
299: function init($number, $base = 10)
300: {
301: return gmp_init($number, $base);
302: }
303:
304: function mod($base, $modulus)
305: {
306: return gmp_mod($base, $modulus);
307: }
308:
309: function mul($x, $y)
310: {
311: return gmp_mul($x, $y);
312: }
313:
314: function div($x, $y)
315: {
316: return gmp_div_q($x, $y);
317: }
318:
319: function powmod($base, $exponent, $modulus)
320: {
321: return gmp_powm($base, $exponent, $modulus);
322: }
323:
324: function toString($num)
325: {
326: return gmp_strval($num);
327: }
328: }
329:
330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342:
343: function Auth_OpenID_math_extensions()
344: {
345: $result = array();
346:
347: if (!defined('Auth_OpenID_BUGGY_GMP')) {
348: $result[] =
349: array('modules' => array('gmp', 'php_gmp'),
350: 'extension' => 'gmp',
351: 'class' => 'Auth_OpenID_GmpMathWrapper');
352: }
353:
354: $result[] = array('modules' => array('bcmath', 'php_bcmath'),
355: 'extension' => 'bcmath',
356: 'class' => 'Auth_OpenID_BcMathWrapper');
357:
358: return $result;
359: }
360:
361: 362: 363:
364: function Auth_OpenID_detectMathLibrary($exts)
365: {
366: $loaded = false;
367:
368: foreach ($exts as $extension) {
369: if (extension_loaded($extension['extension'])) {
370: return $extension;
371: }
372: }
373:
374: return false;
375: }
376:
377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398:
399: function Auth_OpenID_getMathLib()
400: {
401:
402:
403:
404: static $lib = null;
405:
406: if (isset($lib)) {
407: return $lib;
408: }
409:
410: if (Auth_OpenID_noMathSupport()) {
411: $null = null;
412: return $null;
413: }
414:
415:
416:
417:
418: $ext = Auth_OpenID_detectMathLibrary(Auth_OpenID_math_extensions());
419: if ($ext === false) {
420: $tried = array();
421: foreach (Auth_OpenID_math_extensions() as $extinfo) {
422: $tried[] = $extinfo['extension'];
423: }
424: $triedstr = implode(", ", $tried);
425:
426: Auth_OpenID_setNoMathSupport();
427:
428: $result = null;
429: return $result;
430: }
431:
432:
433: $class = $ext['class'];
434: $lib = new $class();
435:
436: return $lib;
437: }
438:
439: function Auth_OpenID_setNoMathSupport()
440: {
441: if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {
442: define('Auth_OpenID_NO_MATH_SUPPORT', true);
443: }
444: }
445:
446: function Auth_OpenID_noMathSupport()
447: {
448: return defined('Auth_OpenID_NO_MATH_SUPPORT');
449: }
450:
451:
452: