標籤:enc china 自訂 bst operation 永久 解密 com key值
1、前言
康盛的 authcode 函數很牛叉,是一個具有有效期間的加解密函數,同一個字元每次加密所產生的結果都是不一致的,並且可以自訂設定到期時間。
設計原理:authcode 是使用異或運算進行加密和解密。
加密
明文:1010 1001
密匙:1110 0011
密文:0100 1010
得出密文0100 1010,解密之需和密匙異或下就可以了
解密
密文:0100 1010
密匙:1110 0011
明文:1010 1001
並沒有什麼高深的演算法,密匙重要性很高,所以,關鍵在於怎麼產生密匙。
2、代碼解析
1 <?php 2 3 /** 4 * @param string $string 原文或者密文 5 * @param string $operation 操作(ENCODE | DECODE), 預設為 DECODE 6 * @param string $key 密鑰 7 * @param int $expiry 密文有效期間, 加密時候有效, 單位 秒,0 為永久有效 8 * @return string 處理後的 原文或者 經過 base64_encode 處理後的密文 9 *************************10 * @example11 * 12 * $a = authcode(‘abc‘, ‘ENCODE‘, ‘key‘);13 * $b = authcode($a, ‘DECODE‘, ‘key‘); // $b(abc)14 *15 * $a = authcode(‘abc‘, ‘ENCODE‘, ‘key‘, 3600);16 * $b = authcode(‘abc‘, ‘DECODE‘, ‘key‘); // 在一個小時內,$b(abc),否則 $b 為空白17 */18 function authcode($string, $operation = ‘DECODE‘, $key = ‘‘, $expiry = 3600) {19 20 // 隨機密鑰長度 取值 0-32;21 // 加入隨機密鑰,可以令密文無任何規律,即便是原文和密鑰完全相同,加密結果也會每次不同,增大破解難度。22 // 取值越大,密文變動規律越大,密文變化 = 16 的 $ckey_length 次方23 // 當此值為 0 時,則不產生隨機密鑰24 $ckey_length = 4; 25 26 $key = md5($key ? $key : ‘default_key‘); // 這裡可以填寫預設key值27 $keya = md5(substr($key, 0, 16)); // 密匙a會參與加解密 [keya = md5 新key前16位]28 $keyb = md5(substr($key, 16, 16)); // 密匙b會用來做資料完整性驗證 [keyb = md5 新key後16位]29 // 密匙c用於變化產生的密文 30 // 加密:keyc = 目前時間毫秒做md5加密,截取末尾隨機秘鑰長度字元31 // 解密:keyc = 截取傳入的字串string末尾隨機秘鑰長度字元32 $keyc = $ckey_length ? ($operation == ‘DECODE‘ ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : ‘‘;33 // 參與運算的密匙 34 $cryptkey = $keya.md5($keya.$keyc);35 $key_length = strlen($cryptkey);36 37 // 明文,前10位用來儲存時間戳記,解密時驗證資料有效性,10到26位用來儲存$keyb(密匙b),解密時會通過這個密匙驗證資料完整性 38 // 如果是解碼的話,會從第$ckey_length位開始,因為密文前$ckey_length位儲存 動態密匙,以保證解密正確 39 $string = $operation == ‘DECODE‘ ? base64_decode(substr($string, $ckey_length)) : sprintf(‘%010d‘, $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;40 $string_length = strlen($string);41 $result = ‘‘;42 $box = range(0, 255);43 44 $rndkey = array();45 // 產生密匙簿 46 for($i = 0; $i <= 255; $i++) {47 $rndkey[$i] = ord($cryptkey[$i % $key_length]);48 }49 50 // 用固定的演算法,打亂密匙簿,增加隨機性,好像很複雜,實際上對並不會增加密文的強度51 for($j = $i = 0; $i < 256; $i++) {52 $j = ($j + $box[$i] + $rndkey[$i]) % 256;53 $tmp = $box[$i];54 $box[$i] = $box[$j];55 $box[$j] = $tmp;56 }57 58 // 核心加解密部分59 for($a = $j = $i = 0; $i < $string_length; $i++) {60 $a = ($a + 1) % 256;61 $j = ($j + $box[$a]) % 256;62 $tmp = $box[$a];63 $box[$a] = $box[$j];64 $box[$j] = $tmp;65 // 從密匙簿得出密匙進行異或,再轉成字元 66 $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));67 }68 69 if($operation == ‘DECODE‘) {70 // substr($result, 0, 10) == 0 驗證資料有效性 71 // substr($result, 0, 10) - time() > 0 驗證資料有效性 72 // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 驗證資料完整性 73 // 驗證資料有效性,請看未加密明文的格式 74 if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {75 return substr($result, 26);76 } else {77 return ‘‘;78 }79 } else {80 // 把動態密匙儲存在密文裡,這也是為什麼同樣的明文,生產不同密文後能解密的原因81 // 因為加密後的密文可能是一些特殊字元,複製過程可能會丟失,所以用base64編碼 82 return $keyc.str_replace(‘=‘, ‘‘, base64_encode($result));83 }84 85 }
3、參考文獻
1、《discuz 經典php加密解密函數 authcode 解析》
康盛(discuz )牛逼的PHP加解密演算法函數