php 162 x69 144,DiscuzX中uc_authcode函数js版本,配合php版双向加密解密

上周准备写一个js版的uc_authcode函数,根据网上整理的资料:http://bbs.csdn.net/topics/390310377?page=1中Frogant的源码(纯JS版)进行相关测试。

同时引入了md5.js和base64.js库。测试结果的准确率不到一半,于是根据DX中的uc_authcode源码进行跟踪调试,发现问题出在base64的编码上,可能是中外对字符串的编码不一致导致的。

注意:无论是js还是php的脚本文件的编码必须为utf-8编码,否则可能会出现错误。原版的代码在IE下兼容有一些问题,经过修改之后目前可兼容IE6,7,8,opera,firefox,google等浏览器。源代码如下:html>

if(isset($_GET['jsCode']))

{

//传入的字符串

$jsCode = base64_decode($_GET['jsCode']);

p('jsCode:'.$jsCode);

//解码后的字符串

$decode = uc_authcode($jsCode, 'DECODE', 'key');

p('解码后:'.$decode);

//urldecode之后的字符串

p('urldecode后:'.urldecode($decode));

}else{

$en = '~!@#$%^&*()_+=-0987654321\][.,/';

$en_code = uc_authcode($en, 'ENCODE', 'key');

p(uc_authcode($en_code, 'DECODE', 'key'));

$cn = '屌丝(联通)';

$cn_code = uc_authcode($cn, 'ENCODE', 'key');

p(uc_authcode($cn_code, 'DECODE', 'key'));

$str = urlencode('来自php加密');

$encode = uc_authcode($str, 'ENCODE', 'key');

}

function p($var)

{

echo "

";

if($var === false)

{

echo 'false';

}else if($var === ''){

print_r("''");

}else{

print_r($var);

}

echo "

";

}

/**

* @param    string      $string 加密内容

* @param    string      $operation 加密动作

* @param    string      $key 私钥

* @param    int         $expiry 有效时间秒

* @return   string      加密串

*/

function uc_authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)

{

$ckey_length = 4;

$key = md5($key);

$keya = md5(substr($key, 0, 16));

$keyb = md5(substr($key, 16, 16));

$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';

$cryptkey = $keya.md5($keya.$keyc);

$key_length = strlen($cryptkey);

$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 

{

$j = ($j + $box[$i] + $rndkey[$i]) % 256;

$tmp = $box[$i];

$box[$i] = $box[$j];

$box[$j] = $tmp;

}

for($a = $j = $i = 0; $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{

return $keyc.str_replace('=', '', base64_encode($result));

}

}

?>

/**

* @param    string      str 加密内容

* @param    string      operation 加密动作

* @param    string      key 密钥

* @param    int         expiry 有效时间秒

* @return   string      加密串

*/

function uc_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用于变化生成的密文

// IE下不支持substr第一个参数为负数的情况

if(ckey_length){

if(operation == 'DECODE'){

var keyc = str.substr(0, ckey_length);

}else{

var md5_time = md5(microtime());

var start = md5_time.length - ckey_length;

var keyc = md5_time.substr(start, ckey_length)

}

}else{

var keyc = '';

}

// 参与运算的密匙

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 

tmpstr = '0' + tmpstr;

}

str = tmpstr + md5(str + keyb).substr(0, 16) + str;

}

strbuf = str;

}

var box = new Array(256);

for (var i = 0; i 

box[i] = i;

}

var rndkey = new Array();

// 产生密匙簿

for (var i = 0; i 

rndkey[i] = cryptkey.charCodeAt(i % cryptkey.length);

}

// 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度

for (var j = i = 0; i 

j = (j + box[i] + rndkey[i]) % 256;

tmp = box[i];

box[i] = box[j];

box[j] = tmp;

}

// 核心加解密部分

var s = '';

//IE下不支持直接通过下标访问字符串的字符,需要先转换为数组

strbuf = strbuf.split('');

for (var a = j = i = 0; i 

a = (a + 1) % 256;

j = (j + box[a]) % 256;

tmp = box[a];

box[a] = box[j];

box[j] = tmp;

// 从密匙簿得出密匙进行异或,再转成字符

s += chr(ord(strbuf[i])^(box[(box[a] + box[j]) % 256]));

}

if (operation == 'DECODE') {

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 {

s = base64_encode(s);

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;

}

function chr(s) {

return String.fromCharCode(s);

}

function ord(s) {

return s.charCodeAt();

}

function md5(str) {

return hex_md5(str);

}

var resultDiv = document.getElementById('resultDiv');

var str = resultDiv.innerHTML;

//php加密,js解密

document.write(uc_authcode(str, 'DECODE', 'key')+'
');

//使用错误密钥将会得到空字符串

document.write(uc_authcode(str, 'DECODE', 'errorkey')+'
');

//英文测试,js加密解密

var en = '~!@#$%^&*()_+=-0987654321\][.,"\'>

var en_code = uc_authcode(en, 'ENCODE', 'key');

document.write(uc_authcode(en_code, 'DECODE', 'key')+'
');

//中文测试,js加密解密,特殊编码字符串需要通过手动进行encodeURI编码解码,暂未发现异常

var cn = encodeURI('屌丝联通营业(),。?“:》《%……');

var cn_code = uc_authcode(cn, 'ENCODE', 'key');

document.write(cn_code+'
');

resultDiv.innerHTML = '点我使用php解码';

经过反复尝试,中文字符未采用duyipeng上传的base64.js中的utf16to8编码方式,而是采用js原生的encodeURI进行编码,在php端同样可以使用urlencode进行编码。最后进行双向测试,目前进行测试的字符全部加密解密成功,由此可以实现js和php进行无缝对接。

注意:在使用GET方式传参过程中,经过uc_authcode之后的加密串可能会带有空格等特殊字符,需要使用js版base64_encode进行编码后传输,在php端使用php版base64_decode进行解码,然后使用uc_authcode进行解密。

转载随意,但请附上文章地址:-)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值