ホームページ > バックエンド開発 > PHPチュートリアル > DZのAuthcode機能をJS版に変換する問題について。

DZのAuthcode機能をJS版に変換する問題について。

WBOY
リリース: 2016-06-23 14:20:44
オリジナル
1412 人が閲覧しました

この投稿は TottyAndBaty によって最終編集されました: 2013-08-30 23:43:38

フォーラムの誰かが以前にこの質問をしました、原文は

http://bbs.csdn.net/topics/390310377?page= 1# post-393233055


php版のauthcodeをjs版に書き込もうとしましたが、結果が違いすぎました。

PHP の JS に対応するいくつかの関数はここで見つけることができます:
chr: http://phpjs.org/functions/chr/

ord: http://phpjs.org/functions/ord/

Base64.encode 、Base64.decode http://www.webtoolkit.info/javascript-base64.html

md5: http://phpjs.org/functions/md5/

Base64.encode と Base64.decode のテスト結果は一致していますphpのものと同じです。


その投稿の中でモデレーターは、「文字セットの問題 (js は常に Unicode を使用する) のため、リテラル翻訳は php と同等ではなく、あまり意味がありません。」 と述べました。

DZ の Authcode 関数は RC4 アルゴリズムを使用しており、

  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]));      }  
ログイン後にコピー


この部分が JS 版で書かれている場合、PHP 版とは問題が異なります。 $string は、このコードを実行する前は同じですが、実行後は異なります。

添付コード:

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;}
ログイン後にコピー


PHP バージョン:

   // 参数解释  // $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 コード部分
68 strbuf[i] =chr(ord(strbuf[i])^ (box [ (box[a] + box[j]) % 256]))
この strbuf は配列ですか?
21 strbuf = Base64.decode(str);
または
36 strbuf = str;
の場合、strbuf[i] = 'x' は無効ですが、エラーは報告されません
同様に ord (strbuf[i]) は正しい値を返すことができません

ord(strbuf[i]) に対応する js は
strbuf.charCodeAt(i) です

chr(n) に対応する js は
String.fromCharCode( n) です

私はあなたが提供したのと同じ名前の php 関数を真剣に調べていませんでしたが、少なくとも js 値の取得と割り当ての部分に問題があります

さらに:
DZ の配布バージョンは次のように分かれています。 utf-8 と gbk
内部コードの性質上、utf-8 バージョンでの Authcode エンコード結果は gbk バージョンでは正しくデコードできません (デコードされたバージョンは utf-8 のままです)
もちろん、中国語が含まれていなければ問題ありません。これがテスト対象です。必ず注意してください

Base64 クラスは utf-8 エンコーディングにも対応しています。 PHP側がutf-8でない場合、同じ結果は得られません

申し訳ありません、見落としです。間違ったバージョンが送信されました。

このコードは私の最終修正の結果です:

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/


元々ソース コードに配置されていた暗号化および復号化データ。現在使用しています。 JS で実装してから、キーをどうするか尋ねます。 JSに直接入れるんですか?

ここで、JS を使用して、元々ソース コードに配置されていた暗号化と復号化データを実装します。それでは、キーをどうするつもりですか? JSに直接入れるんですか?

馬鹿な顧客説明テキスト送信。 。 。 。エルビの上司はパニックになった。 。 。したがって、クライアント暗号化が必要です。 。 。 。


ここで、JS を使用して、元々ソース コードに配置されていた暗号化と復号化データを実装します。それでは、キーをどうするつもりですか? JSに直接入れるんですか?

馬鹿な顧客説明テキスト送信。 。 。 。エルビの上司はパニックになった。 。 。したがって、クライアント暗号化が必要です。 。 。 。
困難を克服するために懸命に努力し、納品後にハッキングされるようにしてください



あなたは現在、JS を使用して、元々ソース コードに配置されていた暗号化と復号化データを実装しています。鍵と関係があるの? JSに直接入れるんですか?

馬鹿な顧客説明テキスト送信。 。 。 。エルビの上司はパニックになった。 。 。したがって、クライアント暗号化が必要です。 。 。 。
頑張って困難を克服し、納品後にハッキングしてもらいましょう

ああ、分かった。こんなことをしても意味がありません。すべてがクライアント側で表示されます。

txのログイン暗号化方式を参考にしましたが、これは諦めました。 。






ここで、JS を使用して、元々ソース コードに配置されていた暗号化と復号化データを実装します。それでは、キーをどうするつもりですか? JSに直接入れるんですか?

馬鹿な顧客説明テキスト送信。 。 。 。エルビの上司はパニックになった。 。 。したがって、クライアント側の暗号化が必要です。 。 。 。
頑張って困難を克服し、納品後にハッキングしてもらいましょう

ああ、分かった。こんなことをしても意味がありません。すべてがクライアント側で表示されます。

txのログイン暗号化方式を参考にしましたが、これは諦めました。 。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート