常用密码函数,加密,解密

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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<?php
/**
* 验证密码
*
* @param string $plain 密码 明文
* @param string $encrypted 密码 密文
*/
function validate_password($plain, $encrypted) {

$stack = explode(':', $encrypted);

if (count($stack) != 2) return false;

if (md5($stack[1] . $plain) == $stack[0]) {
return true;
}

return false;
}

/**
* 加密函数
*
* @param string $plain 密码明文
*/
function encrypt_password($plain) {
$password = '';

for ($i=0; $i<10; $i++) {
$password .= mt_rand();
}

$salt = substr(md5($password), 0, 2);

$password = md5($salt . $plain) . ':' . $salt;

return $password;
}

$res = encrypt_password('abc');
echo $res; //24746b3a7fe57e5e1ec190a096b36224:a3
var_dump(validate_password('abc', $res)); //true
echo '<br>';

/*
非常给力的authcode加密函数,Discuz!经典代码(带详解):
复制代码 代码如下:
*/
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
// 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙
$ckey_length = 4;

// 密匙
$key = md5($key ? $key : $GLOBALS['discuz_auth_key']);

// 密匙a会参与加解密
$keya = md5(substr($key, 0, 16));

// 密匙b会用来做数据完整性验证
$keyb = md5(substr($key, 16, 16));

// 密匙c用于变化生成的密文
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length)
:substr(md5(microtime()), -$ckey_length)) : '';

// 参与运算的密匙
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);

// 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b),
//解密时会通过这个密匙验证数据完整性
// 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length))
: sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
// 产生密匙簿
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
// 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
// 核心加解密部分
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
// 从密匙簿得出密匙进行异或,再转成字符
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
// 验证数据有效性,请看未加密明文的格式
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0)
&& substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
// 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因
// 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码
return $keyc.str_replace('=', '', base64_encode($result));
}
}
/*
函数authcode($string, $operation, $key,$expiry)中的$string:字符串,明文或密文;
$operation:DECODE表示解密,其它表示加密;$key:密匙;$expiry:密文有效期。

用法:
复制代码 代码如下:
*/
$str = 'abcdef';
$key = 'www.helloweba.com';
$res = authcode($str,'ENCODE',$key,0); //加密
echo $res . '<br>';

var_dump(authcode($res,'DECODE',$key,0)); //解密
echo '<br>';

/**
* 加解密函数encrypt()
* @param string $string password
* @param string $operation action E:加密 D:解密
* @param string $key
*
*/
function encrypt($string,$operation,$key=''){
$key=md5($key);
$key_length=strlen($key);

$string=$operation=='D'?base64_decode($string):substr(md5($string.$key),0,8).$string;
$string_length=strlen($string);
$rndkey=$box=array();
$result='';
for($i=0;$i<=255;$i++){
$rndkey[$i]=ord($key[$i%$key_length]);
$box[$i]=$i;
}
for($j=$i=0;$i<256;$i++){
$j=($j+$box[$i]+$rndkey[$i])%256;
$tmp=$box[$i];
$box[$i]=$box[$j];
$box[$j]=$tmp;
}
for($a=$j=$i=0;$i<$string_length;$i++){
$a=($a+1)%256;
$j=($j+$box[$a])%256;
$tmp=$box[$a];
$box[$a]=$box[$j];
$box[$j]=$tmp;
$result.=chr( ord($string[$i]) ^ ( $box[( $box[$a]+$box[$j] )%256] ) );
}
if($operation=='D'){
if(substr($result,0,8)==substr(md5(substr($result,8).$key),0,8)){
return substr($result,8);
}else{
return'';
}
}else{
return str_replace('=','',base64_encode($result));
}
}
/*
函数encrypt($string,$operation,$key)中$string:需要加密解密的字符串;
$operation:判断是加密还是解密,E表示加密,D表示解密;$key:密匙。
用法:
复制代码 代码如下:
*/
$str = 'abc';
$key = 'www.helloweba.com';
$token = encrypt($str, 'E', $key);
echo $token;
echo '<br>';
echo encrypt($token, 'D', $key);