discuz通行證用對稱密鑰的加密,基於任何一數與結果異或必然獲得另外一個數,因此是一個可逆的算法,使用密鑰的每位輪迴加密數據的每位.
passport_encrypt函數使用時隨機數來加密,而後把密鑰放在密文的前面,最後調用的passport_key纔是真正的加密解密函數,那爲何這樣作?密鑰和密文放在一塊兒看起來沒用,我剛開始也這麼想,後來發現這偏偏是最重要的,由於是基於異或加密,也就是說,用戶知道任意兩個數就能夠獲得第三個數,當用戶輸一個明文進去,獲得一個密文,再異或就能獲得密鑰,這是不被容許,discuz是如何防止的?採用隨機數,而後MD5,接在與用戶輸入的前面,這樣用戶就不知道本身的輸入,固然他能夠試,每個數有三十六個可能,discuzMD5了一下密鑰,要試36的32的方,並且這樣也只是獲得了一個MD5,邏輯上不大可能.
要作首頁和論壇的通行證了,因此分析一下這個,可能那邊要在jsp上面實現吧.哎
/*** Passport 加密函數** @param string 等待加密的原字串* @param string 私有密匙(用於解密和加密)** @return string 原字串通過私有密匙加密後的結果*/function passport_encrypt($txt, $key) {//R 使用隨機數加密,密鑰放在字符前面// 使用隨機數發生器產生 0~32000 的值並 MD5()srand((double)microtime() * 1000000);$encrypt_key = md5(rand(0, 32000));// 變量初始化$ctr = 0;$tmp = '';// for 循環,$i 爲從 0 開始,到小於 $txt 字串長度的整數for($i = 0; $i < strlen($txt); $i++) {// 若是 $ctr = $encrypt_key 的長度,則 $ctr 清零$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;// $tmp 字串在末尾增長兩位,其第一位內容爲 $encrypt_key 的第 $ctr 位,// 第二位內容爲 $txt 的第 $i 位與 $encrypt_key 的 $ctr 位取異或。而後 $ctr = $ctr + 1$tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]);}// 返回結果,結果爲 passport_key() 函數返回值的 base65 編碼結果return base64_encode(passport_key($tmp, $key)); //R 真正使用密碼加密}/*** Passport 解密函數** @param string 加密後的字串* @param string 私有密匙(用於解密和加密)** @return string 字串通過私有密匙解密後的結果*/function passport_decrypt($txt, $key) {// $txt 的結果爲加密後的字串通過 base64 解碼,而後與私有密匙一塊兒,// 通過 passport_key() 函數處理後的返回值$txt = passport_key(base64_decode($txt), $key); //R 二次加密就是解密// 變量初始化$tmp = '';// for 循環,$i 爲從 0 開始,到小於 $txt 字串長度的整數for ($i = 0; $i < strlen($txt); $i++) {// $tmp 字串在末尾增長一位,其內容爲 $txt 的第 $i 位,// 與 $txt 的第 $i + 1 位取異或。而後 $i = $i + 1$tmp .= $txt[$i] ^ $txt[++$i]; R //解密隨機加密;}// 返回 $tmp 的值做爲結果return $tmp;}/*** Passport 密匙處理函數** @param string 待加密或待解密的字串* @param string 私有密匙(用於解密和加密)** @return string 處理後的密匙*/function passport_key($txt, $encrypt_key) {// 將 $encrypt_key 賦爲 $encrypt_key 經 md5() 後的值$encrypt_key = md5($encrypt_key);// 變量初始化$ctr = 0;$tmp = '';// for 循環,$i 爲從 0 開始,到小於 $txt 字串長度的整數for($i = 0; $i < strlen($txt); $i++) {// 若是 $ctr = $encrypt_key 的長度,則 $ctr 清零$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr; //R 輪// $tmp 字串在末尾增長一位,其內容爲 $txt 的第 $i 位,// 與 $encrypt_key 的第 $ctr + 1 位取異或。而後 $ctr = $ctr + 1$tmp .= $txt[$i] ^ $encrypt_key[$ctr++]; //R 輪翻異或加密; }// 返回 $tmp 的值做爲結果return $tmp;}/*** Passport 信息(數組)編碼函數** @param array 待編碼的數組** @return string 數組經編碼後的字串*/function passport_encode($array) {// 數組變量初始化$arrayenc = array();// 遍歷數組 $array,其中 $key 爲當前元素的下標,$val 爲其對應的值foreach($array as $key => $val) {// $arrayenc 數組增長一個元素,其內容爲 "$key=通過 urlencode() 後的 $val 值"$arrayenc[] = $key.'='.urlencode($val);}// 返回以 "&" 鏈接的 $arrayenc 的值(implode),例如 $arrayenc = array('aa', 'bb', 'cc', 'dd'),// 則 implode('&', $arrayenc) 後的結果爲 」aa&bb&cc&dd"return implode('&', $arrayenc);}