SQL + ASP.NET 欄位加密 varbinary 處理

摘要:SQL + ASP.NET 欄位加密 varbinary 處理

 上次提過怎麼對 SQL的欄位做 MDx 、SHA1與encryptbypassphrase的「 SQL 資料庫加密」。但是當你很高興的想對欄位加密後,以前端的應用程式(ASP.Net或其他)來抓加密後的值,卻發現SQL所傳來的是 Varbinary 的格式屬性,而你對使用者輸入的密碼作MD5加密卻是字串,這樣怎麼比對阿?

我們來以「AdventureWorks2008」的「[Sales].[CreditCard」來做例子,顯然的當中的信用卡卡號,以明碼方式直接儲存不太好,而且於網路傳輸也是明碼更不好,那怎麼能做到能比對又可以加密的呢?

第一個方法當然是上次我提的 HASHBYTES ('MD5',欄位) AS 別名,這種方式加密囉!稍微改一下 SELECT 語法

SELECT TOP 1000 [CreditCardID],[CardType],HASHBYTES ('MD5',[CardNumber]) as hash_no,[ExpMonth],[ExpYear],[ModifiedDate] FROM [AdventureWorks2008].[Sales].[CreditCard]


看似一切美好,我們來把他做成檢視表 View ,讓前端來應用

這時出現了 <Binary Data>


咦?應該沒關係吧!我們來拉個 SqlDataSource 及 Gridview 看一下


怎麼出現了XX呢?再用 Gridview 看一下

唉唷?怎麼欄位好像不見了.... Hash_no 不見了.... 



接著一連串
在後端 SQL 用 cast 轉來轉去,不論是 char、varchar ...... 各種欄位屬性可能的都試一試
在前端 ASP.NET 用 char 接、用 binary 接 ...... 怎麼都無法做比對

--------- 分隔線 ----------------

前面那一段是我秏呆的嘗試過程,各位沒耐心看,那就看下面的解答就好....

ANS:直接利用 HASHBYTES 轉出的欄位屬性為 Varbinary ,對於前端較難單純用字串來比對,其解法只需在呼叫個 System Function「sys.fn_VarBinToHexStr」就能輕輕鬆鬆的將 16 進制的 varbinary 轉為字串了,這個 Function 在哪呢?


稍微往下捲動,就能找到  sys.fn_VarBinToHexStr

T-SQL 程式碼改為 SELECT  TOP (1000) CreditCardID, CardType, sys.fn_VarBinToHexStr(HASHBYTES('MD5', CardNumber)) AS hash_no, ExpMonth, ExpYear, ModifiedDate FROM Sales.CreditCard


就能得到想要的結果了!

 

那前端 ASP.NET 程式部分怎麼寫

Credit_no.text = "0x" & LCase(FormsAuthentication.HashPasswordForStoringInConfigFile(Credit_no.Text, "MD5")) 

 當中有兩個地方需要注意,

1.因為用 ASP.NET 做 MD5 編碼,之後並不會帶上 0x 這16進制的開頭,而在 SQL 端以 system function 轉出的會包含 0x ,所以得在編碼成 MD5 之後,加上 0x 才能使字串比對正常。

2.從 SQL 轉出的 Hash Value 是 Lower Case(小寫),而 ASP.NET 轉出是Upper Case (大寫),所以得用 LCase 稍微轉一下大小寫,當然都轉成大寫也行。

-------

如此,不論是針對密碼欄位,或者例子中的信用卡卡號,我們都能在後端加密後再傳送,在前端加密後再比對。

註:其實 MD5 並不是加密,只是對輸入的值產生一個 Hash value,不過他具有唯一性,所以可以用來比對資料正確性或檔案是否被竄改。用加密來形容只是讓大家比較容易理解。

~ End

補充一下:加密功能在 SQL 2005 之後才有提供。