SQL Server 登入密碼儲存在 master.dbo.sysxlogins 的 password 欄位(varbinary),並非明文。透過系統預存程序 sp_addlogin 可見其加密邏輯核心為 pwdencrypt() 函數。本文示範如何利用這對內建函數實現自訂密碼雜湊驗證。
| 函數 | 用途 | 特性 |
|---|---|---|
PWDENCRYPT(@plaintext) | 單向雜湊加密 | 輸出 varbinary,同一明文每次產生不同密文(含鹽值),不可逆向 |
PWDCOMPARE(@plaintext, @hash, @version) | 驗證明文與雜湊是否匹配 | 回傳 1/0,@version 0 為舊版、1 為新版(SQL 2000+) |
-- 1. 明文加密存儲
DECLARE @ClearPWD VARCHAR(255) = 'MyStr0ngP@ss';
DECLARE @EncryptedPWD VARBINARY(255);
SELECT @EncryptedPWD = CONVERT(VARBINARY(255), PWDENCRYPT(@ClearPWD));
SELECT @EncryptedPWD AS HashedPassword; -- 0x0100... (含版本、鹽、雜湊)
-- 2. 正確密碼驗證
SELECT PWDCOMPARE(@ClearPWD, @EncryptedPWD, 0) AS MatchResult; -- 1
-- 3. 錯誤密碼驗證
SELECT PWDCOMPARE('WrongPassword', @EncryptedPWD, 0) AS MatchResult; -- 0
pwd VARBINARY(255) NOT NULL DEFAULT PWDENCRYPT('init'),登入時呼叫 PWDCOMPARE 驗證,避免自行實作雜湊演算法風險。sysxlogins,無需知悉明文。PWDCOMPARE 掃描 sysxlogins。HASHBYTES('SHA2_256', ...) + 自管鹽值。PWDENCRYPT 需 CONTROL SERVER 或 SECURITYADMIN 角色;PWDCOMPARE 公開可用。CREATE PROC dbo.usp_ChangePassword
@LoginName SYSNAME,
@OldPlain VARCHAR(128),
@NewPlain VARCHAR(128)
AS
BEGIN
DECLARE @Hash VARBINARY(255);
SELECT @Hash = password FROM master.dbo.sysxlogins WHERE name = @LoginName;
IF @Hash IS NULL OR PWDCOMPARE(@OldPlain, @Hash, 1) = 0
THROW 50001, '原密碼錯誤或登入不存在', 1;
EXEC sp_password @NewPlain, @LoginName; -- 內部自動呼叫 PWDENCRYPT
END;
善用內建 PWDENCRYPT/PWDCOMPARE 可快速建立相對安全的密碼驗證機制,減少自行實作加密的風險。但對高合規要求系統,請採用標準化雜湊演算法並妥善管理鹽值與金鑰輪換。