BigMath.php

Go to the documentation of this file.
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         // Use array_merge to return a zero-indexed array instead of a
00093         // one-indexed array.
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         // Used as the key for the duplicate cache
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             // If we get a number less than this, then it is in the
00161             // duplicated range.
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             // Keep looping if this value is in the low duplicated range
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         // See if the extension specified is already loaded.
00371         if ($extension['extension'] &&
00372             extension_loaded($extension['extension'])) {
00373             $loaded = true;
00374         }
00375 
00376         // Try to load dynamic modules.
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         // If the load succeeded, supply an instance of
00387         // Auth_OpenID_MathWrapper which wraps the specified
00388         // module's functionality.
00389         if ($loaded) {
00390             return $extension;
00391         }
00392     }
00393 
00394     return false;
00395 }
00396 
00419 function &Auth_OpenID_getMathLib()
00420 {
00421     // The instance of Auth_OpenID_MathWrapper that we choose to
00422     // supply will be stored here, so that subseqent calls to this
00423     // method will return a reference to the same object.
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     // If this method has not been called before, look at
00436     // Auth_OpenID_math_extensions and try to find an extension that
00437     // works.
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     // Instantiate a new wrapper
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 ?>

Generated on Thu Feb 19 15:02:21 2009 for OXID eShop CE by  doxygen 1.5.5