白話 discuz加密解密演算法,包你懂

2022-04-09 07:32:38 字數 4313 閱讀 7378

今天和大家分享一下discuz的加密和解密演算法

研究了乙個星期了,

總結了這個

演算法有三個特點

1,動態性,同一字串每次加密的密文都不一樣

2,時間性,可以自己加乙個限期引數,以秒為單位

3,統一性,加密和解密都用同乙個函式

大家可以想一想

要想每次加密後的密文都不一樣,而金鑰是同乙個,那解密只有乙個辦法,

就是把解密的資訊肯定放到密文上面,從而解密

就像你跟不同的人下棋,對手有很多個,如果你想贏,肯定跟不同的人下就用不同的棋

法,而至於用什麼棋法,就要看你的對手是個什麼樣的人,有急躁的,粗心的,等等

第二時間有限性

這個大家肯定一眼就能看出來如果我判斷乙個快取過期了沒有

我可以通過它的建立時間和現在時間對比一下,用這個差值和

租期比較有沒有過期,那肯定這個也要放在密文裡面

第三的話統一性的

該函式就用到異或演算法,比較簡單

例如 明文是01,金鑰是10,兩個異或完之後密文就是11,

而密文再和金鑰異或就可以得到明文,也就是01

而密文和明文異或之後就可以得到金鑰10,是不是很神奇

連我自己都不相信,但事實上就是這樣,其實計算機還有很多

這樣類似的規律

function uc_authcode($string, $operation = 'decode', $key = '123', $expiry = 0)

for ($j = $i = 0; $i < 256; $i++)

for ($a = $j = $i = 0; $i < $string_length; $i++)

if ($operation == 'decode') else

} else

}分析一下1到5行

就是簡單的吧金鑰用md5加密,沒有金鑰的話就用uckey

得到一串32個位加密後的金鑰

$keya 作為密碼本(就是一推打亂的數字)來用

$keyb參與加密這個跟金鑰有關,解密用來驗證的

$ckey_length = 4;

然後就是ckey_length的用處就是為了

就是限制一下加密的後的字串長度

讀者可以自己親自試一下改變 ckey_length

看看輸出來的密文一不一樣

可以看看**最後一句

return $keyc . str_replace('=', '', base64_encode($result));

下面分析keyc

請分析這一行

substr(md5(microtime()), -$ckey_length)) : '';

這就是為什麼同一字串加密後的密文都不一樣

就是利用了時間的唯一性,上面是返回毫秒數再用md5返回 0到32位的字串給keyc

好接著分析

$cryptkey = $keya . md5($keya . $keyc); //64

$key_length = strlen($cryptkey); //64

這個 生成64位的密碼本後面會用到

$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);

到這裡啦

先不看解密的就是會執行這句

sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;

// 明文,前10位用來儲存時間戳,解密時驗證資料有效性,10到26位用來儲存$keyb的

如果沒有租期的話前十位是0的

我們在這裡可以得出

這時候的長度由

$ckey_length+10時間位+16位的$keyb+明文的長度

$result = '';

$box = range(0, 255);

$rndkey = array();

for ($i = 0; $i <= 255; $i++)

for ($j = $i = 0; $i < 256; $i++)

上面是生成256乙個隨機數組

就像洗牌演算法一樣

rand(0,52)

你可以迴圈52次來洗牌

如果重複的話再來一次rand

但這樣的效率不高

而是用for ($i = 0; $i < 52; $i++)

這樣就算重複了隨機數,但每個數在其他位置還是相等的概率,讀者可以自己想一下

而上面 用了 $j = ($j + $box[$i] + $rndkey[$i]) % 256;

這句增加加了隨機性,就是什麼牌一樣,第乙個變了,其他也跟著變了,可以這樣說吧

第乙個數隨機了,而後面的數也隨機啦,而且隨機性會越來愈大

不用rand(0,52)是為了保持加密和解密的密碼本是一樣的

for ($a = $j = $i = 0; $i < $string_length; $i++)

然後到了這裡啦

其實上面也是打亂演算法,再一次打亂,好像沒什麼用

但我自己想啊

如果把他注釋掉

執行第一句

執行 後 也能加密也能機密,如果讀者看懂的話告訴我一聲,

後來想想可能是因為,我們第一次生成了0到255的隨機數,而$string_length這個可能沒有這麼長

可能長度只有40,50啊,60啊,如果要加密的字串很短的話,那密碼本大於長度的那些元素就用不上

啦,那就浪費啦

我想可能是這個原因吧

$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));

這一句就是異或的作用啦,用ascci碼異或後再轉字元,函式可以自己查查是什麼

比如 chr(ord('a')) 還是 a

return $keyc . str_replace('=', '', base64_encode($result));

最後來到這句

就完成了加密啦

為什麼要用base64呢

呵呵,因為異或後的字元不一定是可以列印的字元,所以要用base64來加密一下,後面有時間我說一說

base64的原理和用php親自寫一下

最後用keyc連線呵呵,還記得我開始說的話嗎,慢慢理解一下

下面就開始分析解密的過程

上面講過的那些就不講啦

$key = md5($key ? $key : uc_key); //加密解密時這個是不變的

$keya = md5(substr($key, 0, 16)); //加密解密時這個是不變的

$keyb = md5(substr($key, 16, 16)); //加密解密時這個是不變的

$keyc = $ckey_length ? ($operation == 'decode' ? substr($string, 0, $ckey_length) :

作用是為了保證加密和加密用的那個密碼本是一樣的

$string = $operation == 'decode' ? base64_decode(substr($string, $ckey_length))

這裡取出後$ckey_length個字元

10時間位+16位的$keyb+明文的長度

$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));

如果密碼本加密和解密的一樣 那麼 這句就會變回明文啦,如果不清楚異或的看上面我介紹的

if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) else

好了,終於來到這裡啦,先驗證時間有效性,和keyb是不是用這個金鑰生成的,如果是就返回明文給他

ok,終於分析完

其實我還有乙個問題還沒有明白就是為什麼密碼本長度是256個,我猜的話,因為ascii碼兩個相加不超過255

看看這句話$box[($box[$a] + $box[$j]) % 256],真的發覺discuz這個函式寫的太精彩啦

第一次寫教程,不懂排版,請大家見諒

加密,解密演算法

private symmetricalgorithm mcsp 宣告對稱演算法變數 private const string civ mi56 4zujhy12se6yjy111a 初始化向量 private const string ckey jkhuiy9d 9i 金鑰 常量 其中civ裡面的值...

Discuz 經典加密解密函式 帶詳解

可在配置檔案裡指定預設金鑰 au key 2347adfas string 明文 或 密文 operation decode表示解密,其它表示加密 key 密匙 expiry 密文有效期 function authcode string,operation decode key expiry 0 用...

加密與解密演算法

加密 public static string encode string data 解密 public static string decode string data catch descryptoserviceprovider cryptoprovider new descryptoservi...