在密碼學中,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,歡迎參考課程簡介 (輸入折扣碼「HH202501KU」即可享 85 折優惠)。
這篇文章我們介紹了 Encode、Encrypt 以及 Hash 的差別,這三大概念可以說是密碼學的基礎,也是後端工程師必備的密碼學知識,因此建議大家一定要好好了解會比較好!
如果你對後端技術有興趣的話,也歡迎免費訂閱 《古古的後端筆記》電子報 ,每週二為你送上一篇後端技術分享,那我們就下一篇文章見啦!
本文為 JWT 系列文之一,如果你對 JWT 的其他文章有興趣,也可以直接點擊下列連結跳轉到該文章(建議按照順序閱讀,才會有最佳的閱讀體驗):