本系列第五篇,聚焦 MySQL 內建單向雜湊加密函數的實測對比,闡述為何 MD5() 是儲存密碼的首選,並示範正確的驗證模式。
四大加密函數實測(輸入 'pa55Word')
| 函數 | 輸出範例 | 長度/特徵 | 備註 |
MD5() | a17a41337551d6542fd005e18b43afd4 | 32 字元十六進位 | 最常用、速度快、碰撞概率低 |
SHA1() | ... (40 字元) | 40 字元十六進位 | 比 MD5 慢,安全性略高,但已不建議用於密碼 |
PASSWORD() | 1d35c6556b8cab45 | 16 字元(舊版)/ 41 字元(4.1+) | MySQL 內部認證專用,**不建議應用層使用**(版本間不兼容) |
ENCRYPT() | up2Ecb0Hdj25A | 基於 crypt(),含鹽值 | 依賴系統 crypt,Windows 不支援,輸出需 CHAR BINARY 存儲區分大小寫 |
為何推薦 MD5(及其現代替代品)
- 單向不可逆:雜湊值無法還原明文,資料庫洩露不直接暴露密碼。
- 驗證模式簡單:
SELECT * FROM users WHERE user=? AND pwd=MD5(?),應用層傳明文,資料庫端雜湊比對,不經網路傳輸明文(若連線加密)。
- 不出現在一般查詢日誌/慢查詢日誌的結果集中(僅出現在 SQL 文本),相對
INSERT ... VALUES (MD5('pwd')) 明文不落盤。
正確的密碼儲存與驗證範例
-- 建表:密碼欄位用 CHAR(32) BINARY 固定長度、區分大小寫
CREATE TABLE users (
username VARCHAR(50) PRIMARY KEY,
pwd_hash CHAR(32) BINARY NOT NULL
);
-- 註冊:應用層或 SQL 直接雜湊
INSERT INTO users (username, pwd_hash) VALUES ('alice', MD5('secret123'));
-- 登入驗證:參數化查詢,防注入
SELECT 1 FROM users WHERE username = ? AND pwd_hash = MD5(?);
⚠️ 現代安全標準:MD5 / SHA1 已不足,請升級
| 演算法 | 狀態 | 建議替代方案 |
| MD5 / SHA1 | ❌ 已淘汰(碰撞攻擊、GPU 破解極快) | bcrypt (PHP password_hash())、Argon2id (PHP 7.2+)、PBKDF2 |
| SHA256 / SHA512 | ⚠️ 僅適合完整性校驗,不適合密碼(無鹽、可並行加速) | 同上 |
MySQL 8.0 SHA2() | 可用於簽名/校驗 | 密碼請在應用層用 bcrypt/Argon2id |
現代最佳實踐(應用層處理)
// PHP 7.2+ 範例
$hash = password_hash($plainPassword, PASSWORD_ARGON2ID); // 自動產生鹽、成本因子
// 存入資料庫 pwd_hash VARCHAR(255)
if (password_verify($inputPassword, $storedHash)) {
// 登入成功
}
// 定期檢查 password_needs_rehash() 升級演算法/成本
總結
- MySQL 內建
MD5() 可用於快速雜湊、非核心敏感資料校驗。
- 帳號密碼請在應用層使用 bcrypt/Argon2id,資料庫僅存雜湊字串。
- 棄用
PASSWORD()、ENCRYPT(),避免相容性坑。
- 資料庫連線**務必啟用 SSL/TLS**,防止雜湊值在網路傳輸中被竊聽重放。