Authored by 梁志锋

Merge branch 'develop' of http://git.dev.yoho.cn/web/yohobuy into develop

  1 +<?php
  2 +namespace Plugin;
  3 +/**
  4 + * Enter description here...
  5 + *
  6 + * example:
  7 + * <pre>
  8 + *
  9 + * </pre>
  10 + *
  11 + * @name Q_Utils_AuthCode
  12 + * @version version (2009-10-22 上午10:45:12)
  13 + * @package Q.Utils.AuthCode
  14 + * @author ziyang liuziyang@360quan.com
  15 + * @since 1.0
  16 + */
  17 +
  18 +class AuthCode
  19 +{
  20 +
  21 + /**
  22 + * 验证编码
  23 + *
  24 + * @param String $string
  25 + * @param String $operation
  26 + * @param Integer $expiry
  27 + * @param String $key
  28 + * @return String
  29 + */
  30 + private static function auth($string, $key, $expiry = 0, $operation = 'decode')
  31 + {
  32 + $ckey_length = 4;
  33 + $key = md5($key);
  34 + $keya = md5(substr($key, 0, 16));
  35 + $keyb = md5(substr($key, 16, 16));
  36 + $keyc = $ckey_length ? ($operation == 'decode' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
  37 + $cryptkey = $keya . md5($keya . $keyc);
  38 + $key_length = strlen($cryptkey);
  39 + $string = $operation == 'decode' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
  40 + $string_length = strlen($string);
  41 +
  42 + $result = '';
  43 + $box = range(0, 255);
  44 +
  45 + $rndkey = array();
  46 + for ($i = 0; $i <= 255; $i++)
  47 + {
  48 + $rndkey[$i] = ord($cryptkey[$i % $key_length]);
  49 + }
  50 +
  51 + for ($j = $i = 0; $i < 256; $i++)
  52 + {
  53 + $j = ($j + $box[$i] + $rndkey[$i]) % 256;
  54 + $tmp = $box[$i];
  55 + $box[$i] = $box[$j];
  56 + $box[$j] = $tmp;
  57 + }
  58 +
  59 + for ($a = $j = $i = 0; $i < $string_length; $i++)
  60 + {
  61 + $a = ($a + 1) % 256;
  62 + $j = ($j + $box[$a]) % 256;
  63 + $tmp = $box[$a];
  64 + $box[$a] = $box[$j];
  65 + $box[$j] = $tmp;
  66 + $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
  67 + }
  68 +
  69 + if ($operation == 'decode')
  70 + {
  71 + if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16))
  72 + {
  73 + return substr($result, 26);
  74 + }
  75 + else
  76 + {
  77 + return false;
  78 + }
  79 + }
  80 + else
  81 + {
  82 + return $keyc . str_replace('=', '', base64_encode($result));
  83 + }
  84 + }
  85 + /**
  86 + * 解密
  87 + *
  88 + * @param String $string
  89 + * @param String $key
  90 + * @param Integer $expiry
  91 + * @return String
  92 + */
  93 + public static function decode($string, $key, $expiry = 0)
  94 + {
  95 + return self::auth($string, $key, $expiry, __FUNCTION__);
  96 + }
  97 +
  98 + /**
  99 + * 加密
  100 + *
  101 + * @param String $string
  102 + * @param String $key
  103 + * @param Integer $expiry
  104 + * @return String
  105 + */
  106 + public static function encode($string, $key, $expiry = 0)
  107 + {
  108 + return self::auth($string, $key, $expiry, __FUNCTION__);
  109 + }
  110 +
  111 + /**
  112 + * 获取编码
  113 + *
  114 + * @param String $plaintext
  115 + * @param String $salt
  116 + * @param String $encryption
  117 + * @param bool $show_encrypt
  118 + * @return String
  119 + */
  120 + public static function getCrypted($plaintext, $salt = '', $encryption = 'md5-hex', $show_encrypt = false)
  121 + {
  122 + $salt = self::getSalt($encryption, $salt, $plaintext);
  123 + switch ($encryption)
  124 + {
  125 + case 'plain' :
  126 + return $plaintext;
  127 + case 'sha' :
  128 + $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext));
  129 + return ($show_encrypt) ? '{SHA}' . $encrypted : $encrypted;
  130 + case 'crypt' :
  131 + case 'crypt-des' :
  132 + case 'crypt-md5' :
  133 + case 'crypt-blowfish' :
  134 + return ($show_encrypt ? '{crypt}' : '') . crypt($plaintext, $salt);
  135 + case 'md5-base64' :
  136 + $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext));
  137 + return ($show_encrypt) ? '{MD5}' . $encrypted : $encrypted;
  138 + case 'ssha' :
  139 + $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext . $salt) . $salt);
  140 + return ($show_encrypt) ? '{SSHA}' . $encrypted : $encrypted;
  141 + case 'smd5' :
  142 + $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext . $salt) . $salt);
  143 + return ($show_encrypt) ? '{SMD5}' . $encrypted : $encrypted;
  144 + case 'aprmd5' :
  145 + $length = strlen($plaintext);
  146 + $context = $plaintext . '$apr1$' . $salt;
  147 + $binary = self::_bin(md5($plaintext . $salt . $plaintext));
  148 + for ($i = $length; $i > 0; $i -= 16)
  149 + {
  150 + $context .= substr($binary, 0, ($i > 16 ? 16 : $i));
  151 + }
  152 + for ($i = $length; $i > 0; $i >>= 1)
  153 + {
  154 + $context .= ($i & 1) ? chr(0) : $plaintext[0];
  155 + }
  156 + $binary = self::_bin(md5($context));
  157 +
  158 + for ($i = 0; $i < 1000; $i++)
  159 + {
  160 + $new = ($i & 1) ? $plaintext : substr($binary, 0, 16);
  161 + if ($i % 3)
  162 + {
  163 + $new .= $salt;
  164 + }
  165 + if ($i % 7)
  166 + {
  167 + $new .= $plaintext;
  168 + }
  169 + $new .= ($i & 1) ? substr($binary, 0, 16) : $plaintext;
  170 + $binary = self::_bin(md5($new));
  171 + }
  172 +
  173 + $p = array();
  174 + for ($i = 0; $i < 5; $i++)
  175 + {
  176 + $k = $i + 6;
  177 + $j = $i + 12;
  178 + if ($j == 16)
  179 + {
  180 + $j = 5;
  181 + }
  182 + $p[] = self::_toAPRMD5((ord($binary[$i]) << 16) | (ord($binary[$k]) << 8) | (ord($binary[$j])), 5);
  183 + }
  184 +
  185 + return '$apr1$' . $salt . '$' . implode('', $p) . self::_toAPRMD5(ord($binary[11]), 3);
  186 +
  187 + case 'md5-hex' :
  188 +
  189 + default :
  190 + $encrypted = ($salt) ? md5($plaintext . $salt) : md5($plaintext);
  191 + return ($show_encrypt) ? '{MD5}' . $encrypted : $encrypted;
  192 + }
  193 + }
  194 +
  195 + /**
  196 + * Enter description here...
  197 + *
  198 + * @param unknown_type $encryption
  199 + * @param unknown_type $seed
  200 + * @param unknown_type $plaintext
  201 + * @return unknown
  202 + */
  203 + public static function getSalt($encryption = 'md5-hex', $seed = '', $plaintext = '')
  204 + {
  205 + switch ($encryption)
  206 + {
  207 + case 'crypt' :
  208 + case 'crypt-des' :
  209 + if ($seed)
  210 + {
  211 + return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 2);
  212 + }
  213 + else
  214 + {
  215 + return substr(md5(mt_rand()), 0, 2);
  216 + }
  217 + break;
  218 +
  219 + case 'crypt-md5' :
  220 + if ($seed)
  221 + {
  222 + return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 12);
  223 + }
  224 + else
  225 + {
  226 + return '$1$' . substr(md5(mt_rand()), 0, 8) . '$';
  227 + }
  228 + break;
  229 +
  230 + case 'crypt-blowfish' :
  231 + if ($seed)
  232 + {
  233 + return substr(preg_replace('|^{crypt}|i', '', $seed), 0, 16);
  234 + }
  235 + else
  236 + {
  237 + return '$2$' . substr(md5(mt_rand()), 0, 12) . '$';
  238 + }
  239 + break;
  240 +
  241 + case 'ssha' :
  242 + if ($seed)
  243 + {
  244 + return substr(preg_replace('|^{SSHA}|', '', $seed), -20);
  245 + }
  246 + else
  247 + {
  248 + return mhash_keygen_s2k(MHASH_SHA1, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  249 + }
  250 + break;
  251 +
  252 + case 'smd5' :
  253 + if ($seed)
  254 + {
  255 + return substr(preg_replace('|^{SMD5}|', '', $seed), -16);
  256 + }
  257 + else
  258 + {
  259 + return mhash_keygen_s2k(MHASH_MD5, $plaintext, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
  260 + }
  261 + break;
  262 +
  263 + case 'aprmd5' :
  264 + /* 64 characters that are valid for APRMD5 passwords. */
  265 + $APRMD5 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  266 +
  267 + if ($seed)
  268 + {
  269 + return substr(preg_replace('/^\$apr1\$(.{8}).*/', '\\1', $seed), 0, 8);
  270 + }
  271 + else
  272 + {
  273 + $salt = '';
  274 + for ($i = 0; $i < 8; $i++)
  275 + {
  276 + $salt .= $APRMD5{rand(0, 63)};
  277 + }
  278 + return $salt;
  279 + }
  280 + break;
  281 +
  282 + default :
  283 + $salt = '';
  284 + if ($seed)
  285 + {
  286 + $salt = $seed;
  287 + }
  288 + return $salt;
  289 + break;
  290 + }
  291 + }
  292 +
  293 + public static function genRandom($length = 8)
  294 + {
  295 + $salt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  296 + $len = strlen($salt);
  297 + $makepass = '';
  298 +
  299 + $stat = @stat(__FILE__);
  300 + if (empty($stat) || !is_array($stat))
  301 + $stat = array(
  302 + php_uname()
  303 + );
  304 +
  305 + mt_srand(crc32(microtime() . implode('|', $stat)));
  306 +
  307 + for ($i = 0; $i < $length; $i++)
  308 + {
  309 + $makepass .= $salt[mt_rand(0, $len - 1)];
  310 + }
  311 +
  312 + return $makepass;
  313 + }
  314 +
  315 + public static function _toAPRMD5($value, $count)
  316 + {
  317 + /* 64 characters that are valid for APRMD5 passwords. */
  318 + $APRMD5 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  319 + $aprmd5 = '';
  320 + $count = abs($count);
  321 + while (--$count)
  322 + {
  323 + $aprmd5 .= $APRMD5[$value & 0x3f];
  324 + $value >>= 6;
  325 + }
  326 + return $aprmd5;
  327 + }
  328 +
  329 + public static function _bin($hex)
  330 + {
  331 + $bin = '';
  332 + $length = strlen($hex);
  333 + for ($i = 0; $i < $length; $i += 2)
  334 + {
  335 + $tmp = sscanf(substr($hex, $i, 2), '%x');
  336 + $bin .= chr(array_shift($tmp));
  337 + }
  338 + return $bin;
  339 + }
  340 +
  341 + /**
  342 + * 组合一个安全的密码
  343 + * @param $code
  344 + * @return String
  345 + */
  346 + public static function makePass($code)
  347 + {
  348 + $salt = self::genRandom(32);
  349 + $crypt = self::getCrypted($code . $salt, $salt);
  350 + return $crypt . ':' . $salt;
  351 + }
  352 +
  353 + /**
  354 + * 验证密码
  355 + *
  356 + * @param String $inputPassword
  357 + * @param String $password
  358 + * @return bool
  359 + */
  360 + public static function authPassword($inputPassword, $password)
  361 + {
  362 + if (empty($password) || empty($inputPassword))
  363 + {
  364 + return false;
  365 + }
  366 + $passwordList = explode(':', trim($password));
  367 + if (count($passwordList) != 2)
  368 + {
  369 + return false;
  370 + }
  371 + list($crypt, $salt) = $passwordList;
  372 + $decode = self::getCrypted($inputPassword . $salt, $salt);
  373 + if ($crypt != $decode)
  374 + {
  375 + return false;
  376 + }
  377 + return true;
  378 + }
  379 +}
@@ -85,5 +85,4 @@ @@ -85,5 +85,4 @@
85 {{/ newArrivls}} 85 {{/ newArrivls}}
86 {{/ boys}} 86 {{/ boys}}
87 </div> 87 </div>
88 -{{> layout/page-footer}}  
89 {{> layout/footer}} 88 {{> layout/footer}}
@@ -72,5 +72,4 @@ @@ -72,5 +72,4 @@
72 72
73 {{/ girls}} 73 {{/ girls}}
74 </div> 74 </div>
75 -{{> layout/page-footer}}  
76 {{> layout/footer}} 75 {{> layout/footer}}
@@ -85,5 +85,4 @@ @@ -85,5 +85,4 @@
85 {{/ newArrivls}} 85 {{/ newArrivls}}
86 {{/ boys}} 86 {{/ boys}}
87 </div> 87 </div>
88 -{{> layout/page-footer}}  
89 {{> layout/footer}} 88 {{> layout/footer}}
@@ -33,5 +33,4 @@ @@ -33,5 +33,4 @@
33 {{/ newArrivls}} 33 {{/ newArrivls}}
34 {{/ kids}} 34 {{/ kids}}
35 </div> 35 </div>
36 -{{> layout/page-footer}}  
37 {{> layout/footer}} 36 {{> layout/footer}}
@@ -32,5 +32,4 @@ @@ -32,5 +32,4 @@
32 {{/ newArrivls}} 32 {{/ newArrivls}}
33 {{/ lifestyle}} 33 {{/ lifestyle}}
34 </div> 34 </div>
35 -{{> layout/page-footer}}  
36 {{> layout/footer}} 35 {{> layout/footer}}