使用帶有SQL Server加密技術的認證

iSQlServer發表於2009-10-26

問題:我想使用以SQL Server為基礎的加密技術,但是我想要一些額外的“保護”,這樣即使有人訪問到這些金鑰,他們也不能任意地解密資料。我讀過有關認證,但是我不確定怎麼使用它們。那麼,它們是怎麼操作的呢?

  專家解答

  認證是通過加密的其它資料以及以加密方式儲存的資料。提到加密資料,如果沒有指定正確的認證,那麼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';

  返回下面的結果:

  使用帶有SQL Server加密技術的認證

  圖一

  但是如果我們為@SecurityCode指定正確的值:

  EXEC dbo.RetrieveCard 1, 'MyCard', '888';

  我們得到下面的信用卡號:

  使用帶有SQL Server加密技術的認證

  圖二

  在這種情況下,我們看到正確的認證結果大不相同。因此,如果攻擊者可以得到這個資料庫,甚至如果他/她可以訪問那些金鑰,那麼,沒有認證,他們仍然不能成功獲得這些資料。

原文地址:http://database.ctocio.com.cn/dbzjdysummary/16/8879516_1.shtml

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16436858/viewspace-617456/,如需轉載,請註明出處,否則將追究法律責任。

相關文章