正在加载中···
BEAR's BLOG

QQ空间加密算法–PHP直译实现

发布时间:2018-11-23 15:33
Encryption类代码:
<?PHP
class Encryption
{
public static $f = "";
public static $m = 0;
public static $_a = array();
public static $_b = array();
public static $v = 0;
public static $w = 0;
public static $y = array();
public static $k = array();
public static $b = !0;

public static $q_arr = array();

function __construct()
{
self::$q_arr['PADCHAR'] = '=';
self::$q_arr['ALPHA'] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
}
/**
* PHP实现JS脚本方法 Start >>>
*/
private function random($min = 0, $max = 1)
{
return $min + mt_rand()/mt_getrandmax()*($max-$min);
}

private function JsNumber($s)
{
if($s == '0') return 0;
$num = intval($s);
if(strlen($num) != strlen($s) || $num == 0)
{
$num = 'NaN';
}
return $num;
}

private function charCodeAt($s,$n){
$str = substr($s, $n, 1);
if (strlen($str) == 1)
return ord($str);
$str = mb_convert_encoding($str, 'UCS-4BE', 'utf-8');
$tmp = unpack('N', $str);
return $tmp[1];
}

private function uin2hex($str) {
$maxLength = 16;
$str = intval($str);
for ($hex = dechex($str), $len = strlen($hex), $i = $len; $maxLength > $i; $i++)
$hex = "0" . $hex;
for ($arr = array(), $j = 0; $maxLength > $j; $j += 2)
array_push($arr,"\\x" . substr($hex,$j, 2));
$result = join("",$arr);
eval('$result="' . $result . '";');
return $result;
}

private function shr32($x, $bits){
if($bits <= 0){
return $x;
}
if($bits >= 32){
return 0;
}
$bin = decbin($x);
$l = strlen($bin);
if($l > 32){
$bin = substr($bin, $l - 32, 32);
}elseif($l < 32){
$bin = str_pad($bin, 32, '0', STR_PAD_LEFT);
}
return bindec(str_pad(substr($bin, 0, 32 - $bits), 32, '0', STR_PAD_LEFT));
}
/**
* PHP实现JS脚本方法 End <<<
*/
private function e() {
return 1;
//return round(4294967295 * $this->random());
}

private function i($t, $e, $i) {
(!$i || $i > 4) && ($i = 4);
for ($n = 0, $o = $e; $e + $i > $o; $o++){
$n <<= 8;
$n |= $t[$o];
}
return (4294967295 & $n) >> 0;
}

private function n($t, $e, $i) {
$t[$e + 3] = $i >> 0 & 255;
$t[$e + 2] = $i >> 8 & 255;
$t[$e + 1] = $i >> 16 & 255;
$t[$e + 0] = $i >> 24 & 255;
return $t;
}

private function o($t) {
if (!$t) return "";
for ($e = "", $i = 0; $i < count($t); $i++) {
$n = dechex($this -> JsNumber($t[$i]));
if (1 == strlen($n)) $n = "0" . $n;
$e .= $n;
}
return $e;
}

private function p($t) {
/**for ($e = "", $i = 0; $i < strlen($t); $i += 2)
$e .= chr(parseInt(t.substr(i, 2), 16));
return e*/
}

private function r($t, $e = false) {
if (!$t) return "";
$e && ($t = $this -> s($t));
for ($i = array(), $n = 0; $n < strlen($t); $n++)
$i[$n] = $this -> charCodeAt($t,$n);
return $this -> o($i);
}

private function s($t) {
$e = array();
$i = array();
$n = array();
$o = strlen($t);
for ($e = 0; $o > $e; $e++)
{
$i = $this -> charCodeAt($t,$e);
if($i > 0 && 127 >= $i)
{
array_push($n,$t[$e]);
}else if($i >= 128 && 2047 >= $i){
array_push($n,chr(192 | $i >> 6 & 31), chr(128 | 63 & $i));
}else if($i >= 2048 && 65535 >= $i){
array_push($n, chr(224 | $i >> 12 & 15), chr(128 | $i >> 6 & 63), chr(128 | 63 & $i));
}
}
return join("",$n);
}

private function l($t) {
self::$_a = array();
self::$_b = array();
self::$v = $w = 0;
self::$b = !0;
self::$m = 0;
$i = count($t);
$n = 0;
self::$m = ($i + 10) % 8;
0 != self::$m && (self::$m = 8 - self::$m);
self::$y = array();
self::$_a[0] = 255 & (248 & $this -> e() | self::$m);
for ($o = 1; self::$m >= $o; $o++)
self::$_a[$o] = 255 & $this -> e();
self::$m++;
for ($o = 0; 8 > $o; $o++)
self::$_b[$o] = 0;
for ($n = 1; 2 >= $n;)
{
if(8 > self::$m)
{
self::$_a[self::$m++] = 255 & $this -> e();
$n++;
}
if(8 == self::$m)
{
$this -> c();
}
}
for ($o = 0; $i > 0;)
{
if(8 > self::$m)
{
self::$_a[self::$m++] = $t[$o++];
$i--;
}
if(8 == self::$m)
{
$this -> c();
}
}
for ($n = 1; 7 >= $n;)
{
if(8 > self::$m)
{
self::$_a[self::$m++] = 0;
$n++;
}
if(8 == self::$m)
{
$this -> c();
}
}
return self::$y;
}

private function a($t) {
}

private function c() {
for ($t = 0; 8 > $t; $t++){
self::$_a[$t] ^= self::$b ? self::$_b[$t] : self::$y[self::$w + $t];
}
for ($e = $this -> u(self::$_a), $t = 0; 8 > $t; $t++){
self::$y[self::$v + $t] = $e[$t] ^ self::$_b[$t];
self::$_b[$t] = self::$_a[$t];
}
self::$w = self::$v;
self::$v += 8;
self::$m = 0;
self::$b = !1;
}

private function u($t) {
for ($e = 16, $o = $this -> i($t, 0, 4), $p = $this -> i($t, 4, 4), $r = $this -> i(self::$f, 0, 4), $s = $this -> i(self::$f, 4, 4), $l = $this -> i(self::$f, 8, 4), $a = $this -> i(self::$f, 12, 4), $c = 0, $u = 2654435769; $e-- > 0;)
{
$c += $u;
$c = $this -> shr32((4294967295 & $c),0);
$o += ($p << 4) + $r ^ $p + $c ^ ($this -> shr32($p, 5)) + $s;
$o = $this -> shr32((4294967295 & $o), 0);
$p += ($o << 4) + $l ^ $o + $c ^ ($this -> shr32($o,5)) + $a;
$p = $this -> shr32((4294967295 & $p),0);
}
$g = array();
$g = $this -> n($g, 0, $o);
$g = $this -> n($g, 4, $p);
return $g;
}

private function g($t) {
}

private function d($t) {
}

private function h($t, $e = false) {
$i = array();
if ($e)
{
for ($n = 0; $n < strlen($t); $n++)
$i[$n] = 255 & $this -> charCodeAt($t,$n);
}else{
for ($o = 0, $n = 0; $n < strlen($t); $n += 2)
$i[$o++] = intval(substr($t, $n, 2), 16);
}
return $i;
}

/**
* TEA方法
*/

private function t($s) {
return strtoupper(md5($s));
}
private function strToBytes($t,$e = false) {
return $this -> r($t,$e);
}
private function TeaInitkey($t, $e = false) {
self::$f = $this -> h($t, $e);
return self::$f;
}

private function TeaEncrypt($t, $e = false) {
$i = $this -> h($t, $e);
$n = $this -> l($i);
return $this -> o($n);
}


private function Eng($t) {
for ($e = '', $i = 0; $i < (strlen($t)); $i += 2){
$e = $e . chr(intval(substr($t, $i, 2), 16));
}
return $e;
}

private function Qgetbyte($t, $e)
{
$i = $this -> charCodeAt($t,$e);
if ($i > 255) return "INVALID_CHARACTER_ERR: DOM Exception 5";
return $i;
}

private function encode($t) {
$e;
$i;
$n = self::$q_arr['PADCHAR'];
$o = self::$q_arr['ALPHA'];
//var p = q.getbyte; ///Qgetbyte
$r = array();
$t = "" . $t;
$s = strlen($t) - strlen($t) % 3;
if (0 == strlen($t)) return $t;
for ($e = 0; $s > $e; $e += 3)
{
$i = $this -> Qgetbyte($t, $e) << 16 | $this -> Qgetbyte($t, $e + 1) << 8 | $this -> Qgetbyte($t, $e + 2);
array_push($r,$o[$i >> 18]);
array_push($r,$o[$i >> 12 & 63]);
array_push($r,$o[$i >> 6 & 63]);
array_push($r,$o[63 & $i]);
}
switch (strlen($t) - $s) {
case 1:
$i = $this -> Qgetbyte($t, $e) << 16;
array_push($r,$o[$i >> 18] . $o[$i >> 12 & 63] . $n . $n);
break;
case 2:
$i = $this -> Qgetbyte($t, $e) << 16 | $this -> Qgetbyte($t, $e + 1) << 8;
array_push($r,$o[$i >> 18] . $o[$i >> 12 & 63] . $o[$i >> 6 & 63] . $n);
}
return join("",$r);
}

function Enh($e = "", $i, $n="", $o) {
$i = $this -> uin2hex($i);
$p = $o ? $e : $this -> t($e);
$r = $this -> Eng($p);
$s = $this -> t($r . $i);
$l = $this -> strToBytes(strtoupper($n), !0);
$a = dechex($this -> JsNumber(strlen($l) / 2));
while(strlen($a) < 4)
$a = "0" . $a;
$TestF = $this -> TeaInitkey($s);
$c = $this -> TeaEncrypt($p . $this -> strToBytes($i) . $a . $l);
$TestF = $this -> TeaInitkey("");
$u = dechex($this -> JsNumber(strlen($c) / 2));
while (strlen($u) < 4)
$u = "0" . $u;
$aa = new RSA();
$h = $aa -> rsa_encrypt($this -> Eng($u . $c));
$returnd = $this -> encode($this -> Eng($h));
$returnd = str_replace('/', '-', $returnd);
$returnd = str_replace('+', '*', $returnd);
$returnd = str_replace('=', '_', $returnd);
return $returnd;
}

function test() {
return $this -> e();
}
}

$p = '123456';//密码
$u = '10001';//QQ号
$verifycode = 'abds';//验证码
$a = new Encryption();
$p = $a -> Enh($p,$u,$verifycode, Null);