问题:我想使用以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';
返回下面的结果:
图一
但是如果我们为@SecurityCode指定正确的值:
EXEC dbo.RetrieveCard 1, 'MyCard', '888';
我们得到下面的信用卡号:
图二
在这种情况下,我们看到正确的认证结果大不相同。因此,如果攻击者可以得到这个数据库,甚至如果他/她可以访问那些密钥,那么,没有认证,他们仍然不能成功获得这些数据。
原文地址:http://database.ctocio.com.cn/dbzjdysummary/16/8879516_1.shtml
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/16436858/viewspace-617456/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/16436858/viewspace-617456/