首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 加密函數實戰:AES_ENCRYPT、DES_ENCRYPT、SHA2 保護敏感資料完整指南

     編輯:MySQL 資料庫相關知識

為什麼要在資料庫層加密?

應用層加密雖靈活,但易出現實作不一、金鑰管理分散、備份洩漏等問題。MySQL 內建加密函數可將敏感欄位(身分證、信用卡、醫療記錄)在寫入時自動加密,讀取時解密,實現透明資料加密(TDE)雛形。

核心對稱加密函數

函數演算法金鑰長度適用場景
AES_ENCRYPT(str, key) / AES_DECRYPTAES-128-ECB16 字節(128-bit)通用高強度加密,推薦首選
DES_ENCRYPT(str, key) / DES_DECRYPTDES/3DES8/24 字節舊系統相容,不建議新專案
ENCRYPT(str, salt)Unix crypt()2 字節 salt密碼雜湊(已棄用,改用 SHA2)

單向雜湊函數(密碼、完整性驗證)

  • SHA2(str, 256) / SHA2(str, 512):SHA-256/512,推薦
  • SHA1(str):160-bit,已脆弱,禁用於安全場景
  • MD5(str):128-bit,極易碰撞,僅用於非安全校驗
  • PASSWORD(str):MySQL 內部認證雜湊,不可用於業務

實戰範例:身分證字號 AES 加密存儲

1. 產生/管理金鑰

-- 生產環境金鑰應存於金鑰管理系統 (KMS)、環境變數、密碼保險箱
-- 這裡示範用固定 16 字節金鑰(實際必須輪換、分級)
SET @master_key = UNHEX('0123456789ABCDEF0123456789ABCDEF');

2. 建表與寫入

CREATE TABLE `users` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(50),
  `id_card_enc` VARBINARY(100)  -- 加密後二進制,長度 = 原長度填充至 16 倍數
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `users` (`name`, `id_card_enc`)
VALUES ('Alice', AES_ENCRYPT('A123456789', @master_key));

3. 讀取解密

SELECT `name`, CAST(AES_DECRYPT(`id_card_enc`, @master_key) AS CHAR) AS `id_card`
FROM `users` WHERE `id` = 1;

進階:金鑰分級與輪換策略

  • 主金鑰 (KEK):加密資料金鑰 (DEK),存 KMS/HSM
  • 資料金鑰 (DEK):每張表/每欄位一組,定期輪換
  • 輪換流程:UPDATE t SET col_enc = AES_ENCRYPT(AES_DECRYPT(col_enc, old_key), new_key)
  • 應用層僅持有 DEK(經 KEK 解密後),資料庫備份無金鑰不可解密

效能與避坑指南

  • 索引失效:加密欄位無法建立有效索引(密文無序),僅適合低頻查詢欄位
  • 空間膨脹:AES 填充至 16 字節倍數,VARBINARY 儲存
  • 字元集陷阱:加密/解密雙端字元集必須一致,建議統一 utf8mb4
  • SQL 注入風險:金鑰參數化傳遞,絕不拼接 SQL 字串

MySQL 8.0 新功能:元件式加密

  • component_ssl、component_keyring:外掛式金鑰管理
  • INNODB_TABLESPACE_ENCRYPTION:表空間級透明加密(企業版)

結語

MySQL 內建加密函數提供資料庫層面的最後一道防線。結合 AES-128 + 分級金鑰管理 + 應用層參數化,可滿足大多數合規要求。但記住:加密 ≠ 訪問控制,仍需配合權限最小化、審計日誌、網路隔離構建纵深防禦。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved