Web 應用儲存密碼、身分證、信用卡等敏感資料時,MySQL 內建加密函數提供資料庫層面保護。分為**雙向加密** (可解密) 與**單向雜湊** (不可逆),按安全等級選用。
-- 插入加密密碼
INSERT INTO users (username, password)
VALUES ('joe', ENCODE('guessme', 'abracadabra'));
-- 儲存為二進位字串
-- 驗證時解密比對
SELECT DECODE(password, 'abracadabra') FROM users WHERE username = 'joe';
-- 回傳 'guessme'
缺點:演算法專有、強度低、MySQL 8.0 已移除。**不建議新專案使用**。
-- AES-128-ECB 模式,金鑰長度 16 字元
INSERT INTO users (username, password)
VALUES ('joe', AES_ENCRYPT('guessme', '16byteslongkey!'));
-- 解密
SELECT AES_DECRYPT(password, '16byteslongkey!') FROM users WHERE username = 'joe';
-- 回傳二進位,需 CAST: CAST(AES_DECRYPT(...) AS CHAR)
關鍵點:
VARBINARY,查詢時需 CAST(... AS CHAR) 或 HEX() 顯示-- 儲存雜湊值 (不可逆)
INSERT INTO users (username, password_hash)
VALUES ('joe', SHA2('guessme', 256)); -- SHA-256
-- 驗證:雜湊比對
SELECT COUNT(*) FROM users
WHERE username = 'joe' AND password_hash = SHA2('input_pass', 256);
最佳實踐:加鹽
-- 註冊時
SET @salt = SUBSTRING(MD5(RAND()), 1, 8);
SET @hash = SHA2(CONCAT(@salt, 'guessme'), 256);
INSERT INTO users (username, password_hash, salt) VALUES ('joe', @hash, @salt);
-- 登入驗證
SELECT password_hash, salt FROM users WHERE username = 'joe';
-- 應用層計算 SHA2(CONCAT(salt, input_pass), 256) 比對
$stmt = $pdo->prepare("SELECT password_hash, salt FROM users WHERE username = ?");
$stmt->execute([$username]);
$row = $stmt->fetch();
if ($row && hash_equals($row['password_hash'], hash('sha256', $row['salt'] . $input_pass))) {
// 登入成功
}
| 場景 | 推薦函數 | 金鑰管理 | 備註 |
|---|---|---|---|
| 密碼儲存 | SHA2(..., 256) + Salt | 無 (單向) | 業界標準,配合 bcrypt/argon2 更佳 |
| 身分證/銀行卡 (需解密顯示) | AES_ENCRYPT/AES_DECRYPT | 環境變數/金鑰管理系統 | 符合 PCI-DSS 加密儲存要求 |
| 一般敏感欄位 (內部系統、低風險) | ENCODE/DECODE | 應用配置檔 | 僅相容舊系統,新專案禁用 |