- 1對1字元交換方式
- 0xFF 的 XOR 字元 運算方式
- 字元移位方式
第一種:1對1字元交換方式。這一種的方式如同 PHP的str_rot13的函式一樣,為固定的英文字母作交換。下面範例是用PHP實作 str_rot13的方式:
<?php
class String1
{
// 搜尋字元組
public static $rot13_from = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 替換字元組
public static $rot13_to = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM";
public static function encode ($str)
{
preg_match_all('/[a-zA-Z]/', self::$rot13_from, $rot13_search_array);
preg_match_all('/[a-zA-Z]/', self::$rot13_to, $rot13_replace_array);
// 組合成陣列 array('a' => 'n', 'b' => 'o' .... 的陣列
$tr = array_combine($rot13_search_array[0], $rot13_replace_array[0]);
// 轉換資料
return strtr($str, $tr);
}
public static function decode ($str)
{
return self::encode($str);
}
}
$str = "PHP: Hypertext Preprocessor";
echo str_rot13($str);
echo "\r\n";
echo $rot13 = String1::encode($str);
echo "\r\n";
echo str_rot13($rot13);
echo "\r\n";
echo String1::decode($rot13);
?>
我們可以再String1 這個類別內的encode方法,看到使用 preg_match_all 用正規表示式將定義的固定字串的字元抓取到陣列內,並且再使用array_combine 將兩陣列組合成為一個索引值和資料值對應的陣列。如所引值為 a 那麼對應的值為 n,所引值為 b 那麼其對應的值為 o。之後用 strtr 這個函式將字串依照陣列定義作資料轉換。
上面範例的輸出結果:
CUC: Ulcregrkg Cercebprffbe
CUC: Ulcregrkg Cercebprffbe
PHP: Hypertext Preprocessor
PHP: Hypertext Preprocessor這個觀念可以延伸到0x00 - 0xff 字元作成對應表,再將資料作轉換也可以。
第二種:0xFF 的 XOR 字元 運算方式。其實只是個簡單運算,如將 0x01 作一下和0xFF的 XOR 運算,那麼得到的結果為0xFE,反之0xFE再作一次 0xFF的XOR 運算則得到 0x01的值。
下面這個範例程式則是將所有的字元都作了一下0xFF的XOR 運算。
<?php
class String2
{
public static function encode ($str)
{
$len = strlen($str);
for ($i = 0; $i < $len; $i ++) {
$word .= chr(ord($str[$i]) ^ 0xff);
}
return $word;
}
public static function decode ($str)
{
return self::encode($str);
}
}
$str = "PHP: Hypertext Preprocessor";
echo $str = String2::encode($str);
echo "\r\n";
echo String2::decode($str);
?>
輸出結果:
窈級葽????蒍?????
PHP: Hypertext Preprocessor
其實這個應用並不是只有對0xFF作XOR運算,而是用資料最大字元,這邊使用0xFF是因為所有字元最大的是0xFF,而再設計時,可以稍為調整一下,會得到不一樣的結果。
第三種:字元移位方式。這個方式其實是將字元值往前推或往後推幾位數。如將 a 往前推兩位則變為c,b則便為d。下面的程式範例則是依照這個觀念設計:
<?php
class String3
{
private static $shift = 0x02;
public static function encode ($str = "")
{
$len = strlen($str);
for ($i = 0; $i < $len; $i ++) {
$chr = ord($str[$i]);
$chr = ($chr + self::$shift > 0xff)
? $chr + self::$shift - 0xff
: $chr + self::$shift;
$word .= chr($chr);
}
return $word;
}
public function decode ($str)
{
$len = strlen($str);
for ($i = 0; $i < $len; $i ++) {
$chr = ord($str[$i]);
$chr = ($chr - self::$shift < 0x00)
? $chr - self::$shift + 0xff
: $chr - self::$shift;
$word .= chr($chr);
}
return $word;
}
}
$str = "PHP: Hypertext Preprocessor";
echo "\r\n";
echo $str = String3::encode($str);
echo "\r\n";
echo String3::decode($str);
?>
這個範例是字元往前移動的範例,我們可以看到 String3這個類別內的encode這個方法作了一些處理,當字元移位後值超過0xFF,則減掉0xFF,而再decode反解時,則是低於0x00時,要往後開始算。
範例的執行結果:
RJR<"J{rgtvgzv"Rtgrtqeguuqt
PHP: Hypertext Preprocessor
其實整個程式反之可以將String3:decode 當編碼用,而將String3:encode當解碼用。這樣就是將位元往後移的方式。
粗略寫了三個固定字元的編碼方式,希望這篇能讓學弟了解一下加密基礎。但加密也不一定是固定字元的方式。
舉個簡單的例子:將0xFF這個字元作一下位元位移運算子運算,如 0xFF << 0x02 則資料便成0x3FC。但是如果用 0x3FC >> 0x02 則資料又變成0xFF。
總而言之,這些基礎可以交錯應用,就可以作出自己訂的文件加解密規則囉。
沒有留言:
張貼留言
我的意見