在密碼學裡有所謂的編碼( Encode )、加密( Encrypt )跟雜湊( Hash ),他們有甚麼不一樣呢?
編碼( Encode )
摩斯密碼
摩斯密碼最早是山謬·摩斯發明的( Sammuel Morse ),他一開始的構想的利用特殊密碼本或字典來加密訊息,目的不是要隱藏內容,而是要讓訊息發送更簡便迅速。而我們現在熟知的摩斯電碼是經過佛里德克希·克烈門斯·格爾克( Friedrich Clemens Gerke )改良,以簡短的點與底線來把最常用的字母代碼縮短。
假如今天收到一份摩斯密碼.... ..
,那你可以很快翻譯出來是HI
htmlspecialchars
html 裡設計了一些特殊符號的編碼來防範 xss 的攻擊,舉例來說,下面這一段程式碼
<?php
echo '<a href=\"#\">Test Link</a>';
echo '<br>';
$Str = htmlspecialchars("<a href=\"#\">Test Link</a>",ENT_QUOTES);
echo $Str;
?>
最後會輸出這樣的結果
Test Link
<a href="#">Test Link</a>
如果檢查網頁原始碼,可以發現是這樣子的
<a href=\"#\">Test Link</a><br><a href="#">Test Link</a>
htmlspecialchars 會將敏感的字元像是>
、<
以及單雙引號等加以編碼,html 看到這些編碼就知道是僅供閱讀的符號。( 這個例子裡雙引號使用\
跳脫所以沒有被編碼 )
霍夫曼編碼
霍夫曼編碼( Huffman Coding )是一種用來進行無失真壓縮的編碼演算法,原理是把常用的字記成縮寫,所以可以達到壓縮資料量讓傳輸更快的效果。
總結一下甚麼是編碼,從上面的例子不難看出編碼沒有安全性可言,但他可以達到省時、跳脫 等等的效果。
加密( Encrypt )
加密跟編碼有一點相似,不過就算知道了使用甚麼加密法,還需要有金鑰( key )才可以解碼。
密碼棒
史書裡最早記載的換位式密碼使用「密碼棒」( scytale ),一組密碼棒包含兩根圓木棒,尺寸要一模一樣。送訊息時,送信者把一條長長的羊皮紙緊緊纏繞在木棍上,然後沿著木棒的長軸寫下訊息,這樣一來打開信紙有一串不相干的字,只有另一個擁有密碼棒的人將羊皮紙纏上才能讀取內容。
AES
AES( Advanced Encryption Standard )也是一種對稱式加密法,也就是說加密者與解密者都使用同一把金鑰,AES 可能的金鑰數量達到 10 的 38 次方的數量級,所以安全性相當的高。但是對稱性加密法都有共通的問題,如果在雙方交換金鑰的時候被攔截,那不管是多安全的對稱式加密法都會破功。而 HTTPS 協定就是根據這個漏洞去做了改良。
非對稱加密法
非對稱加密法可以產生一組公鑰( Public Key )跟私鑰( Private Key ),用公鑰加密的內容只能用私鑰解開。
假設我要傳訊息給 A,A 生成一組公鑰跟私鑰,並將公鑰傳給我。我把鑰傳遞的訊息用這把公鑰加密以後,再傳給 A,這時候 A 用私鑰解開訊息內容就可以了。就算有中間人攔截到了公鑰以及被公鑰加密的訊息,也無法解碼。 如果有興趣瞭解可以搜尋著名的非對稱式加密法RSA
。
雜湊( Hashing )
身分證字號
台灣的身分證的最後一碼是透過雜湊函式來給定的,算法像下面這樣
(1) 第一個字元代表地區
A | B | C | ... | Z |
---|---|---|---|---|
10 | 11 | 12 | ... | 33 |
(2) 第二個字元代表性別, 1 代表男性, 2 代表女性
(3) 第三個字元到第九個字元為流水號碼。
(4) 第十個字元為檢查號碼。
(5) 檢查碼的產生規則是將身分自字號的每一個位數乘上權數後之積相加,權數依序為 1、9、8、7、6、5、4、3、2、1
(6) 相加後之值除以模數 10 取其餘數
(7) 最後由模數減去餘數得檢查號碼,若餘數為 0 時,則設定其檢查碼為 0
所以 F123456789 並不是一組合法的身分證字號,F123456784 才是。
雜湊函式厲害的地方在於就算你知道算法也推不回去,像身份證字號的案例可以寫成 10- (A + 9B + 8C + 7D + 6E + 5F + 4G + 3H + 2I + J)%10 = ANSWER ,這麼多變數要怎麼推阿,10 個變數至少要 10 條方程式才可以找到唯一解,像這種情況只能慢慢湊。
雜湊函式可能會遇到碰撞的問題,也就是可能會有超過一組答案對應到同一個解,至於為甚麼這會是個問題,等等會談到雜湊函式的用途。
驗證檔案是否被竄改
在使用 bootstrap 或 jquery 這些第三方 library 時,官方都會提供一個 integrity 屬性,這個屬性是程式碼經過 SHA-2 演算法雜湊的結果,如果你下載的跟官方的 integrity 值不一樣,那檔案就跟官方的不同。
儲存使用者密碼
後端在儲存使用者密碼的時候,通常只會儲存雜湊後的密碼,這樣一來即使後端被駭也可以保障使用者的密碼不外洩。不過如果有兩組密碼經過雜湊後的值相同,也就是所謂的碰撞,這樣一來這兩組密碼都可以登入同一個使用者,所以選擇雜湊函式時碰撞的機率就是一個很重要的指標了。
加鹽
雖然駭客沒辦法破解雜湊後的密碼,但駭客自己建立起一個常用字串對照雜湊值的表格,網路上還真的有整理一張彩虹表,裡面有許多常用的組合跟對應的雜湊值。
但其實是可以防範的,我們只要給密碼加鹽就可以了。
假設我的密碼原本是 123,後台會自動在密碼後綴 abc,所以後端儲存的密碼是 123abc 雜湊的結果,除非駭客知道加鹽的內容,否則沒辦法靠彩虹表查表。