

會員登入




密碼的加密法-以對稱式加密為例
還記得第一章我們學過的對稱式加密演算法嗎? AES演算法利用一把初始金鑰與明文進行多回合的運算後,產出密文。現在,我們來觀察AES演算法如何成為密碼的守門人!
情況一、 觀察密碼的加密過程,以及加密結果是否能回推為原本密碼。
Alice 想要偷偷對Bob告白,趁著去羅馬旅遊的時候寄出一張上面有「愛神邱比特射箭」圖像的明信片給他。但是 Alice 怕信件會寄到Bob家裡,容易被他的父母發現,因此在寄出前,想嘗試在圖像貼上各種裝飾品隱藏起來。
在此,我們用裝飾明信片圖像來比喻加密過程:
- 「密碼」 ➝ 明信片上的圖像
- 「系統金鑰」 ➝ 明信片上的各種裝飾品
- 「AES 加密演算法」的程序 ➝ 貼上裝飾品的順序
- 「加密結果」 ➝ 完成裝飾的明信片
※「系統金鑰」是隱藏在系統內部,只有製造商才知道,一般系統管理員並不知道。
➢ 操作方法
- 先輸入 HappyCat 的密碼(可以用英文字母、數字或特殊符號組成,最多20個字元)。
- 請點擊一個裝飾品,並按下「裝飾」,蓋住邱比特的圖像。
注意!請根據裝飾品編號由小到大依序裝飾。 - 根據雲朵對話窗的內容,照著建議操作。

編號 | 帳號 | 加密後的密碼 |
---|---|---|
1 | HappyCat | |
*為方便觀察,密碼為直接顯示。

![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |





情況二、 觀察密碼加密後的結果,評估密碼「加密」的安全性。
➢ 操作方法
現在假設你是另外一位使用者 ChubbyDog:
- 請在空白欄位中自行設定 ChubbyDog 的密碼。
- 觀察加密結果如何儲存於資料庫,分析駭客的攻擊手法。
➢ 回答問題
- 若 ChubbyDog 密碼與 HappyCat 相同,資料庫儲存的密碼會和 HappyCat 一樣 嗎?
- 若 ChubbyDog 密碼與 HappyCat 不同,資料庫儲存的密碼會和 HappyCat 一樣 嗎?





前情提要:
有位神通廣大的駭客,已經駭入資料庫,可以看到資料庫裡面的資訊。 幸好先前系統管理員早已透過對稱式加密技術,將系統金鑰與密碼一同加密,只儲存加密後的密碼於資料庫中。
P.S. 以拆解明信片為例,駭客如果要知道明信片上的原始圖像(密碼),必須把裝飾品按照順序拿下(逆推AES演算法),但是駭客在過程中無從得知哪些是裝飾品(系統金鑰),哪些是原始圖示(密碼),因為他們都是圖像。
P.S. 請你按下所有「新增」按鈕,表示駭客新增多組假帳密。
新增完成後,觀察加密後的密碼中,哪一組與ChubbyDog的加密後密碼一樣? 請直接點擊該組「加密後的密碼」,並按下「尋找完畢」,表示駭客已破解密碼。
P.S. 此方法便是所謂的暴力破解法。


編號 | 帳號 | 加密後的密碼 | |
---|---|---|---|
1 | HappyCat | ||
2 | ChubbyDog | ||
*黃底色的儲存格表示駭客創建的帳號密碼。

單向函數的特性 – 以雜湊函數為例
單向函數是指有一個函數F,若給予X,則很快就可計算出Y=F(X),但若僅知道Y,則很難導出X。(還記得我們在第一單元學過的 MD5 雜湊演算法嗎?沒錯! 雜湊函數就是一種單向函數。)
情況一、 複習雜湊函數的特性,觀察雜湊值是否能回推為原本密碼。
在此,我們用攪打果汁來比喻雜湊過程:
- 「密碼」 ➝ 食材(水果)
- 「密碼的雜湊過程」 ➝ 食材的攪打過程
- 「雜湊值」 ➝ 成品(果汁)
➢ 操作方法
- 輸入各種英文字母、數字或符號組成的密碼,最多20個字元。
- 觀察雜湊過程。

編號 | 帳號 | 密碼的雜湊值 |
---|---|---|
1 | HappyCat | |
*為方便觀察,密碼為直接顯示。



情況二、 觀察密碼的雜湊值,評估密碼「透過單向函式進行雜湊」的安全性。
➢ 操作方法
現在假設你是另外一位使用者 ChubbyDog:
- 請在空白欄位中自行設定 ChubbyDog 的密碼。
- 觀察密碼的雜湊值如何儲存於資料庫,分析駭客的攻擊手法。
➢ 回答問題
- 若 ChubbyDog 密碼與 HappyCat 相同,資料庫儲存的雜湊值會和 HappyCat 一樣 嗎?
- 若 ChubbyDog 密碼與 HappyCat 不同,資料庫儲存的雜湊值會和 HappyCat 一樣 嗎?

系統管理員為了提高資料庫的系統安全性,將使用者密碼「透過單向函數轉換為雜湊值」。 此方法既免於保管系統金鑰的困擾,又可以讓駭客難以逆推原始密碼。
P.S. 請你按下所有「新增」按鈕,表示駭客新增多組假帳密。
新增完成後,觀察加密後的密碼中,哪一組與ChubbyDog的加密後密碼一樣? 請直接點擊該組「加密後的密碼」,並按下「尋找完畢」,表示駭客已破解密碼。
P.S. 此方法便是所謂的暴力破解法。


編號 | 帳號 | 密碼的雜湊值 | |
---|---|---|---|
1 | HappyCat | ||
2 | ChubbyDog | ||
*黃底色的儲存格表示駭客創建的帳號密碼。

加鹽後雜湊的特性
我們可以看到,「單向函數法」和「加密法」,兩種方法最後都會陷入「暴力破解」的困境。況且,在「加密法」中,只要駭客擁有系統金鑰,就能逆推原本密碼的樣貌。因此,有一個安全性較高的儲存密碼方式,將使用者密碼「加鹽後雜湊」,並將「密碼的雜湊值」、「鹽巴」儲存於資料庫中,以利於日後的密碼驗證。
情況:觀察加鹽後的密碼雜湊值及鹽巴,評估密碼「加鹽後雜湊」的安全性。
在此,我們用攪打果汁來比喻加鹽後雜湊的過程:
- 「密碼」 ➝ 食材(水果)
- 「鹽巴」 ➝ 調味料
- 「密碼的雜湊過程」 ➝ 食材的攪打過程
- 「雜湊值」 ➝ 成品(果汁)
➢ 操作方法
現在假設你是使用者 ChubbyDog:
- 請在空白欄位中自行設定 ChubbyDog 的密碼。(由英文字母、數字或符號組成,最多20個字元)
- 請在空白欄位中自行設定 ChubbyDog 的鹽巴。(由英文字母、數字或符號組成,因考慮平台效能,最多15個字元)
- 觀察 密碼的雜湊值 及 鹽巴 如何儲存於資料庫,看看駭客是否還能用暴力破解法得知密碼。
➢ 回答問題
假設現在 HappyCat 的密碼是 Cat123,鹽巴為 qo@2@$!jfsr:
- 若 ChubbyDog 的密碼與 HappyCat 相同,但其鹽巴與 HappyCat 不同,資料庫儲存的密碼雜湊值會和 HappyCat 一樣 嗎?
- 若 ChubbyDog 的密碼與 HappyCat 相同,且其鹽巴也與 HappyCat 相同,資料庫儲存的密碼雜湊值會和 HappyCat 一樣 嗎?


編號 | 帳號 | 加鹽後的 密碼雜湊值 |
鹽巴 |
---|---|---|---|
1 | HappyCat | 8064949b36af2bd88f1005ebdc9d7999 | qo@2@$!jfsr |
2 | ChubbyDog | ||


-
鹽巴必須唯一
若不同使用者設定一樣的密碼和鹽巴,那麼加密結果會一樣,這樣就失去了「加鹽」的保護作用了!
所以在密碼學中,必須確保程式隨機產生的「鹽巴」必須是獨一無二的。 -
密碼及鹽巴長度很重要
尤其是鹽巴長度越長,越難進行彩虹表攻擊。
(彩虹表是駭客預先計算好的大型對照表,包含常見密碼及其對應的雜湊值,當鹽巴長度越長,越需要大量計算資源建立彩虹表)

會員註冊(簡易版)
第一步、網頁接收到使用者新增的會員資料後,存入後端資料庫,其中密碼採「加鹽後雜湊」的方式存入資料庫中。
➢ 按下「執行程式」,想一想程式碼如何利用bcrypt函式庫將密碼「加鹽後雜湊」。
# 所以在此引入bcrypt函式庫
import bcrypt
# 將密碼加鹽後雜湊
password = b''
salt = bcrypt.gensalt()
print("Salt:\n", salt)
hashed_password = bcrypt.hashpw(password, salt)
print("Hashed Password:\n", hashed_password)
執行結果:
(b字元作為前綴,表示後面接續的字串是 bytes 型態,以利於處理加密和雜湊等涉及二進位數據的操作。)
第二步、系統管理員將新增的會員資料儲存至資料庫中。
➢ 請將剛註冊的「密碼雜湊值」及「鹽巴」填入資料庫,完成後按下「儲存」,表示儲存成功。

編號 | 帳號 | 加鹽後的 密碼雜湊值 |
鹽巴 |
---|---|---|---|
1 | |||
➢ 回答問題
觀察這次使用bcrypt函式庫做為「加鹽後雜湊」的執行結果,鹽值可能被添加在原始密碼的哪個位置?
會員登入
網頁接收到使用者嘗試登入的帳號密碼後,進入網頁後端驗證密碼正確性。
➢ 請協助將該帳號在資料庫中儲存的「密碼雜湊值」和「鹽巴」分別填入程式碼中。
# 讀取原先在資料庫儲存的「密碼的雜湊值」、鹽巴
salt =
hashed_password =
# 待驗證的密碼
login_password = b''
hashed_password2 = bcrypt.hashpw(login_password, salt)
print("Hashed Password:\n", hashed_password)
print("Hashed Password2:\n", hashed_password2)
if (hashed_password2 == hashed_password):
print("登入成功")
else:print("登入失敗")
執行結果:
(b字元作為前綴,表示後面接續的字串是 bytes 型態,以利於處理加密和雜湊等涉及二進位數據的操作。)

編號 | 帳號 | 加鹽後的 密碼雜湊值 |
鹽巴 |
---|---|---|---|
1 | |||
➢ 想想看
假設登入時輸入錯誤的密碼,程式能否正確判讀呢?為什麼?
試著在上方的登入介面輸入錯誤的密碼吧!