将DX中的authcode改成JS版,高难度的转换

看小雪 2012-12-09 09:04:22

// 参数解释
// $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));
}
}


不晓得那位大虾能改成JS版,因为目前没发现JS有好用而且能与动态语言互用的加密解密函数,不要对我说base64呀。


谢谢!!!
...全文
732 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
gloomyzerg 2014-01-24
  • 打赏
  • 举报
回复
引用 14 楼 czw249 的回复:


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 = new Buffer(str,'base64');
		//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 = new Buffer(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] = 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 = strbuf.toString('base64');

		var regex = new RegExp('=', "g");
		s = s.replace(regex, '');
		s = keyc+s;
	}

	return s;
}

function md5(str){
    var hash = require('crypto').createHash('md5');
    return hash.update(str+"").digest('hex');
}

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;
}

//console.log(authcode('4961CxOTjLPyesRm0Qips70cCaFJzgCZg4F4GGMiDVQ','DECODE','key'));
//console.log(authcode('abc','ENCODE','key'));

这个方法 思路是对的 但是有一个小问题 就是 中文加密的问题 你的md5 对中文加密的话会和PHP 不一致 应该 改成

function md5(str){
  var Buffer = require('buffer').Buffer
  var buf = new Buffer(1024);
  var len = buf.write(str, 0);
  str = buf.toString('binary', 0, len);

  var md5sum = require('crypto').createHash('md5');
  md5sum.update(str);
  str = md5sum.digest('hex');
  return str;
}
Frogant 2014-01-13
  • 打赏
  • 举报
回复
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 += 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();}

纯JS的,需要自己先加载 MD5.js 和 base64.js 分别实现 MD5 和 base64
czw249 2013-03-11
  • 打赏
  • 举报
回复


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 = new Buffer(str,'base64');
		//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 = new Buffer(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] = 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 = strbuf.toString('base64');

		var regex = new RegExp('=', "g");
		s = s.replace(regex, '');
		s = keyc+s;
	}

	return s;
}

function md5(str){
    var hash = require('crypto').createHash('md5');
    return hash.update(str+"").digest('hex');
}

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;
}

//console.log(authcode('4961CxOTjLPyesRm0Qips70cCaFJzgCZg4F4GGMiDVQ','DECODE','key'));
//console.log(authcode('abc','ENCODE','key'));

czw249 2013-03-11
  • 打赏
  • 举报
回复
我今天实现了一个node.js版本authcode 有人要吗
看小雪 2012-12-17
  • 打赏
  • 举报
回复
不弄了,好难呀。 本来是想把DX论坛用的authcode弄成JS版,汗,感觉以我的水平不太现实。
xuzuning 2012-12-12
  • 打赏
  • 举报
回复
PHP 对应 js chr String.fromCharCode ord String.charCodeAt range(0, 255) new Array(256); 然后循环充填 由于涉及字符集问题(js 始终使用unicode),直译后与php不对等,没有大大意义
看小雪 2012-12-12
  • 打赏
  • 举报
回复
js中不晓得那些函数与PHP中的这些相对应range(0, 255)、chr、ord,所以弄了一下,不成功,才来这里求助的。 我不经常写js,如果用也是jquery。 目前出现的PHP问题我都能解决掉,但JS的话,必须要找高手了,毕竟我不擅长,而且我的发展方向为后端或者运维。 版主也来了,那就写个完全的吧,也好测试,为web2.0做点贡献,毕竟很少的网站才会做前端加密的。 PS:虽然我的小博客用了前端登录加密,但不通用,因此才想找一款适合前端加密的函数。希望版主能够理解。
xuzuning 2012-12-12
  • 打赏
  • 举报
回复
没有解决的办法? 我想应该有,不过应该很麻烦 你不是有 js 版的 base64 吗?你可用它对中文进行编解码测试一下
看小雪 2012-12-12
  • 打赏
  • 举报
回复
引用 9 楼 xuzuning 的回复:
PHP 对应 js chr String.fromCharCode ord String.charCodeAt range(0, 255) new Array(256); 然后循环充填 由于涉及字符集问题(js 始终使用unicode),直译后与php不对等,没有大大意义
弱弱的问下:直译后不对等,难道没有解决的办法? 版主,如果文件编码用utf-8,PHP也用utf-8,这样呢????
看小雪 2012-12-11
  • 打赏
  • 举报
回复
@sibang : DX用到的加密解密算法当中用到了base64_decode、md5,这个你不用关心,我有现成的JS版,可以直接使用,你能把其它的代码转换成JS吗???
看小雪 2012-12-11
  • 打赏
  • 举报
回复
引用 2 楼 sibang 的回复:
工程挺大的,自己修改的挺头大,你可以参考别人写的稍加修改一下 http://hi.baidu.com/suidxfzggebjmqq/item/aaa6259751875bf229164794
主要是没有经过时间的沉淀,稳定不稳定还不知道呀。稳定性在加密与解密当中是相当重要的。其次才是加密强度,我是这样认为的。以前看别人弄的base64,结果有些无法解密。太扯蛋了。
xuzuning 2012-12-11
  • 打赏
  • 举报
回复
开玩笑吧? js 的string 提供有 substr 方法 返回一个从指定位置开始的指定长度的子字符串。 substring 方法 返回位于 String 对象中指定位置的子字符串。
引用 6 楼 sibang 的回复:
你写一个substr函数吧,然后我帮你把php转成js substr($key, 0, 16)这个函数用来从string类型的变量$key左侧抓取16位 ord用来返回字符的 ASCII 码值 这俩函数搞定了就没难点了.
www_7di_net 2012-12-11
  • 打赏
  • 举报
回复
你写一个substr函数吧,然后我帮你把php转成js substr($key, 0, 16)这个函数用来从string类型的变量$key左侧抓取16位 ord用来返回字符的 ASCII 码值 这俩函数搞定了就没难点了.
www_7di_net 2012-12-11
  • 打赏
  • 举报
回复
只要base64没问题,别的都很简单啊
www_7di_net 2012-12-10
  • 打赏
  • 举报
回复
工程挺大的,自己修改的挺头大,你可以参考别人写的稍加修改一下 http://hi.baidu.com/suidxfzggebjmqq/item/aaa6259751875bf229164794
看小雪 2012-12-10
  • 打赏
  • 举报
回复
JS的高手呀,过来看看吧,我是只会些PHP,懂一点点的JS皮毛。

20,359

社区成员

发帖
与我相关
我的任务
社区描述
“超文本预处理器”,是在服务器端执行的脚本语言,尤其适用于Web开发并可嵌入HTML中。PHP语法利用了C、Java和Perl,该语言的主要目标是允许web开发人员快速编写动态网页。
phpphpstorm 技术论坛(原bbs)
社区管理员
  • 开源资源社区
  • phpstory
  • xuzuning
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧