專家解答
認證是通過加密的其它資料以及以加密方式儲存的資料。提到加密資料,如果沒有指定正確的認證,那麼SQL Server不會返回以解密方式存在的資料。而且,如果使用了錯誤的金鑰,還會返回一個NULL值。例如,考慮儲存信用卡密碼的情形。如果在獲取信用卡時沒有傳遞正確的安全程式碼,那麼就不可能得到信用卡密碼。
首先我們需要做的時確定我們有正對這個過程的主碼、認證和對稱金鑰。下面的程式碼將建立你在資料庫中測試的這些物件:
--建立資料庫主碼,用它來加密證照金鑰
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'SomeStr0ngPassw0rd!';
GO |
CREATE CERTIFICATE
EncryptKeyForCreditCard
WITH SUBJECT = 'Certificate Used to Encrypt Symmetric Key for credit card number handling'; GO |
CREATE SYMMETRIC KEY
CreditCardEncryptionKey
WITH ALGORITHM = AES_256 ENCRYPTION BY CERTIFICATE EncryptKeyForCreditCard; GO |
下面的指令碼建立了一張表和一個儲存過程來描述這個問題。
/*建立表來儲存信用卡資訊。
通常我們有一個外碼CustomerID參照使用者表。儘管如此,在這個例項中我們不會建立這樣一個外碼。
CREATE TABLE dbo.CreditCard (
CreditCardID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED, CustomerID INT NOT NULL, CardFriendlyName VARCHAR(50) NOT NULL, NameOnCard VARCHAR(100) NOT NULL, ExpirationDate SMALLDATETIME NOT NULL, CardNumber VARBINARY(128) NOT NULL ); GO CREATE PROC dbo.InsertCard @CustomerID INT, @CardFriendlyName VARCHAR(50), @NameOnCard VARCHAR(100), @ExpirationDate SMALLDATETIME, @CardNumber CHAR(16), @SecurityCode CHAR(3) AS BEGIN OPEN SYMMETRIC KEY CreditCardEncryptionKey DECRYPTION BY CERTIFICATE EncryptKeyForCreditCard; INSERT INTO dbo.CreditCard (CustomerID, CardFriendlyName, NameOnCard, ExpirationDate, CardNumber) VALUES (@CustomerID, @CardFriendlyName, @NameOnCard, @ExpirationDate, EncryptByKey(Key_GUID('CreditCardEncryptionKey'), @CardNumber, 1, @SecurityCode) ); CLOSE SYMMETRIC KEY CreditCardEncryptionKey; END; GO CREATE PROC dbo.RetrieveCard @CustomerID INT, @CardFriendlyName VARCHAR(50), @SecurityCode CHAR(3) AS BEGIN SELECT NameOnCard, ExpirationDate, CONVERT(CHAR(16), DecryptByKeyAutoCert(cert_ID('EncryptKeyForCreditCard'), NULL, CardNumber, 1, @SecurityCode)) AS CardNumber FROM dbo.CreditCard WHERE CustomerID = @CustomerID AND CardFriendlyName = @CardFriendlyName; END; GO |
當信用卡號碼儲存在CreditCard表中時,它將以加密的格式儲存。當我們儲存它時,如果我們使用@SecurityCode作為認證,那麼它需要作為一個認證以純文字(不加密)的形式得到信用卡號碼。因此,當我們指定EncryptByKey()函式,我們將確定使用告訴該函式我們要使用一個認證的引數並且把@SecurityCode引數當作認證來傳遞。到檢索這張卡的時間時,我們將使用DecryptByKeyAutoCert(),因為我們只需要指定證照,它會自動解密對稱金鑰然後訪問該資料。我們再次指定引數來指出正在使用一個認證,然後如果@SecurityCode引數是正確的,那麼我們會把它當作一個認證來傳遞,這時將返回信用卡號碼,否則SQL Server將返回一個NULL。
讓我們來看一個例項。
EXEC dbo.InsertCard 1, 'MyCard', 'John Doe', '20120601', '1111222233334444', '888';
這裡使用的‘888’,如果還指定其它,那麼信用卡號將不返回。例如:
EXEC dbo.RetrieveCard 1, 'MyCard', '777';
返回下面的結果:
圖一
但是如果我們為@SecurityCode指定正確的值:
EXEC dbo.RetrieveCard 1, 'MyCard', '888';
我們得到下面的信用卡號:
圖二
在這種情況下,我們看到正確的認證結果大不相同。因此,如果攻擊者可以得到這個資料庫,甚至如果他/她可以訪問那些金鑰,那麼,沒有認證,他們仍然不能成功獲得這些資料。
原文地址:http://database.ctocio.com.cn/dbzjdysummary/16/8879516_1.shtml