在密碼學中,Encode、Encrypt、Hash 可以說是三大基礎概念,並且也是後端工程師必備的密碼學知識,因此這篇文章就會詳細來介紹什麼是 Encode、Encrypt、Hash,以及比較他們之間的區別。
本文為 JWT 系列文之一,如果你對 JWT 的其他文章有興趣,也可以直接點擊下列連結跳轉到該文章(不過建議還是按照順序閱讀,才會有最佳的閱讀體驗):
在密碼學中有三大概念,分別是:
以下分別介紹如何透過這三種不同的方法,去對數據做不同的處理。
所謂的 Encode(編碼),就是「數據可以直接被編碼」,並且中間「不需要」任何的密鑰參與。
像是在下面的例子中,左邊的原始字串 123,就可以被 Encode(編碼)成右邊的 gg2oGVzdD,而右邊的 gg2oGVzdD,他也是可以直接被 Decode(解碼)回原始的字串 123 的。
因此在 Encode 和 Decode 的過程中,是不需要任何的密鑰,「所有人」 都可以輕易的 Encode 和 Decode。

而一般在實務上,最常見的 Encode 演算法為「Base64」,像是在這個 Base64 Encode 的網站中,只要在上面輸入 test123,下面就會出現 Encode 過後的結果 dGVzdDEyMw==。

而這時如果大家複製一下下方的結果 dGVzdDEyMw==,然後點擊左邊的 Decode 連結(跳轉到 Decode 的頁面),然後將剛剛的結果 dGVzdDEyMw== 貼在上面的話,這時候就可以直接將這個結果 Decode 回原始的字串 test123。

所以對於 Encode 和 Decode 來說,他們完全不需要密鑰的參與,也可以對數據進行「編碼和解碼」,因此所有人都可以針對某一筆數據進行 Encode 和 Decode。
也因為如此,大家在使用 Base64 去 Encode 數據時,一定要注意這個數據是沒有被加密過的,所以所有人都有能力將他 Decode 回原始的字串!!一定要小心!!!
所以下次當你看到有人在網路上隨意散播使用 Base64 Encode 的數據時,你完全可以大膽的將他 Decode,就可以得到原始的字串,因此千萬不要再誤解 Base64 很安全了🥹,他真的就只是一個編碼的工具而已,完全沒有任何加密的成分在裡面!
補充:Encode 其實嚴格上來說不算加密,因為他只是改變數據的呈現方式,完全沒有加密可言,但口語上有時候還是會把 Encode 歸類成加密,因此才放在這裡一起介紹。
了解了 Encode 之後,接下來我們可以來看一下 Encrypt 的相關介紹。
所謂的 Encrypt(加密),就是「將數據加密成密文」,所以透過 Encrypt 加密過後的數據,他可以說是非常安全的。
而在 Encrypt 的世界中,又可以再細分成兩種加密方式,分別是:
所以以下針對這兩種加密方式來介紹。
在對稱加密中,只會有「一把」密鑰存在,因此不論是加密還是解密,就統統是用這把密鑰來進行。
舉例來說,左邊的原始的字串 123,他就可以透過這把密鑰(或是簡稱為這把 key),加密成右邊的 gg2oGVzdD,而右邊的 gg2oGVzdD,他也可以透過這把密鑰,解密回原始的字串 123。
所以在對稱加密中,就只會存在「一把」密鑰,因此不管你是要加密還是解密,統統就是透過這把密鑰進行。

也因為在對稱加密中只有一把密鑰存在,所以這把密鑰必須要好好的保護,絕對不可以洩漏,一但密鑰洩漏,駭客就可以透過這把密鑰解密出原始的字串,因此在對稱加密中,保護密鑰是非常重要的任務!
而不同於對稱加密,在非對稱加密中,則是會有「兩把」密鑰存在。
在這兩把密鑰中,其中一把會叫做「公鑰」(也就是 Public Key),另一把則叫做「私鑰」(也就是 Private Key),因此在非對稱加密中,就是由「公鑰」和「私鑰」共同配合,對數據進行加密和解密。
所以這兩把密鑰,他們的特性如下:
並且在非對稱加密中,有一個很神奇的運作邏輯,也就是:
所以換句話說的話,就是 「由其中一把鑰匙所加密的數據,只能夠用另一把鑰匙來解密」,這就是「非對稱加密」的運作方式。

也由於非對稱加密的神奇特性(其中一把加密的數據,只能用另一把解密),所以在 JWT 中的「數位簽名」,實際上就是用非對稱加密所實作的。甚至不止 JWT,像是區塊鏈中的數位簽名,他背後也是用非對稱加密實作的(不如說只要是扯到「數位簽名」或是「數位簽章」這個概念,底層都是同一套,都是用非對稱加密實作)。
所以在了解 JWT 的「數位簽名」是如何實作的之前,建議大家一定要先了解「非對稱加密」的運作邏輯(也就是其中一把加密的數據,只能用另一把解密),這樣子後續在了解 JWT 的相關知識時,才能夠知道他底層的運作邏輯為何。
在了解了 Encrypt 中的「對稱加密」和「非對稱加密」之後,最後我們也可以來看一下 Hash 的相關介紹。
所謂的 Hash(雜湊),就是「單方面的將數據轉換成亂碼(或稱為 Hash Value,雜湊值)」,並且這個 Hash Value,他是「不能夠」轉換回原始的字串的。
舉例來說,左邊的原始字串 123,他可以被 Hash 成右邊的亂碼 gg2o861kdn5(又稱為 Hash Value,雜湊值),但是我們卻沒辦法將右邊的亂碼 gg2o861kdn5,轉換回原始的字串 123。

所以在 Hash 的世界中,所有的數據只要被 Hash 過,就再也沒辦法轉換回原始的數據,就算老天來也沒用,世界上沒有人(包含駭客和你自己)有能力將 Hash Value 轉換回原始的數據。
從根本的邏輯上,只要一個數據被 Hash 過,那我們是真的沒有辦法將這個數據轉換回原始的字串,但是!!駭客就想到一招破解的方式:「既然我沒辦法將數據轉換回來,那我乾脆提前做一張很大很大的表格,提前記錄 什麼樣的數據 會轉換成 什麼樣的亂碼 不就好了?」
舉例來說,駭客可以提前計算出 123 這個字串會被 Hash 成 gg2o861kdn5、456 這個字串會被 Hash 成 aaaa777k3nt…等等的結果。因此當駭客發現某一筆被 Hash 過的值是 aaaa777k3nt 時,駭客就只要回來查詢這張表格,就可以馬上找出 aaaa777k3nt 的原始字串是 456,因此就可以用這張很大的表格,來破解被 Hash 過後的值。
| 原始字串 | Hash 過的值 |
|---|---|
| 123 | gg2o861kdn5 |
| 456 | aaaa777k3nt |
因此像是常見的 Hash 演算法「MD5」,駭客就已經透過 「彩虹表(Rainbow Table)」 反向破解出他的所有可能組合了,因此在實務上,建議大家選擇更可靠的 Hash 演算法(像是 BCrypt)來實作,才能夠避免駭客的攻擊。
即使 MD5 已經被駭客的「彩虹表」給反向破解了,但實際上我們還是可以透過一個簡單的補強方法,來強化 Hash 的安全性,這個做法就叫做 「加鹽(salting)」。
所謂的加鹽,就是「偷偷在原始的字串中插入一段亂碼」,然後再把這整個字串拿去 Hash,等於是我們為原始的字串偷加了一點調味料(鹽巴),讓他變得不太一樣。
舉例來說,我們就可以在原始的字串 123 中,偷偷加上一點鹽巴 ND3dmEyMzQxM,這樣最後 Hash 出來的結果就會不一樣。

而這種加鹽的做法之所以可以反制駭客,有兩個原因:
12ND3dmEyMzQxM3,但是駭客也不知道「到底哪一個字母是我們偷加的鹽巴」、「哪一個字母是原始的字串」,因此即使駭客看著手上的 12ND3dmEyMzQxM3 字串時,他也不知道其中的 123 才是真實的原始字串。所以透過「加鹽(salting)」的方式,我們就能夠大大的提升了 Hash 的安全性了!讚!
補充:現今流行的 Hash 演算法(ex: BCrypt),通常都會自帶加鹽的實作,因此不需要我們再額外手動去為他加鹽,為我們節省許多開發的時間,太讚啦!!
所以總和上述的介紹,最後來總結一下 Encode、Encrypt、Hash 這三大概念的話:

所以透過這張表格,希望能夠讓大家更了解 Encode、Encrypt 和 Hash 他們之間的差別在哪裡,因此大家後續在使用上,就可以根據自己的需求,決定哪一種方式是最適合你的實作方法了。
補充:本文是擷取自我開設的線上課程「資安一把罩!Spring Security 零基礎入門」的內容,如果你想了解更多的資安內容、以及如何應用 Spring Security,歡迎參考課程簡介 (輸入折扣碼「HH202509KU」即可享 85 折優惠)。
這篇文章我們介紹了 Encode、Encrypt 以及 Hash 的差別,這三大概念可以說是密碼學的基礎,也是後端工程師必備的密碼學知識,因此建議大家一定要好好了解會比較好!
如果你對後端技術有興趣的話,也歡迎免費訂閱《古古的後端筆記》電子報,每週二為你送上一篇後端技術分享,那我們就下一篇文章見啦!
本文為 JWT 系列文之一,如果你對 JWT 的其他文章有興趣,也可以直接點擊下列連結跳轉到該文章(建議按照順序閱讀,才會有最佳的閱讀體驗):