Xxtea.class.php
4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Think\Crypt\Driver;
// Xxtea 加密实现类
class Xxtea
{
/**
* 加密字符串
*
* @param string $str
* 字符串
* @param string $key
* 加密key
* @param integer $expire
* 有效期(秒)
* @return string
*/
public static function encrypt($str, $key, $expire = 0)
{
$expire = sprintf('%010d', $expire ? $expire + time() : 0);
$str = $expire . $str;
$v = self::str2long($str, true);
$k = self::str2long($key, false);
$n = count($v) - 1;
$z = $v[$n];
$y = $v[0];
$delta = 0x9E3779B9;
$q = floor(6 + 52 / ($n + 1));
$sum = 0;
while (0 < $q --) {
$sum = self::int32($sum + $delta);
$e = $sum >> 2 & 3;
for ($p = 0; $p < $n; $p ++) {
$y = $v[$p + 1];
$mx = self::int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ self::int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$z = $v[$p] = self::int32($v[$p] + $mx);
}
$y = $v[0];
$mx = self::int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ self::int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$z = $v[$n] = self::int32($v[$n] + $mx);
}
return self::long2str($v, false);
}
/**
* 解密字符串
*
* @param string $str
* 字符串
* @param string $key
* 加密key
* @return string
*/
public static function decrypt($str, $key)
{
$v = self::str2long($str, false);
$k = self::str2long($key, false);
$n = count($v) - 1;
$z = $v[$n];
$y = $v[0];
$delta = 0x9E3779B9;
$q = floor(6 + 52 / ($n + 1));
$sum = self::int32($q * $delta);
while ($sum != 0) {
$e = $sum >> 2 & 3;
for ($p = $n; $p > 0; $p --) {
$z = $v[$p - 1];
$mx = self::int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ self::int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$y = $v[$p] = self::int32($v[$p] - $mx);
}
$z = $v[$n];
$mx = self::int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ self::int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$y = $v[0] = self::int32($v[0] - $mx);
$sum = self::int32($sum - $delta);
}
$data = self::long2str($v, true);
$expire = substr($data, 0, 10);
if ($expire > 0 && $expire < time()) {
return '';
}
$data = substr($data, 10);
return $data;
}
private static function long2str($v, $w)
{
$len = count($v);
$s = array();
for ($i = 0; $i < $len; $i ++) {
$s[$i] = pack("V", $v[$i]);
}
if ($w) {
return substr(join('', $s), 0, $v[$len - 1]);
} else {
return join('', $s);
}
}
private static function str2long($s, $w)
{
$v = unpack("V*", $s . str_repeat("\0", (4 - strlen($s) % 4) & 3));
$v = array_values($v);
if ($w) {
$v[count($v)] = strlen($s);
}
return $v;
}
private static function int32($n)
{
while ($n >= 2147483648) {
$n -= 4294967296;
}
while ($n <= - 2147483649) {
$n += 4294967296;
}
return (int) $n;
}
}