﻿# SQL Server中秘密的PWDENCRYPT與PWDCOMPARE函數

前幾天有個客戶的網站出問題（不是我們開發的），請我們幫他看，主要的問題是他們的網站會員在進行查詢密碼時，會員收到信的時候在密碼的欄位竟然會出現 System.Binary\[\] 字樣。而我進去資料庫中查看時，發現該會員資料表中的密碼欄位是 varbinary 格式，而我當然不知道他儲存的是什麼值，進而查看他們資料庫中的 Stored Procedure 對於密碼欄位的操作方法，這才發現他們用來驗證會員是否正確登入的方法是使用 PWDCOMPARE 函數。

由於我沒看過這個函數，便上網去[查看看](http://www.google.com/search?hl=zh-TW&esrch=BetaShortcuts&q=pwdcompare&lr=)，發現這個函數真的是個迷樣的 SQL 內建 Function，而且在 MSDN, TechNet 上都查不到相關文件，而我在 Google 搜尋 [pwdcompare site:microsoft.com](http://www.google.com/search?hl=zh-TW&esrch=BetaShortcuts&q=pwdcompare+site%3Amicrosoft.com&btnG=%E6%90%9C%E5%B0%8B&lr=) 得到的結果也僅僅才 127 筆資料而已，且大多這個關鍵字僅僅出現在論壇中，感覺這個 Function 似乎是微軟刻意不讓他曝光的。

而 PWDENCRYPT 與 PWDCOMPARE 函數剛好是一對兄弟，一個負責**加密**、一個負責**比對**，但就是沒有「**解密**」的函數。意思也就是說，使用 PWDENCRYPT 加密過的資料是無法反解的，類似一種 Hash 處理方法。

而且我還發現，使用 PWDENCRYPT 函數加密同樣的字串資料，每次回應的結果都會不一樣，但是使用 PWDCOMPARE 函數一樣可以對加密過的資料進行比對，以下是簡單的使用方法介紹。

**PWDENCRYPT 函數**

```
select pwdencrypt('ok')
```

執行後的結果：

```
0x010066E6CDE3C8DE9363BE015AC22966456F230432D6485C6B58
```

*注意：每次執行 select pwdencrypt('ok') 的結果都會不一樣，這是一種對密碼保護的機制，只是我不清楚他的演算法。*

**PWDCOMPARE 函數**

```
select pwdcompare('ok', 0x010066E6CDE3C8DE9363BE015AC22966456F230432D6485C6B58)
```

執行後的結果為 1 或 0 而已，1 代表密碼比對成功，0 代表密碼比對失敗。

第一個參數是當初加密時的設定的**密碼**字串。第二個參數是當時加密後的**二進位值**。

事實上，SQL Server 本身在進行密碼驗證時，應該也就是用 PWDCOMPARE 函數在比對的，怎麼說呢？你可以先執行以下 T-SQL 查詢出系統登入帳號的 password\_hash 欄位：

```
SELECT password_hash FROM master.sys.sql_logins WHERE name='sa'
```

然後再將結果用 PWDCOMPARE 函數驗證一下你設定的 sa 密碼，如果回傳值是 1 就代表密碼正確。

*備註：雖然有人說這類 undocumented functions 未來可能隨時被取消或刪除，但我卻認為這一組 Function 應該會長久存在，只是「沒有文件」而已。*

我也簡單的測試了一下，這兩個 Function 在 SQL 2000, 2005, 2008 都可以使用，只是我也發現了一些不同的 SQL Server 版本之間在使用這兩個 Function 時的小差異：

1.  使用 PWDENCRYPT 時 SQL 2000 與 SQL 2005/2008 加密過後的 hash 長度不一樣！
2.  SQL 2005/2008 加密過的密碼在 SQL 2000 中無法使用 PWDCOMPARE 函數驗證密碼！
3.  SQL 2005 與 SQL 2008 基本上是相容的。
4.  SQL 2000 加密過的密碼雖然比較長，但在 SQL 2005/2008 中還是可以使用 PWDCOMPARE 函數驗證密碼！

要使用這兩個 Function 的人可能要小心的不是 PWDENCRYPT 與 PWDCOMPARE 函數未來會消失，而是要考慮未來的 SQL Server 版本對兩個 Function 的實做是否能相容，目前看來向下相容應該是沒問題，但未來是否會持續向下相容還是很難說，畢竟資料庫中的資料還是會一直沿用下去。

**相關連結**

-   [初探 pwdencrypt 與 pwdcompare 函數](http://sharedderrick.blogspot.com/2008/11/pwdencrypt-pwdcompare.html)
-   [pwdencrypt and pwdcompare](https://web.archive.org/web/20121215000810/http://msmvps.com:80/blogs/gladchenko/archive/2005/04/06/41083.aspx)
-   [SQL Server password encryption models](http://www.enterpriseitplanet.com/security/features/article.php/1582981)
-   [Designing Security for Microsoft SQL Server 2005: Course 2787](https://learn.microsoft.com/en-us/credentials/certifications/retired-courses)
