Skip to content

2026-08-10

/ 15 分鐘閱讀

/ Full Stack Fundamentals

SHA256 與 Salt:為什麼密碼雜湊一定要加鹽,以及雜湊在勒索軟體與加密貨幣的應用

上一篇用 OpenSSL 示範了 MD5 雜湊,也解釋了為什麼同樣的輸入永遠得到同樣的輸出,讓 MD5 很容易被彩虹表攻擊破解。這一節延續同一個實驗,換成強度更高的 SHA1、SHA256,並帶出真正能防堵彩虹表攻擊的關鍵技巧:Salt(加鹽)。

SHA1 與 SHA256:更長的雜湊值,更高的破解成本

延續上一篇用 OpenSSL 對同一個 foo 檔案做雜湊的示範,換成 SHA1:

bash
openssl sha1 foo

MD5 的輸出大約 33 個字元,SHA1 則長達 41 個字元,代表的熵(entropy,隨機程度)明顯更高。但問題還是一樣:只要輸入相同,全班每個人跑出來的 SHA1 雜湊值依然完全相同,一樣可以做成彩虹表,只是儲存這張表所需要的空間會變大。

接著換成目前的黃金標準 SHA256:

bash
openssl sha256 foo

SHA256 的輸出長達 65 個字元。雜湊值越長,建立彩虹表所需要的儲存空間就會呈爆炸性成長,破解難度也隨之大幅提高。但即使用了 SHA256,只要沒有額外處理,同一組密碼的雜湊值依然是固定不變的,仍然稱不上真正安全,常見的密碼變化模式(例如 p@sswordpassword123)一樣可以被收錄進雜湊字典裡。

Salt:讓雜湊值不再可預測

真正能解決「同輸入同輸出」這個根本問題的做法,是加鹽(Salt)。Salt 就是一個隨機數字或隨機雜湊值,對每一次雜湊運算而言都是獨一無二的:把原始輸入和這個隨機的 Salt 一起丟進雜湊函式運算,得到的結果就叫做加鹽雜湊(salted hash)。

以密碼 foo 為例,先附加一個隨機數字再送進 SHA1 運算,得到的雜湊值就會變得完全無法辨識,而且這個過程幾乎不會增加多少運算成本,仍然使用同一套加密雜湊演算法,卻讓任何人都不可能事先建好一份彩虹表,因為每一筆資料的 Salt 都不一樣。

這也是密碼學雜湊(cryptographic hash)跟一般雜湊函式的差異所在:一般雜湊函式只要知道輸入或所用的演算法,往往就能被反推回去(MD5 正是因為容易被反推而不再安全),而 Salt 的隨機性正是讓雜湊結果無法被反推的關鍵。

Salt 通常會存在資料庫裡保存下來,這樣使用者登入時才能用同一組 Salt 重新計算雜湊值,拿去跟資料庫裡儲存的雜湊值比對。存放 Salt 的資料庫本身通常也會加密,並對其中的內容再做一層雜湊,形成層層防護;即使真的有人拿到伺服器的 root 權限,直接側錄網路封包往往還比硬碰硬破解雜湊資料庫更容易,但這不代表 Salt 就不重要。

常見的密碼儲存錯誤

明明只花幾分鐘就能示範清楚密碼雜湊的必要性,但仍然有公司直接把密碼存成明文,完全不做任何雜湊處理。另一種常見的錯誤心態是「只要 MD5 雜湊很多次就安全了」,例如把同一組密碼反覆 MD5 十次;但這種做法對電腦來說同樣輕而易舉就能破解,並不會因為多雜湊幾次就變得安全。

真正安全的做法,是搭配一組強健、難以破解的加密雜湊函式,並為每一位使用者各自產生獨一無二的 Salt。就算資料庫真的外洩,攻擊者拿到的也只是一堆看似隨機的亂碼,因為他們並不知道每一筆資料對應的 Salt 是什麼,也就無法反推回原始密碼。隨著愈來愈多基礎設施都建立在網路應用程式與伺服器之上,安全始終是最需要優先關注的一環。

為什麼不要自己寫雜湊演算法

千萬不要自己動手設計加密或雜湊演算法。位元位移、加入某個「神奇數字」之類的手法,表面上看起來輸出很隨機,但這類問題背後牽涉到橢圓曲線密碼學(elliptic curve cryptography)等高度專業的數學領域:所有數學函式背後都遵循某種規律性,只要把一個雜湊函式的輸出跑得夠多次,就有機會看出隱藏在裡面的曲線與規律,進而被反推破解。人類與電腦其實都不擅長產生真正的隨機性,一切終究是可預測的,這也是隨機性本身之所以是一個困難問題的原因。正因如此,密碼雜湊應該永遠交給像 SHA256 這種已經被廣泛驗證過的標準演算法,而不是自己發明一套。

Bcrypt 是另一個常見的密碼雜湊演算法,底層採用 Blowfish 加密演算法。SHA256 目前仍是最主流、最廣為人知的加密雜湊標準。

MD5 仍然有用的場合:檔案驗證

雖然 MD5 不再適合用來儲存密碼,但它在驗證檔案完整性上仍然很實用。無論檔案大小為何,MD5 都會把內容壓縮成固定長度、大約 33 個字元的雜湊值;只要比對雙方各自計算出的 MD5 值是否一致,就能確認檔案在傳輸過程中沒有被竄改過。開源專案經常會附上檔案的 MD5 雜湊值,讓使用者下載後可以自行比對驗證。

這種驗證機制也牽涉到軟體供應鏈的安全性:從下載一個套件、到把它跑在伺服器上的每一個環節都需要被保護。像是知名的 NPM 套件被惡意挾持(hijack)這類事件,攻擊者可能重新發布一個外觀相同、但夾帶惡意流量側錄功能的版本;透過比對 MD5 雜湊值,就能確認拿到的檔案確實是作者原本發布的版本,而不是遭到竄改的版本。

不過 MD5 因為長度只有 33 個字元,比較容易發生碰撞(collision):也就是能刻意製造出另一個內容不同、卻擁有相同 MD5 雜湊值的檔案。相較之下,SHA1 發生碰撞的機率極低,SHA256 則幾乎不可能發生碰撞。這也是雜湊演算法選擇上的取捨:MD5 運算速度快,SHA256 運算較慢但安全性高出許多。

雜湊的其他應用:加密貨幣與勒索軟體

雜湊技術也是加密貨幣運作的核心:比特幣(Bitcoin)使用 SHA256,透過解出雜湊謎題來獲得比特幣獎勵;以太坊(Ethereum)則使用一種叫 Keccak-256 的演算法,雖然常被稱作 SHA3,但嚴格來說並不完全等同於 SHA3(因為 SHA3 本身並未被視為具備足夠的密碼學安全性),使用時最好還是稱它為 Keccak,以免引起以太坊社群的不滿。

勒索軟體(ransomware)也是建立在雜湊技術之上的惡意應用:它並不是把資料搬到別的目錄再加上密碼保護,而是直接把使用者的檔案跑過雜湊函式,變成一大段看似亂碼的內容,再刪除原始檔案,只有攻擊者自己握有還原用的 Salt 與金鑰。正因為背後用的是真正具備密碼學安全性的雜湊技術,勒索軟體才會如此難以破解、危害如此嚴重,而勒索軟體的興起與加密貨幣的普及之間也存在著明顯的關聯,因為加密貨幣讓贖金可以匿名支付。

複習

MD5、SHA1、SHA256 在雜湊長度上有什麼主要差異?

MD5 大約產生 33 個字元,SHA1 產生 41 個字元,SHA256 產生 65 個字元。雜湊值越長,代表的熵越高,也讓彩虹表攻擊需要的儲存空間隨之大幅增加,破解難度也隨之提升。

什麼是密碼學雜湊中的 Salt?

Salt 是在雜湊運算前加入輸入資料的隨機數字或隨機雜湊值,能讓每一次雜湊運算的結果都獨一無二,防止攻擊者建立彩虹表。Salt 必須被儲存下來(通常存在資料庫裡),這樣之後驗證密碼時才能套用同一組 Salt 重新計算,每位使用者都應該擁有各自獨立的 Salt,才能發揮最大的安全效果。

MD5 雜湊有哪些實際的應用場合?

MD5 適合用來驗證檔案完整性,讓使用者可以確認下載到的檔案內容與原始檔案一致、沒有被竄改過。

加密貨幣(如比特幣、以太坊)如何運用雜湊技術?

比特幣使用 SHA256 來解出雜湊謎題以換取獎勵;以太坊則在區塊鏈驗證過程中使用 Keccak-256(常被稱作 SHA3,但嚴格來說並不完全相同)。

小測驗

在密碼學雜湊的脈絡下,什麼是彩虹表? 針對常見密碼預先計算好的雜湊值對照表
MD5 這類雜湊函式有哪個與資安無關的實用場合? 透過比對檔案雜湊值來驗證檔案完整性

此文章是 FrontendMasters 上的 Full Stack Fundamentals, v3 課程筆記

最後更新時間:

Buy Me A Coffee
0 %
MIT Licensed | Copyright © 2025-present Wen-Hsiu's Blog
Photo by Federica Galli on Unsplash