00001 <?php
00002
00021 require_once 'Auth/OpenID/CryptUtil.php';
00022
00026 require_once 'Auth/OpenID.php';
00027
00033 class Auth_OpenID_MathLibrary {
00045 function longToBinary($long)
00046 {
00047 $cmp = $this->cmp($long, 0);
00048 if ($cmp < 0) {
00049 $msg = __FUNCTION__ . " takes only positive integers.";
00050 trigger_error($msg, E_USER_ERROR);
00051 return null;
00052 }
00053
00054 if ($cmp == 0) {
00055 return "\x00";
00056 }
00057
00058 $bytes = array();
00059
00060 while ($this->cmp($long, 0) > 0) {
00061 array_unshift($bytes, $this->mod($long, 256));
00062 $long = $this->div($long, pow(2, 8));
00063 }
00064
00065 if ($bytes && ($bytes[0] > 127)) {
00066 array_unshift($bytes, 0);
00067 }
00068
00069 $string = '';
00070 foreach ($bytes as $byte) {
00071 $string .= pack('C', $byte);
00072 }
00073
00074 return $string;
00075 }
00076
00086 function binaryToLong($str)
00087 {
00088 if ($str === null) {
00089 return null;
00090 }
00091
00092
00093
00094 $bytes = array_merge(unpack('C*', $str));
00095
00096 $n = $this->init(0);
00097
00098 if ($bytes && ($bytes[0] > 127)) {
00099 trigger_error("bytesToNum works only for positive integers.",
00100 E_USER_WARNING);
00101 return null;
00102 }
00103
00104 foreach ($bytes as $byte) {
00105 $n = $this->mul($n, pow(2, 8));
00106 $n = $this->add($n, $byte);
00107 }
00108
00109 return $n;
00110 }
00111
00112 function base64ToLong($str)
00113 {
00114 $b64 = base64_decode($str);
00115
00116 if ($b64 === false) {
00117 return false;
00118 }
00119
00120 return $this->binaryToLong($b64);
00121 }
00122
00123 function longToBase64($str)
00124 {
00125 return base64_encode($this->longToBinary($str));
00126 }
00127
00142 function rand($stop)
00143 {
00144 static $duplicate_cache = array();
00145
00146
00147 $rbytes = $this->longToBinary($stop);
00148
00149 if (array_key_exists($rbytes, $duplicate_cache)) {
00150 list($duplicate, $nbytes) = $duplicate_cache[$rbytes];
00151 } else {
00152 if ($rbytes[0] == "\x00") {
00153 $nbytes = Auth_OpenID::bytes($rbytes) - 1;
00154 } else {
00155 $nbytes = Auth_OpenID::bytes($rbytes);
00156 }
00157
00158 $mxrand = $this->pow(256, $nbytes);
00159
00160
00161
00162 $duplicate = $this->mod($mxrand, $stop);
00163
00164 if (count($duplicate_cache) > 10) {
00165 $duplicate_cache = array();
00166 }
00167
00168 $duplicate_cache[$rbytes] = array($duplicate, $nbytes);
00169 }
00170
00171 do {
00172 $bytes = "\x00" . Auth_OpenID_CryptUtil::getBytes($nbytes);
00173 $n = $this->binaryToLong($bytes);
00174
00175 } while ($this->cmp($n, $duplicate) < 0);
00176
00177 return $this->mod($n, $stop);
00178 }
00179 }
00180
00190 class Auth_OpenID_BcMathWrapper extends Auth_OpenID_MathLibrary{
00191 var $type = 'bcmath';
00192
00193 function add($x, $y)
00194 {
00195 return bcadd($x, $y);
00196 }
00197
00198 function sub($x, $y)
00199 {
00200 return bcsub($x, $y);
00201 }
00202
00203 function pow($base, $exponent)
00204 {
00205 return bcpow($base, $exponent);
00206 }
00207
00208 function cmp($x, $y)
00209 {
00210 return bccomp($x, $y);
00211 }
00212
00213 function init($number, $base = 10)
00214 {
00215 return $number;
00216 }
00217
00218 function mod($base, $modulus)
00219 {
00220 return bcmod($base, $modulus);
00221 }
00222
00223 function mul($x, $y)
00224 {
00225 return bcmul($x, $y);
00226 }
00227
00228 function div($x, $y)
00229 {
00230 return bcdiv($x, $y);
00231 }
00232
00238 function _powmod($base, $exponent, $modulus)
00239 {
00240 $square = $this->mod($base, $modulus);
00241 $result = 1;
00242 while($this->cmp($exponent, 0) > 0) {
00243 if ($this->mod($exponent, 2)) {
00244 $result = $this->mod($this->mul($result, $square), $modulus);
00245 }
00246 $square = $this->mod($this->mul($square, $square), $modulus);
00247 $exponent = $this->div($exponent, 2);
00248 }
00249 return $result;
00250 }
00251
00252 function powmod($base, $exponent, $modulus)
00253 {
00254 if (function_exists('bcpowmod')) {
00255 return bcpowmod($base, $exponent, $modulus);
00256 } else {
00257 return $this->_powmod($base, $exponent, $modulus);
00258 }
00259 }
00260
00261 function toString($num)
00262 {
00263 return $num;
00264 }
00265 }
00266
00276 class Auth_OpenID_GmpMathWrapper extends Auth_OpenID_MathLibrary{
00277 var $type = 'gmp';
00278
00279 function add($x, $y)
00280 {
00281 return gmp_add($x, $y);
00282 }
00283
00284 function sub($x, $y)
00285 {
00286 return gmp_sub($x, $y);
00287 }
00288
00289 function pow($base, $exponent)
00290 {
00291 return gmp_pow($base, $exponent);
00292 }
00293
00294 function cmp($x, $y)
00295 {
00296 return gmp_cmp($x, $y);
00297 }
00298
00299 function init($number, $base = 10)
00300 {
00301 return gmp_init($number, $base);
00302 }
00303
00304 function mod($base, $modulus)
00305 {
00306 return gmp_mod($base, $modulus);
00307 }
00308
00309 function mul($x, $y)
00310 {
00311 return gmp_mul($x, $y);
00312 }
00313
00314 function div($x, $y)
00315 {
00316 return gmp_div_q($x, $y);
00317 }
00318
00319 function powmod($base, $exponent, $modulus)
00320 {
00321 return gmp_powm($base, $exponent, $modulus);
00322 }
00323
00324 function toString($num)
00325 {
00326 return gmp_strval($num);
00327 }
00328 }
00329
00343 function Auth_OpenID_math_extensions()
00344 {
00345 $result = array();
00346
00347 if (!defined('Auth_OpenID_BUGGY_GMP')) {
00348 $result[] =
00349 array('modules' => array('gmp', 'php_gmp'),
00350 'extension' => 'gmp',
00351 'class' => 'Auth_OpenID_GmpMathWrapper');
00352 }
00353
00354 $result[] = array(
00355 'modules' => array('bcmath', 'php_bcmath'),
00356 'extension' => 'bcmath',
00357 'class' => 'Auth_OpenID_BcMathWrapper');
00358
00359 return $result;
00360 }
00361
00365 function Auth_OpenID_detectMathLibrary($exts)
00366 {
00367 $loaded = false;
00368
00369 foreach ($exts as $extension) {
00370
00371 if ($extension['extension'] &&
00372 extension_loaded($extension['extension'])) {
00373 $loaded = true;
00374 }
00375
00376
00377 if (!$loaded) {
00378 foreach ($extension['modules'] as $module) {
00379 if (@dl($module . "." . PHP_SHLIB_SUFFIX)) {
00380 $loaded = true;
00381 break;
00382 }
00383 }
00384 }
00385
00386
00387
00388
00389 if ($loaded) {
00390 return $extension;
00391 }
00392 }
00393
00394 return false;
00395 }
00396
00419 function &Auth_OpenID_getMathLib()
00420 {
00421
00422
00423
00424 static $lib = null;
00425
00426 if (isset($lib)) {
00427 return $lib;
00428 }
00429
00430 if (Auth_OpenID_noMathSupport()) {
00431 $null = null;
00432 return $null;
00433 }
00434
00435
00436
00437
00438 $ext = Auth_OpenID_detectMathLibrary(Auth_OpenID_math_extensions());
00439 if ($ext === false) {
00440 $tried = array();
00441 foreach (Auth_OpenID_math_extensions() as $extinfo) {
00442 $tried[] = $extinfo['extension'];
00443 }
00444 $triedstr = implode(", ", $tried);
00445
00446 Auth_OpenID_setNoMathSupport();
00447
00448 $result = null;
00449 return $result;
00450 }
00451
00452
00453 $class = $ext['class'];
00454 $lib = new $class();
00455
00456 return $lib;
00457 }
00458
00459 function Auth_OpenID_setNoMathSupport()
00460 {
00461 if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {
00462 define('Auth_OpenID_NO_MATH_SUPPORT', true);
00463 }
00464 }
00465
00466 function Auth_OpenID_noMathSupport()
00467 {
00468 return defined('Auth_OpenID_NO_MATH_SUPPORT');
00469 }
00470
00471 ?>