[ PHPXref.com ] [ Generated: Sun Jul 20 20:16:20 2008 ] [ ShareToDo 1.0.0 ]
[ Index ]     [ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/include/ -> Auth_TypeKey.php (source)

   1  <?php
   2  // Copyright (c) 2004 Daiji Hriata All Right Reserved.

   3  // $Id: Auth_TypeKey.phps,v 1.3 2004/10/10 14:59:49 hirata Exp $

   4  // 

   5  // Auth_TypeKey Class

   6  //

   7  // Simple example:

   8  //

   9  // $tk = new Auth_TypeKey();

  10  // $tk->site_token('PUTYOURTYPEKEYTOKEN');

  11  // $tk->verifyTypeKey( $msg );

  12  // if (PEAR::isError($result)) {

  13  //     echo "INVALID";

  14  // } else {

  15  //     echo "VALID";

  16  // }

  17  
  18  require_once 'PEAR.php';
  19  
  20  /**

  21  * Error code

  22  */
  23  define('AUTH_TYPEKEY_ERROR_INVALID', -1);
  24  define('AUTH_TYPEKEY_ERROR_TIMEOUT', -2);
  25  define('AUTH_TYPEKEY_ERROR_NOT_EXIST_BIGINT', -3);
  26  define('AUTH_TYPEKEY_ERROR_NOT_RETRIEVE_PUBKEY', -4);
  27  define('AUTH_TYPEKEY_ERROR_NOT_SET_SITE_TOKEN', -5);
  28  define('AUTH_TYPEKEY_ERROR_NOT_EXIST_GMP', -6);
  29  define('AUTH_TYPEKEY_ERROR_NOT_EXIST_BCMATH', -7);
  30  
  31  class Auth_TypeKey extends PEAR
  32  {
  33      /**

  34       * TypeKey Public_Key URLs

  35       */ 
  36      var $AUTH_TYPEKEY_BASEURL = 'https://www.typekey.com/t/typekey/';
  37      var $AUTH_TYPEKEY_SIG_URL = 'http://www.typekey.com/extras/regkeys.txt';
  38  
  39      /**

  40       * TypeKey version

  41       */
  42      var $AUTH_TYPEKEY_VERSION = '1';
  43  
  44      /**

  45       * TypeKey requires site_token

  46       */
  47      var $AUTH_TYPEKEY_SITE_TOKEN = NULL;
  48  
  49  
  50      /**

  51       * time limitatino of TypeKey validation (sec)

  52       */
  53      var $AUTH_TYPEKEY_TIMEOUT = 300;
  54  
  55      /**

  56       * function to compute BIGINT

  57       */
  58      var $AUTH_TYPEKEY_BIGINT = '';
  59  
  60      /**

  61       * Initialize.

  62       *

  63       * @param array $init        parameters for initialize: 

  64       *                          'version' : TypeKey version

  65       *                          'token' : TypeKey Site Token

  66       *

  67       * @return mixed  true on success. PEAR_Error on failure.

  68       * 

  69       * @access public

  70       */
  71      function Auth_TypeKey ( $init = array() )
  72      {
  73          $this->PEAR();
  74          if (!$this->_exist_bigint()) {
  75              return PEAR::raiseError("BCMATH or GMP is required", 
  76                                      AUTH_TYPEKEY_ERROR_NOT_EXIST_BIGINT);
  77          }
  78          if (array_key_exists('version', $init)) {
  79              $this->version($init['version']);
  80          }
  81          if (array_key_exists('token', $init)) {
  82              $this->site_token($init['token']);
  83          }
  84          return true;
  85      }
  86  
  87      /**

  88       * Set/show TypeKey version

  89       *

  90       * @param  string $version   TypeKey version to set.  

  91       *                           If nothing, just look.

  92       *

  93       * @return string            Current setting of TypeKey version

  94       * 

  95       * @access public

  96       */
  97      function version($version = NULL)
  98      {
  99          if (!is_null($version)) {
 100              $this->AUTH_TYPEKEY_VERSION = $version;
 101          }
 102          return $this->AUTH_TYPEKEY_VERSION;
 103      }
 104  
 105  
 106      /**

 107       * Set/show TypeKey Site Token

 108       *

 109       * @param  string $version        TypeKey Site Token to set.  

 110       *                                if nothing, just look.

 111       *

 112       * @return mixed  string          Current setting of TypeKey Site Token 

 113       *                                if set. PEAR_Error if not set.

 114       * 

 115       * @access public

 116       */
 117      function site_token($token = NULL) 
 118      {
 119          if (!is_null($token)) {
 120              $this->AUTH_TYPEKEY_SITE_TOKEN = $token;
 121          }
 122          if (is_null($this->AUTH_TYPEKEY_SITE_TOKEN)) {
 123              return PEAR::raiseError('SITE TOKEN is not set.',
 124                                       AUTH_TYPEKEY_ERROR_NOT_SET_SITE_TOKEN);
 125          }
 126          return $this->AUTH_TYPEKEY_SITE_TOKEN;
 127      }
 128  
 129      /**

 130       * Verify the TypeKey authentication requirement

 131       *

 132       * @param  array $query        TypeKey Site Token to set.  if nothing, just look.

 133       * @param  array $key          Public Keys of TypeKey service.  if NULL, using preset URLs.

 134       *

 135       * @return mixed  true on success.  PEAR_Error on failure.

 136       * 

 137       * @access public

 138       */
 139      function verifyTypeKey ( $query,  $key = NULL ) 
 140      {
 141          // Retrieve key per each request.

 142          if (is_null($key)) {
 143              $key = $this->_fetch_key('');
 144              if ($key == false) {
 145                  return PEAR::raiseError('Cannot get pubkey.',
 146                                          AUTH_TYPEKEY_ERROR_NOT_RETRIEVE_PUBKEY);
 147              }
 148          }
 149  
 150          foreach ( array( 'email', 'name', 'nick', 'ts', 'sig') as $i ) {
 151              $$i = $query[$i];
 152          }
 153          
 154          // The nickname field is sent as url_encoded utf-8 data(like %xx%xx... )

 155          // from Tyepkey but signed before encoded.  Usually all fields are

 156          // decoded by PHP automatically, but it might cause invalid_error,

 157          // especially using with mb_stirng.  rawurlencoded strings is

 158          // better for that case.  It can be gotten from QUERY_STRING

 159          $nick = rawurldecode($nick);
 160  
 161          switch ($this->version()) {
 162          case '1':
 163              $message = implode('::', array( $email, $name, $nick, $ts));
 164              break;
 165          case '1.1':
 166            $token = $this->site_token();
 167            if (PEAR::isError($token)) {
 168              return $token;
 169            }                
 170            $message = implode('::', array( $email, $name, $nick, $ts, $token));
 171                  break;
 172          default:
 173            // default is version '1'

 174            $message = implode('::', array( $email, $name, $nick, $ts));
 175            break;
 176          }
 177  
 178          if( $this->_dsa_verify($message, $sig, $key) == true) {
 179              if ( time() - $ts > $this->AUTH_TYPEKEY_TIMEOUT ) {
 180                  return PEAR::raiseError("Timestamp from TypeKey is too old", 
 181                                          AUTH_TYPEKEY_ERROR_TIMEOUT);
 182              }
 183              return true;
 184          } else {
 185              return PEAR::raiseError("Invalid signature", 
 186                                      AUTH_TYPEKEY_ERROR_INVALID);
 187          }
 188      }
 189  
 190      /* Generate URL to link to Sign-In using TypeKey service

 191       * 

 192       * @param  string  $return_url        URL to be returned after authentication

 193       * @param  boolean $need_email        if true, require email address of user.

 194       *

 195       * @return mixed   string  $url                URL to link TypeKey Sign-In

 196       *                 PEAR_Error on failure

 197       *

 198       * @access public

 199       */
 200  
 201      function urlSignIn ($return_url, $need_email = false, $options = array ())
 202      {
 203          $token = $this->site_token();
 204          if (PEAR::isError($token)) {
 205              return $token;
 206          }
 207  
 208          $option_query = '';
 209          foreach ($options as $key => $value) {
 210              $option_query .= '&' . $key . '=' . $value;
 211          }
 212  
 213          $url = $this->AUTH_TYPEKEY_BASEURL;
 214          $url .= "login?t=" . $token;
 215          $url .= (($need_email == 1) ? "&need_email=1" : '');
 216          $url .= (($this->version()) ? "&v=" . $this->version() : '');
 217          $url .= $option_query;
 218          $url .= "&_return=" . rawurlencode($return_url);
 219          return $url;
 220      }    
 221  
 222      /* Generate URL to link to sign out

 223       * 

 224       * @param  string  $return_url        URL to be returned after authentication

 225       *

 226       * @return string  $url                URL to link TypeKey sign out.

 227       *

 228       * @access public

 229       */
 230      function urlSignOut ( $return_url ) {
 231          $url = $this->AUTH_TYPEKEY_BASEURL;
 232          $url .= "logout?";
 233          $url .= "_return=" . rawurlencode($return_url);
 234          return $url;
 235      }    
 236  
 237      /* 

 238       * Fetch keys of TypeKey service

 239       * 

 240       * @param  string $url        URL of TypeKey Public Keys

 241       *

 242       * @return mixed  array of Public keys of TypeKey services

 243       *                false on error

 244       *

 245       * @access private

 246       */
 247      function _fetch_key ( $url = '')
 248      {
 249          if ($url == '') {
 250              $url = $this->AUTH_TYPEKEY_SIG_URL;
 251          }
 252          $lines = @file($url);
 253          if ($lines == false) {
 254              return false;
 255          }
 256          $key_raw = explode(" ", $lines[0]);
 257  
 258          foreach ($key_raw as $e) {
 259              list($key_index, $key_value) = explode("=", $e);
 260              $key[$key_index] = trim($key_value);
 261          }
 262          return $key;
 263      }
 264  
 265      /* 

 266       * check existing bigint function

 267       * 

 268       * @return boolean  true if available bigint funciton gmp or bcmath

 269       *                  false if not available.

 270       *

 271       * @access private

 272       *

 273       */
 274      function _exist_bigint () 
 275      {
 276          $extension_bigint = array( 'bcmath', 'gmp' );
 277          $exist_bigint = false;
 278          foreach ($extension_bigint as $ext) {
 279              if (extension_loaded($ext)) {
 280                  $exist_bigint = true;
 281                  $this->AUTH_TYPEKEY_BIGINT = $ext;
 282              }
 283          }
 284          return $exist_bigint;
 285      }
 286  
 287      /* 

 288       * dsa verification

 289       * 

 290       * @param  string $message Message to verify

 291       * @param  string @sig     Sign for the message, two keys are 

 292       *                         included separeted by ':' (colon)

 293       * @param  array  $key     ublic keys for the signiture

 294       *

 295       * @access private

 296       *

 297       */
 298      function _dsa_verify ( $message, $sig, $key )
 299      {
 300          $func = $this->AUTH_TYPEKEY_BIGINT;
 301          $func = '_dsa_verify_' . $func;
 302          return $this->$func( $message, $sig, $key );
 303      }
 304  
 305      /* 

 306       * dsa verification using gmp

 307       * 

 308       * @param  string $message Message to verify

 309       * @param  string @sig     Sign for the message, two keys are 

 310       *                         included separeted by ':' (colon)

 311       * @param  array  $key     ublic keys for the signiture

 312       *

 313       * @access private

 314       *

 315       */
 316      function _dsa_verify_gmp ( $message, $sig, $key )
 317      {
 318          list( $r_sig, $s_sig ) = explode(":", $sig );
 319          $r_sig = base64_decode($r_sig);
 320          $s_sig = base64_decode($s_sig);
 321  
 322          foreach ($key as $i => $v) {
 323              $key[$i] = gmp_init($v);
 324          }
 325          $s1 = gmp_init($this->_gmp_bindec($r_sig));
 326          $s2 = gmp_init($this->_gmp_bindec($s_sig));
 327  
 328          $w = gmp_invert($s2,$key['q']);
 329          $hash_m = gmp_init('0x' . sha1($message));
 330  
 331          $u1 = gmp_mod(gmp_mul($hash_m,$w),$key['q']);
 332          $u2 = gmp_mod(gmp_mul($s1,$w),$key['q']);
 333  
 334          $v = gmp_mod( 
 335                   gmp_mod( 
 336                       gmp_mul(
 337                           gmp_powm($key['g'],$u1,$key['p']), 
 338                           gmp_powm($key['pub_key'],$u2,$key['p'])),
 339                       $key['p']), 
 340                   $key['q']);
 341          if (gmp_cmp($v, $s1) == 0) {
 342              return true;
 343          } else {
 344              return false;
 345          }
 346      }
 347  
 348      /* 

 349       * gmp_bindec

 350       * 

 351       * @param  string $bin  binary data

 352       *

 353       * @return gmp    value of $bin

 354       *

 355       * @access private

 356       */
 357      function _gmp_bindec ($bin) 
 358      {
 359          $dec = gmp_init(0);
 360          while (strlen($bin)) {
 361              $i = ord(substr($bin, 0, 1));
 362                  $dec = gmp_add(gmp_mul($dec,256),$i);
 363                  $bin = substr($bin, 1);
 364              }
 365          return gmp_strval($dec);
 366      }
 367  
 368      /* 

 369       * dsa verification using bcmath

 370       * 

 371       * @param  string $message Message to verify

 372       * @param  string @sig     Sign for the message, two keys are 

 373       *                         included separeted by ':' (colon)

 374       * @param  array  $key     ublic keys for the signiture

 375       *

 376       * @access private

 377       *

 378       */
 379      function _dsa_verify_bcmath ( $message, $sig, $key )
 380      {
 381          list( $r_sig, $s_sig ) = explode(":", $sig );
 382  
 383          $r_sig = base64_decode($r_sig);
 384          $s_sig = base64_decode($s_sig);
 385  
 386          $s1 = $this->_bc_bindec($r_sig);
 387          $s2 = $this->_bc_bindec($s_sig);
 388  
 389          $w = $this->_bc_invert($s2,$key['q']);
 390          $hash_m = $this->_bc_hexdec(sha1($message));
 391  
 392          $u1 = bcmod(bcmul($hash_m,$w),$key['q']);
 393          $u2 = bcmod(bcmul($s1,$w),$key['q']);
 394  
 395          $v = bcmod( 
 396                   bcmod( 
 397                       bcmul(
 398                           bcmod($this->_bc_powmod($key['g'],$u1,$key['p']), $key['p']),
 399                           bcmod($this->_bc_powmod($key['pub_key'],$u2,$key['p']),$key['p'])),
 400                       $key['p']), 
 401                   $key['q']);
 402  
 403          if (bccomp($v, $s1) == 0) {
 404              return true;
 405          } else {
 406              return false;
 407          }
 408      }
 409  
 410      /* 

 411       * _bc_hexdec

 412       * 

 413       * @param  string $hex

 414       *

 415       * @return string dec converted from $hex

 416       *

 417       * @access private

 418       */
 419      function _bc_hexdec ($hex)
 420      {
 421          $dec = "0";
 422          while (strlen($hex)) {
 423              $i = HexDec(substr($hex, 0, 4));
 424              $dec = bcadd(bcmul($dec,65536),$i);
 425              $hex = substr($hex, 4);
 426          }
 427          return $dec;
 428      }
 429  
 430      /* 

 431       * _bc_bindec

 432       * 

 433       * @param  string $bin

 434       *

 435       * @return string dec converted from $bin

 436       *

 437       * @access private

 438       */
 439      function _bc_bindec ($bin)
 440      {
 441          $dec = "0";
 442          while (strlen($bin)) {
 443              $i = ord(substr($bin, 0, 1));
 444              $dec = bcadd(bcmul($dec,256),$i);
 445              $bin = substr($bin, 1);
 446          }
 447          return $dec;
 448      }
 449  
 450      /* 

 451       * _bc_invert

 452       * 

 453       * @param  string $x, $y

 454       *

 455       * @return string inverse $x and $y

 456       *

 457       * @access private

 458       */
 459      function _bc_invert ($x, $y) 
 460      {
 461          while (bccomp($x,0)<0) { 
 462              $x = bcadd($x,$y); 
 463          }
 464          $r = $this->_bc_exgcd($x, $y);
 465          if ($r[2] == 1) {
 466              $a = $r[0];
 467              while (bccomp($a,0)<0) {
 468                  $a = bcadd($a,$y);
 469              }
 470              return $a;
 471          } else {
 472              return false;
 473          }
 474      }
 475  
 476      /* 

 477       * _bc_exgcd

 478       * 

 479       * @param  string $x, $y

 480       *

 481       * @return string extended gcd of $x and $y

 482       *

 483       * @access private

 484       */
 485      function _bc_exgcd ($x, $y) 
 486      {
 487          $a0 = 1; $a1 = 0;
 488          $b0 = 0; $b1 = 1;
 489          $c = 0;
 490          while($y > 0) {
 491              $q = bcdiv($x, $y, 0);
 492              $r = bcmod($x, $y);
 493              $x = $y; $y = $r;
 494              $a2 = bcsub($a0, bcmul($q,$a1));
 495              $b2 = bcsub($b0, bcmul($q,$b1));
 496              $a0 = $a1; $a1 = $a2;
 497              $b0 = $b1; $b1 = $b2;
 498          }
 499          return (array($a0, $b0, $x));
 500      }
 501  
 502      /* 

 503       * _bc_powmod

 504       * 

 505       * @param  string $x, $y, $mod

 506       *

 507       * @return string bcmod(bcpow($x, $y), $mod)

 508       *

 509       * @access private

 510       */
 511      function _bc_powmod ($x, $y, $mod)
 512      {
 513          if (function_exists('bcpowmod')) {
 514              return bcpowmod($x, $y, $mod);
 515          } else {
 516              if (bccomp($y,1) == 0) {
 517                  return bcmod($x, $mod);
 518              } else if (bcmod($y,2) == 0) {
 519                  return bcmod(bcpow($this->_bc_powmod($x, bcdiv($y,2), $mod), 2), $mod);
 520              } else {
 521                  return bcmod(bcmul($x, $this->_bc_powmod($x, bcsub($y,1), $mod)), $mod);
 522              }
 523          }
 524      }
 525  }
 526  ?>


[ Powered by PHPXref - Served by Debian GNU/Linux ]