Image for post
Image for post

一次搞懂密碼學中的三兄弟 — Encode、Encrypt 跟 Hash

Larry Lu
Larry Lu
Mar 23 · 10 min read

前言

隨著資訊安全越來越受到使用者的重視,密碼學作為資訊安全的基石也逐漸變成開發人員的必修課,所以筆者我今天就要來說說密碼學中大家很容易搞混的三個東西:編碼(Encode)、加密(Encrypt)跟雜湊(Hash)

雖然他們三者的比較已經很多人寫過了,但還是有些人搞不清楚,所以這篇決定換個方式:不提太多理論,而是舉大量的例子跟實際應用,如果這些例子你都能看懂,那自然就會知道三者的差別

編碼(Encoding)

首先來看看最簡單的編碼,所謂的編碼並不會修改資料、也沒有任何加密的效果,單純就是 換個方式來表達資料 而已,其中最有名的例子就是摩斯密碼

Image for post
Image for post

在摩斯密碼的編碼系統中,每個英文字母都可以被表示成點(dot)跟劃(dash)的組合,或是表示成長音跟短音,譬如說將 Hello World 編碼(encode)成摩斯密碼的形式就是 .... . .-.. .-.. --- .-- --- .-. .-.. -..

雖然這串東西乍看之下很難懂,但 只要知道摩斯密碼的轉換規則 就有辦法翻譯回來,所以編碼 完全沒有安全性可言,就只是 換個方式來表達資料 而已

實例

在 JavaScript 中有兩個很實用的 function 分別是 encodeURIdecodeURI,他們是用來把網址中的特殊字元(空白、標點符號等等)編碼成符合 URL 的格式(轉完變超醜的)

譬如說 https://www.google.com/search?q=創世神 這段網址會被編碼成 https://www.google.com/search?q=%E5%89%B5%E4%B8%96%E7%A5%9E,所以即便電腦不支援顯示中文,或是某些比較舊的瀏覽器無法貼中文網址,也還是可以透過編碼後的網址連到目標網站

Base64 是一種可以把二進位的資料編碼成 ASCII 字元的方法,如果你想在純文字的介面上傳送圖片給朋友,可以先用指令 cat hello.png | base64 把圖片編碼成 Base64 格式,然後把生出來的這一大串東西傳給他

Image for post
Image for post

你的朋友收到 這團看起來像是亂碼的東西 後,只要用 Base64 進行 decode 就可以收到原本的圖片了:echo {那一大串} | base64 -D > image.png

Image for post
Image for post

為了讓編碼後的那一大串能顯示在一個螢幕之內,我用的圖片畫質很差,請不要介意 XD

雖然這團東西看起來像亂碼,但他是沒有任何安全性的,熟悉 Base64 的人很快就能解碼回來,頂多只能騙騙你那不懂電腦的老媽XD

霍夫曼編碼(Huffman Coding)是一種用來進行 無失真壓縮 的編碼演算法,說穿了他的概念就是把常用的字記成縮寫,從而降低資料量、達到壓縮的效果

如果還是覺得有點抽象的話,可以想想你去早餐店跟阿姨點餐時:

我要 “一個雞腿堡加蛋“ 跟 “大杯的冰紅茶”

因為阿姨腦中有一個早餐縮寫的對照表,所以在你講的同時阿姨就會快速在紙上記下 “G堡蛋、大冰紅”,這就是壓縮技術的原理:把常出現的字用縮寫記錄下來,等日後要解壓縮時再還原回去

加密(Encrypt)

加密跟剛說到的編碼有點像,唯一不同之處是加密跟解密必須要有金鑰(Key)才能進行。以最簡單的 凱薩加密法 來說,他加密的方式就是把每個英文字母加上一個 偏移量,這個偏移量就是用來執行加解密的 Key

Image for post
Image for post

假如我想要用凱薩加密法對 Hello World 進行加密,並且設定 key=3,那加密完的結果就會變成 Khoor Zruog,只有知道 key 的人才有辦法把 Khoor Zruoog 還原回去 Hello World

說是這麼說,但你我都知道英文字母不就那 26 個嗎?照目前電腦的運算速度,只要把偏移量從 0 到 25 都算過一遍,即便我不知道 key 也可以很容易就看出偏移量是 3

Image for post
Image for post

所以說凱薩加密法非常不安全,他最大的用處應該就是在課堂上傳紙條,但又不想被中間的同學看懂(我就幹過這種事XD),除此之外在現代已經沒什麼用處了

實例

AES (Advanced Encryption Standard) 是一種對稱加密演算法,所謂的對稱就是說加密解密 都是用同一個 key,這點跟上面說到的凱薩加密法一樣,但 AES 不像凱薩的 key 只有 0–25 這麼少種,而是可以有超過 10³⁸ 種,所以安全性比凱薩高非常非常多

除了安全性高不易被破解之外,AES 加密檔案的速度也非常快,所以被美國政府用來加密機密檔案。如果你也想用 AES 來加密 D 槽裡面那些神秘檔案,可以試試系統內建的 OpenSSL

加密:openssl aes-256-cbc -in <input> -out <output>,輸入密碼(Key)加密後會變成一團醜不拉嘰的亂碼,完全不知道從何破解起,不像凱薩加密完還是英文字母,一下子就猜到了

Image for post
Image for post

要解密時就同樣的指令加個 -d,輕輕鬆鬆

Image for post
Image for post

但如果你不小心忘記密碼,那就真的 gg 了,因為 AES 加密後的檔案即便用超級電腦來破解,也要超過十億年,更不用說用你的電腦了XD

AES 又快又安全,聽起來超厲害對吧?但他這類 對稱式加密法 有一個缺點:就是如果你想把加密後的 文字/檔案 傳給你的秘密情人 Alice,兩個人就必須先講好密碼是什麼,這樣你傳過去她才用你設的密碼解密

但因為網路環境是不安全的(尤其是在有 HTTPS 之前),所以除非你把 Alice 當面約出來講密碼是什麼,不然只要是透過網路把密碼傳給對方,就有機會被中間人拿走

一旦中間人拿到密碼,那你用再強的加密演算法都沒有用。而且比起完全沒加密,更恐怖的是明明密碼已經被偷走了,你還自以為檔案有加密就超安全,真的怎麼死的都不知道

為了解決上述的問題,於是就有了非對稱加密法,其中最有名的就是 RSA

RSA 這類非對稱加密法有個很特別的地方,就是他會產生一組兩個 Key 分別叫公鑰(Public Key)跟私鑰(Private Key),而且 用公鑰加密的內容只能用私鑰解(超神奇的!!!)

同樣的情況當你要傳檔案給 Alice,就先請 Alice 生一組 Key 然後把公鑰傳給你。你有了 Alice 產生的公鑰之後,就用公鑰幫檔案加密再傳給她,Alice 收到就可以用她自己手上的私鑰解開(這段比較難,可以多看幾遍)

安全性方面,因為私鑰從頭到尾都在 Alice 手上,完全沒有傳出去過,所以即便中間人取得公鑰加密後的檔案也沒辦法解開,超安全 der

雜湊(Hashing)

接著是最後一個:雜湊,不知道大家有沒有注意過你的身分證字號,他的最後一碼其實是個驗證碼哦,他是前九碼根據 某個公式 計算出來的

M140051653 這個身分證字號來說,計算的方式是先把 M 轉換成對應的數字 21,接著根據下圖的方式進行計算,如果算出來剛好等於最後一碼,那代表這個身分證字號是合法的

Image for post
Image for post

這種把各個 欄位/字元 丟進去某個公式計算的方式就叫做雜湊(Hash),而這個計算公式就稱為 雜湊函數(Hash function),過程可能會做各種加減乘除,最後算出一個值或字串

因為最後一個數字 3 是經由前幾個數字計算、濃縮出來的,所以理所當然不可能由雜湊後的結果 3 回推出前幾個數字分別是什麼,所以雜湊的過程是 不可逆的

實例

如果你想驗證某兩個檔案的內容是否相同,可以使用 md5 來計算檔案的雜湊值,他會使用某個 hash function 根據檔案內容 計算出一個長度 128 bit 的雜湊值,若是兩個檔案內容不同就會計算出不同的 hash value

其實有很低的機率(1/2¹²⁸)會產生碰撞,造成不同檔案有相同的 hash value,但因為機率太小一般情況下可以忽略

Image for post
Image for post

如上圖,從雜湊值可以看出 data1 跟 data2 的雜湊值是相同的,也就代表他們的檔案內容有很高機率一樣,而 data2 跟 data3 的雜湊值不同,代表他們的內容一定不一樣

如果你開發過前端的話應該會發現,在你要使用 bootstrap 或 jquery 這類第三方 library 時,官方都會提供一個 integrity 屬性,那個就是 library 程式碼經過 SHA-2 演算法 hash 的結果

Image for post
Image for post

這樣子做有個好處,因為使用 bootstrap 的網站太多了,如果有天很不幸官方提供的 bootstrap.js 網址被駭客偷換成惡意程式碼,就會有很多網站遭殃

但有了 hash 之後,因為不同的程式碼會導致不同的 hash value,所以瀏覽器看到就不會載入怪怪的 bootstrap.js,只因為他的 hash 結果跟原本的不一樣

大部分網站的後端資料庫都不會直接儲存使用者的密碼,因為那樣太危險了,取而代之的是儲存密碼的雜湊值

當使用者嘗試要登入時,只要將使用者輸入的密碼進行雜湊,再跟資料庫裡面的雜湊值比對就可以了。只要輸入的密碼是正確的,用同一個公式進行計算必定會得到相同的結果

安全性方面,因為雜湊值無法反推回原密碼,所以即便有一天資料庫不小心洩漏出去了,駭客還是拿不到使用者的密碼,只能拿到密碼的雜湊值

關於如何安全的儲存使用者密碼,可以看我另一篇「聽說不能用明文存密碼,那到底該怎麼存?」會有更詳細的解說

重點整理

看到這相信大家都已經累了,怕大家看到後面就忘了前面,所以再條列一下他們三個的重點

  • 只是換個方式表達資料
  • 不需要 Key 即可解碼(不安全)
  • 用 Key 來保護資料的機密性
  • 加密跟解密都需要 Key
  • 把資料丟進一串公式計算出一個結果
  • 無法反推回原字串

總結

相信大家都了解編碼、加密跟雜湊的不同了,因為他們三者各有優缺,適用的情境也不太一樣,所以實務上常常各取所長把他們混在一起用

譬如說壓縮檔加密就同時用到編碼跟加密、JWT(JSON Web Token)用到編碼跟雜湊、HTTPS 的實現則是用到加密跟雜湊…

像這樣的例子還有很多,他們三者相輔相成才有了現在流行的各種認證機制,很多聽起來很神奇、很安全的功能其實背後都是他們在撐,所以說他們是網路安全的基石也不為過吧!

Starbugs Weekly 星巴哥技術專欄

一群技術人想寫出一些好文章,所建立的技術專欄。每週二會發佈技術週刊,分享科技新知,歡迎大家訂閱…

Larry Lu

Written by

Larry Lu

我是 Larry 盧承億,傳說中的 0.1 倍工程師。我熱愛技術、喜歡與人分享,專長是 Javascript 跟 Go,平常會寫寫技術文章還有參加各種技術活動,歡迎大家來找我聊聊技術~

Starbugs Weekly 星巴哥技術專欄

一群技術人想寫出一些好文章,所建立的技術專欄。每週二會發佈技術週刊,分享科技新知,歡迎大家訂閱 https://weekly.starbugs.dev/。

Larry Lu

Written by

Larry Lu

我是 Larry 盧承億,傳說中的 0.1 倍工程師。我熱愛技術、喜歡與人分享,專長是 Javascript 跟 Go,平常會寫寫技術文章還有參加各種技術活動,歡迎大家來找我聊聊技術~

Starbugs Weekly 星巴哥技術專欄

一群技術人想寫出一些好文章,所建立的技術專欄。每週二會發佈技術週刊,分享科技新知,歡迎大家訂閱 https://weekly.starbugs.dev/。

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store