我希望使用对称密钥来应用SQL列级加密。创建数据库主密钥,证书和对称密钥所需的初始步骤似乎很简单,我已成功使用对称密钥测试加密/解密数据。
但是,一旦数据被加密,我不知道如何最好地查询它。 E.g。
SELECT PlainTextA, PlainTextB, PlainTextC
WHERE CONVERT(varchar, DECRYPTBYKEY(EncyptedColumn)) = @SearchTerm
肯定会导致全表扫描?
我认为可能有用的其他选项是首先加密搜索条件,例如
SELECT PlainTextA, PlainTextB, PlainTextC
WHERE EncyptedColumn = ENCRYPTBYKEY(KEY_GUID('KeyName'), @SearchTerm)
但这不起作用,因为生成的加密值总是不同。
任何建议都将不胜感激。
答案 0 :(得分:14)
典型的方法是将加密值和都存储为值的单向散列。当您寻找特定值时,您将寻求哈希值。通过这种方式,您可以高效查询,无需解密每个行,以便找到您感兴趣的值:
create table Table (
EncryptedColumn varbinary(max),
HashValue binary(20),
PlainA int,
PlainB varchar(256),
PlainC Datetime);
create index ndxTableHash on Table(HashValue);
select PlainA, plainB, PlainC
from table
where HashValue = HashBytes('SHA1', @searchTerm);
从理论上讲,你可以在蓝色的月亮中发生一次哈希冲突,对于在解密的列上添加双重检查是偏执的安全:
select PlainA, plainB, PlainC
from table
where HashValue = HashBytes('SHA1', @searchTerm)
and DecryptByKey(..., EncryptedColumn) = @searchTerm;
另见Indexing encrypted data和SQL Server 2005: searching encrypted data。
答案 1 :(得分:2)
您有一个选项是向表中添加一个新列(或者在其中包含计算列的WITH SCHEMABINDING
视图,并使用搜索值的单向HASH进行索引)。它不一定是强大的哈希 - something as simple as CHECKSUM will work。然后,在查找中对搜索值进行哈希处理,并通过索引对其进行过滤。这样,您可以暴露可搜索和可索引的内容,而不会实际暴露值本身。
但是,如果有另一种方法直接这样做,我很想知道它是什么:)
答案 2 :(得分:-2)
另一种选择是使用包含一列解密值的View,并根据它查找记录。
SELECT PlainTextA, PlainTextB, PlainTextC from TheView
WHERE DecryptedColumn = @SearchTerm