2010-08-24 56 views
10

我正在寻找使用对称密钥应用SQL列级加密。创建数据库主密钥,证书和对称密钥所需的初始步骤似乎很简单,我已经成功使用对称密钥测试了加密/解密数据。WHERE子句中的SQL加密列

但是,一旦数据被加密,我不知道如何最好地查询它。例如。

SELECT PlainTextA, PlainTextB, PlainTextC 
WHERE CONVERT(varchar, DECRYPTBYKEY(EncyptedColumn)) = @SearchTerm 

肯定会导致全表扫描?

我认为可能工作的另一个选择是首先加密搜索条件,例如,

SELECT PlainTextA, PlainTextB, PlainTextC 
WHERE EncyptedColumn = ENCRYPTBYKEY(KEY_GUID('KeyName'), @SearchTerm) 

但是这不起作用,因为生成的加密值总是不同的。

任何建议将不胜感激。

回答

10

的典型方法是同时存储加密值的单向散列值。当你寻求一个特定的值时,你会寻找散列。这种方式可以有效地查询,W/O不必解密为了行找到你感兴趣的值:

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 dataSQL Server 2005: searching encrypted data

+2

顺便说一句,你绝对不会**做的一件事就是用行特定值(PK)对散列进行赋值:你会完全回到方形1,不知道要寻找什么。对于这种情况,你*可以*用哈希值和*站点全局*值。这足以防止彩虹表攻击,但可以保持数据的可搜索性。请注意,虽然具有相同内容的两个不同行会*具有相同的散列,因此您正在公开某些信息,但是这是具有可搜索数据的定义。 – 2010-08-24 21:17:01

+0

“请注意,虽然具有相同内容的两个不同的行将具有相同的散列” - 这是我使用散列的主要关注点,因为它降低了安全级别,但是我正在使用的表将具有4到5个加密列,如果我只为其中一个添加相应的哈希列,然后它可以被接受。 – 2010-08-24 21:36:39

+0

请注意,表中的散列冲突会受到生日攻击(中间相遇)的影响,因此明显高于直觉。仍然SHA1有20个字节的相当大的地址空间。 – 2010-08-24 23:52:02

2

您拥有的一个选项是在表格中添加一个新列(或者在其中包含一个带有计算列的WITH SCHEMABINDING视图,并对其进行索引),并使用搜索值的单向HASH。它不必是一个强大的散列 - something as simple as CHECKSUM will work。然后,在搜索中对搜索值进行散列,并使用已编制索引的散列进行筛选。这样,您可以暴露可搜索和可索引的内容,而不会实际暴露该值本身。

但是,如果有另一种方式来直接做到这一点,我很想知道它是什么:)

+0

感谢您的回复和链接。我认为在使用主键作为盐之前,在哈希之前对它进行赋值也是最好的办法? – 2010-08-24 21:08:24

+1

不,你不会想要加盐的价值,除非(如雷姆斯所说)它是某种“全球盐”,然后它不是真正的盐。如果你用你的价值观来衡量,你的指数查找变得不可能,因为盐对于每一行都是不同的。 – SqlRyan 2010-08-24 22:46:20

-1

另一种选择是使用包含解密值列的查看并根据它查找记录。

SELECT PlainTextA, PlainTextB, PlainTextC from TheView 
WHERE DecryptedColumn = @SearchTerm