フォーラムの誰かが以前にこの質問をしました、原文は
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)); } }
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;}
ここで、JS を使用して、元々ソース コードに配置されていた暗号化と復号化データを実装します。それでは、キーをどうするつもりですか? JSに直接入れるんですか?
馬鹿な顧客説明テキスト送信。 。 。 。エルビの上司はパニックになった。 。 。したがって、クライアント暗号化が必要です。 。 。 。
ここで、JS を使用して、元々ソース コードに配置されていた暗号化と復号化データを実装します。それでは、キーをどうするつもりですか? JSに直接入れるんですか?
馬鹿な顧客説明テキスト送信。 。 。 。エルビの上司はパニックになった。 。 。したがって、クライアント暗号化が必要です。 。 。 。
困難を克服するために懸命に努力し、納品後にハッキングされるようにしてください
あなたは現在、JS を使用して、元々ソース コードに配置されていた暗号化と復号化データを実装しています。鍵と関係があるの? JSに直接入れるんですか?
馬鹿な顧客説明テキスト送信。 。 。 。エルビの上司はパニックになった。 。 。したがって、クライアント暗号化が必要です。 。 。 。
頑張って困難を克服し、納品後にハッキングしてもらいましょう
ああ、分かった。こんなことをしても意味がありません。すべてがクライアント側で表示されます。
txのログイン暗号化方式を参考にしましたが、これは諦めました。 。
ここで、JS を使用して、元々ソース コードに配置されていた暗号化と復号化データを実装します。それでは、キーをどうするつもりですか? JSに直接入れるんですか?
馬鹿な顧客説明テキスト送信。 。 。 。エルビの上司はパニックになった。 。 。したがって、クライアント側の暗号化が必要です。 。 。 。
頑張って困難を克服し、納品後にハッキングしてもらいましょう
ああ、分かった。こんなことをしても意味がありません。すべてがクライアント側で表示されます。
txのログイン暗号化方式を参考にしましたが、これは諦めました。 。