PHP開發(fā)者在日常工作中,經(jīng)常會使用到PHP的MD5函數(shù)。該函數(shù)可以加密一段數(shù)據(jù),并得到一段長度為32位的唯一加密字符串。所有PHP程序員對于MD5這個函數(shù)肯定早已經(jīng)了解得很深入了,那么今天我們不妨來一探究竟,看看PHP中MD5函數(shù)的源碼實現(xiàn)。
為了更好地理解MD5算法的工作方式,我們可以從對其輸入數(shù)據(jù)的預處理開始。在PHP的源代碼當中,輸入數(shù)據(jù)被看作一個字符串,然后被劃分成了512位的塊,每個塊被視為16個32位的小塊。接下來,我們可以使用以下示例PHP代碼,來查看該處理過程的具體實現(xiàn)。
function md5_prep_data($input) { $length = strlen($input); $size = 64 - ($length + 8) % 64; $input .= str_repeat("\0", $size); $input .= pack("V", $length); return $input; }在上述代碼中,我們可以看到首先對輸入數(shù)據(jù)進行了長度檢查,然后為了填充數(shù)據(jù)塊,使用了不定長度填充函數(shù)。這個函數(shù)通過為輸入數(shù)據(jù)添加一個填充字節(jié)序列,來確保數(shù)據(jù)長度能夠被4整除。由于填充字節(jié)序列的長度不確定,我們需要利用str_repeat函數(shù)來填充字節(jié)序列,確保其長度滿足需要的塊大小。最后,我們還需要在末尾添加一個64位的long類型的數(shù)據(jù),表示輸入數(shù)據(jù)的原始長度。 接下來,我們將從改善消息摘要的角度,進行MD5算法的實現(xiàn)。在該過程中,我們將通過多次對16個32位小塊的處理,來得到最終的128位哈希。
function md5_improve_hash(&$hashes, $data) { $t = 0; $p = 0; for ($i = 0; $i< 16; $i++) { $t = $data[$p++] & 0xff; $t |= ($data[$p++] & 0xff)<< 8; $t |= ($data[$p++] & 0xff)<< 16; $t |= ($data[$p++] & 0xff)<< 24; $hashes[$i] = $t; } return $hashes; }在上述代碼當中,我們可以看到將當前塊的16個32位小塊賦值給了$hashes數(shù)組。最終,這個數(shù)組將會被用于計算最終的哈希值。通過對每個小塊逐一處理,再將它們合并成一個128位的哈希值。 接下來是MD5算法的主代碼,該算法是所有PHP源代碼中MD5處理的核心過程。我們先來看看預處理的數(shù)據(jù)塊計算函數(shù)。
function md5_calc_function($f, $b, $c, $d) { switch ($f) { case 0: return ($b & $c) | (~$b & $d); case 1: return ($b & $d) | ($c & ~$d); case 2: return $b ^ $c ^ $d; case 3: return $c ^ ($b | ~$d); } }在上述代碼當中,我們可以看到$ f參數(shù)表示了將要用到的函數(shù)的類型。而后其他三個函數(shù)變量則表示了需要處理的塊。 最后,讓我們來看看PHP源代碼中MD5核心函數(shù)的實現(xiàn)。
function md5_core($process, $hashes, $input, $index) { $a = $hashes[0]; $b = $hashes[1]; $c = $hashes[2]; $d = $hashes[3]; for ($i = 0; $i< $process; $i += 4) { $f = $i/4; $temp = $d; $d = $c; $c = $b; $b = $a; $a = $hashes[$f] + $a + md5_calc_function($f % 4, $b, $c, $d) + $input[$index + $i]; $a = $a & 0xffffffff; $temp_hash = $a; $a = $d; $d = $c; $c = $b; $b = $temp; $hashes[$f] = $temp_hash; } return $hashes; }在上述代碼當中,我們可以看到通過一個循環(huán)來處理每個數(shù)據(jù)塊。將當前哈希值保存在變量$a中,并且處理當前塊的16個小塊。組合這些小塊,最終得到當前塊的哈希值。最后,我們可以使用$hashes數(shù)組存儲結果,以便于后續(xù)計算。 這就是PHP中MD5函數(shù)的源代碼實現(xiàn)。通過這篇文章,我們可以看到PHP中MD5函數(shù)經(jīng)過了重重處理,才能夠得到最終的哈希值。雖然我們一般只需要調(diào)用MD5函數(shù),但是這個函數(shù)的內(nèi)部實現(xiàn)卻非常有趣和值得研究。