解析discuz authcode&&base64加密方式

來自http://hi.baidu.com/studyphp
function authcode ($string, $operation, $key = '') {
#string 爲需加、解密字符串
#operation DECODE時解密

$key = md5($key ? $key : $GLOBALS['discuz_auth_key']);
$key_length = strlen($key);

$string = $operation == 'DECODE' ? base64_decode($string) : substr(md5($string.$key), 0, 8).$string;
#注意這裏,如果不是解密的話。string爲string&key的md5的前8位。
$string_length = strlen($string);

$rndkey = $box = array();
$result = '';

for($i = 0; $i <= 255; $i++) {
    $rndkey[$i] = ord($key[$i % $key_length]);
    $box[$i] = $i;
}

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;
#以上的過程就是加、解密的過程。雖說寫的很複雜,但是原理很簡單。只要key不變,($box[($box[$a] + $box[$j]) % 256])都是唯一的值,加密時當1^0時變成了1,解密時1^0自然變成了1,或者這樣說,加密時0^1變成1,解密時1^1就變成了0.
    $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
所以經過這個過程,是解密時,$result此時就被還原了.
}

if($operation == 'DECODE') {
    echo substr($result, 0, 8).'<br>';
之前說 $string的前8位是key的md5的前8位,後面就是string,所以下面這個判斷也就不難理解了.
    if(substr($result, 0, 8) == substr(md5(substr($result, 8).$key), 0, 8)) {
     return substr($result, 8);
    } else {
     return '';
    }
} else {
    return str_replace('=', '', base64_encode($result));
}

}
轉載請注:來自http://hi.baidu.com/studyphp
後附:base64的編,解碼原理

Base64 編碼其實是將3個8位字節轉換爲4個6位字節,( 3*8 = 4*6 = 24 ) 這4個六位字節 其實仍然是8位,只不過高兩位被設置爲0. 當一個字節只有6位有效時,它的取值空間爲0 到 2的6次方減1 即63,也就是說被轉換的Base64編碼的每一個編碼的取值空間爲(0~63) 。

事實上,0~63之間的ASCII碼有許多不可見字符,所以應該再做一個映射,映射表爲

‘A‘ ~ ‘Z‘ ? ASCII(0 ~ 25)

‘a’ ~ ‘z‘ ? ASCII(26 ~ 51)

‘0’ ~ ‘9‘ ? ASCII(52 ~ 61)

‘+‘ ? ASCII(62)

‘/‘ ? ASCII(63)

這樣就可以將3個8位字節,轉換爲4個可見字符。

具體的字節拆分方法爲:(圖(畫得不好,領會精神 :-))

aaaaaabb ccccdddd eeffffff    //abcdef其實就是1或0,爲了看的清楚就用abcdef代替

~~~~~~~~ ~~~~~~~~ ~~~~~~~~

字節 1 字節 2 字節 3

    ||
    //

00aaaaaa 00bbcccc 00ddddee 00ffffff

注:上面的三個字節位原文,下面四個字節爲Base64編碼,其前兩位均爲0。

這樣拆分的時候,原文的字節數量應該是3的倍數,當這個條件不能滿足時,用全零字節

補足,轉化時Base64編碼用=號代替,這就是爲什麼有些Base64編碼以一個或兩個等號結

束的原因,但等號最多有兩個,因爲:如果F(origin)代表原文的字節數,F(remain)代

表餘數,則

F(remain) = F(origin) MOD 3 成立。

所以F(remain)的可能取值爲0,1,2.

如果設 n = [F(origin) – F(remain)] / 3

當F(remain) = 0 時,恰好轉換爲4*n個字節的Base64編碼。

當F(remain) = 1 時,由於一個原文字節可以拆分爲屬於兩個Base64編碼的字節,爲了

讓Base64編碼是4的倍數,所以應該爲補2個等號。

當F(remain) = 2 時,由於兩個原文字節可以拆分爲屬於3個Base64編碼的字節,同理,

應該補上一個等號。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章