21,886
社区成员
发帖
与我相关
我的任务
分享
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]));
}
function authcode(str, operation, key, expiry) {
var operation = operation ? operation : 'DECODE';
var key = key ? key : '';
var expiry = expiry ? expiry : 0;
var ckey_length = 4;
key = md5(key);
// 密匙a会参与加解密
var keya = md5(key.substr(0, 16));
// 密匙b会用来做数据完整性验证
var keyb = md5(key.substr(16, 16));
// 密匙c用于变化生成的密文
var keyc = ckey_length ? (operation == 'DECODE' ? str.substr(0, ckey_length): md5(microtime()).substr(-ckey_length)) : '';
// 参与运算的密匙
var cryptkey = keya+md5(keya+keyc);
var strbuf;
if(operation == 'DECODE') {
str = str.substr(ckey_length);
strbuf = Base64.decode(str);
//string = b.toString();
}
else {
expiry = expiry ? expiry + time() : 0;
tmpstr = expiry.toString();
if(tmpstr.length>=10)
str = tmpstr.substr(0,10)+md5(str+keyb).substr(0, 16)+str;
else {
var count = 10 - tmpstr.length;
for(var i=0;i<count;i++) {
tmpstr = '0'+tmpstr;
}
str = tmpstr+md5(str+keyb).substr(0, 16)+str;
}
strbuf = str;
}
var box = new Array(256);
for(var i=0; i < 256; i++) {
box[i] = i;
}
var rndkey = new Array();
// 产生密匙簿
for(var i=0; i < 256; i++) {
rndkey[i] = cryptkey.charCodeAt(i % cryptkey.length);
}
// 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度
for(var j = i = 0; i < 256; i++) {
j = (j + box[i] + rndkey[i]) % 256;
tmp = box[i];
box[i] = box[j];
box[j] = tmp;
}
// 核心加解密部分
var s = '';
for(var a = j = i = 0; i < strbuf.length; i++) {
a = (a + 1) % 256;
j = (j + box[a]) % 256;
tmp = box[a];
box[a] = box[j];
box[j] = tmp;
// 从密匙簿得出密匙进行异或,再转成字符
//s += String.fromCharCode(string[i] ^ (box[(box[a] + box[j]) % 256]));
strbuf[i] =chr(ord(strbuf[i]) ^ (box[(box[a] + box[j]) % 256]))
}
if(operation == 'DECODE') {
var s = strbuf.toString();
if((s.substr(0, 10) == 0 || s.substr( 0, 10) - time() > 0) && s.substr(10, 16) == md5(s.substr(26)+keyb).substr(0, 16)) {
s = s.substr(26);
} else {
s = '';
}
}
else {
var s = Base64.encode(strbuf.toString());
var regex = new RegExp('=', "g");
s = s.replace(regex, '');
s = keyc+s;
}
return s;
}
function time() {
var unixtime_ms = new Date().getTime();
return parseInt(unixtime_ms / 1000);
}
function microtime(get_as_float) {
var unixtime_ms = new Date().getTime();
var sec = parseInt(unixtime_ms / 1000);
return get_as_float ? (unixtime_ms/1000) : (unixtime_ms - (sec * 1000))/1000 + ' ' + sec;
}
// 参数解释
// $string: 明文 或 密文
// $operation:DECODE表示解密,其它表示加密
// $key: 密匙
// $expiry:密文有效期
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') {
// substr($result, 0, 10) == 0 验证数据有效性
// substr($result, 0, 10) - time() > 0 验证数据有效性
// substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
// 验证数据有效性,请看未加密明文的格式
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));
}
}
function authcode(str, operation, key, expiry) {
var operation = operation ? operation : 'DECODE';
var key = key ? key : '';
var expiry = expiry ? expiry : 0;
var ckey_length = 4;
key = md5(key);
// 密匙a会参与加解密
var keya = md5(key.substr(0, 16));
// 密匙b会用来做数据完整性验证
var keyb = md5(key.substr(16, 16));
// 密匙c用于变化生成的密文
var keyc = ckey_length ? (operation == 'DECODE' ? str.substr(0, ckey_length): md5(microtime()).substr(-ckey_length)) : '';
// 参与运算的密匙
var cryptkey = keya+md5(keya+keyc);
var string="";
if(operation == 'DECODE') {
string =Base64.decode(str.substr(ckey_length));
}
else {
expiry = expiry ? expiry + time() : 0;
tmpstr = expiry.toString();
if(tmpstr.length>=10)
string = tmpstr.substr(0,10)+md5(str+keyb).substr(0, 16)+str;
else {
var count = 10 - tmpstr.length;
for(var i=0;i<count;i++) {
tmpstr = '0'+tmpstr;
}
string = tmpstr+md5(str+keyb).substr(0, 16)+str;
}
}
var box = new Array(256);
for(var i=0; i < 256; i++) {
box[i] = i;
}
var rndkey = new Array();
// 产生密匙簿
for(var i=0; i < 256; i++) {
rndkey[i] = cryptkey.charCodeAt(i % cryptkey.length);
}
// 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度
for(var j = i = 0; i < 256; i++) {
j = (j + box[i] + rndkey[i]) % 256;
tmp = box[i];
box[i] = box[j];
box[j] = tmp;
}
// 核心加解密部分
var result = '';
for(var 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+=String.fromCharCode(string.charCodeAt(i) ^ (box[(box[a] + box[j]) % 256]));
}
if(operation == 'DECODE') {
var s="";
if((result.substr(0, 10) == 0 || result.substr( 0, 10) - time() > 0) && result.substr(10, 16) == md5(result.substr(26)+keyb).substr(0, 16)) {
s = result.substr(26);
}
}
else {
var s = Base64.encode(result);
var regex = new RegExp('=', "g");
s = s.replace(regex, '');
s = keyc+s;
}
return s;
}
这里基本上没采用替代版的CHR,ORD,等,都用的JS只带的。我的测试页面编码都是UTF-8编码。
这里的Base64.encode与php的base64_encode结果一样。
前文说的ord,chr 都有提供JS版本的。
chr:http://phpjs.org/functions/chr/
ord:http://phpjs.org/functions/ord/