T-SQL/CLR 确定性加密函数
T-SQL/CLR function for deterministic encryption
我有一个 table 用户代理字符串 table 具有以下结构:
UserAgentStringID INT
UserAgentStringValue VARBINARY(8000)
[UserAgentStringValue]
字段使用对称密钥加密。 table 结构的先前版本是:
UserAgentStringID INT
UserAgentStringValue NVARCHAR(4000)
UserAgentStringHASH BINARY(32)
并且我在 [UserAgentStringHASH]
列上有索引以优化搜索者。
对于新格式,这样的索引不如 ENCRYPTION function uses InitializationVector 有效,以便每次使用相同的输入调用加密函数时生成随机值:
Initialization vectors are used to initialize the block algorithm. It
is not intended to be a secret, but must be unique for every call to
the encryption function in order to avoid revealing patterns.
所以,我可以在我的加密字段上创建索引,但如果我尝试按加密值搜索,我将无法找到任何内容。
我不想使用 HASH
因为使用散列函数不是安全技术。如果有人拥有我的 table 数据并且 table 拥有全部或大量用户代理,he/she 将能够通过哈希执行连接并显示我的数据。
在 SQL Server 2016 SP
标准版中,我们有 Always Encrypted
允许对列值使用 Deterministic Encryption
- 这意味着相等比较有效并且可以创建索引。
我正在寻找一种通过其他技术优化搜索的方法,或者一种使用 CLR 实现确定性加密的方法?
知道没有变通方法对我来说也很好。我想我会用性能来支付数据保护。
我发布了一个解决方法 - 这不是理想的解决方案,但它是速度和安全性之间的折衷。
详情
- a 列必须加密(比方说电子邮件地址)
- 必须实现快速搜索(假设电子邮件用于登录,我们需要尽快找到记录)
- 我们无法使用 Always Encrypted 确定性加密(由于各种原因)
- 我们不想将散列函数与 salt 一起使用 - 如果每个用户都有 salt,ze 可能能够使用大型样本数据库读取散列值
安全等级
有多种实现安全层次结构的方法。 MSDN 中的以下架构对其进行了很好的描述。
在我们的环境中,我们使用 Database Mater Key -> Certificate -> Symmetric Key 层次结构。只有 DBA know
DMK 密码,才能访问证书和对称密钥。一些开发人员可以处理 encrypt/decrypt 数据(使用纯 T-SQL)而其他人则不能。
请注意,使用 Always Encrypted 可以进行角色分离 - 使用数据的人员无权访问密钥,有权访问密钥的人员无权访问数据。在我们的案例中,我们希望保护我们的数据不受外界影响,并拥有其他技术 granting/logging 内部数据访问。
有权访问加密数据的开发人员
可以访问受保护数据的开发人员可以对其进行加密和解密。他们无权访问对称密钥值。如果可以访问对称密钥值,则 ze 能够 decrypt 没有用于保护对称密钥的证书的数据事件。基本上,只有 sys.admins 和 db_owners 可以访问对称密钥值。
如何哈希
我们需要哈希来进行快速搜索,但我们不能使用未加密的盐。从安全角度来看,没有加盐的哈希就像纯文本。因此,我们决定使用对称密钥值作为盐。是这样的:
SELECT @SymmetricKeyValue = CONVERT(VARCHAR(128), DECRYPTBYCERT(C.[certificate_id], KE.[crypt_property]), 1)
FROM [sys].[symmetric_keys] SK
INNER JOIN [sys].[key_encryptions] KE
ON SK.[symmetric_key_id] = KE.[key_id]
INNER JOIN [sys].[certificates] C
ON KE.[thumbprint] = C.[thumbprint]
WHERE SK.[name] = @SymmetricKeyName;
并将该值连接到您的电子邮件地址,然后计算哈希值。这对我们有好处,因为我们将哈希绑定到安全层次结构。并且它不是每条记录的不同盐,它是相同的 - 但如果知道对称密钥值,则 ze 能够直接解密数据。
注意事项
您需要创建使用 EXECUTE AS OWNER
子句按散列值搜索或计算散列的例程(存储过程、触发器)。否则,开发人员将无法执行它们,因为只有 sys.admins 和 db_owners 可以访问对称密钥值。
我有一个 table 用户代理字符串 table 具有以下结构:
UserAgentStringID INT
UserAgentStringValue VARBINARY(8000)
[UserAgentStringValue]
字段使用对称密钥加密。 table 结构的先前版本是:
UserAgentStringID INT
UserAgentStringValue NVARCHAR(4000)
UserAgentStringHASH BINARY(32)
并且我在 [UserAgentStringHASH]
列上有索引以优化搜索者。
对于新格式,这样的索引不如 ENCRYPTION function uses InitializationVector 有效,以便每次使用相同的输入调用加密函数时生成随机值:
Initialization vectors are used to initialize the block algorithm. It is not intended to be a secret, but must be unique for every call to the encryption function in order to avoid revealing patterns.
所以,我可以在我的加密字段上创建索引,但如果我尝试按加密值搜索,我将无法找到任何内容。
我不想使用 HASH
因为使用散列函数不是安全技术。如果有人拥有我的 table 数据并且 table 拥有全部或大量用户代理,he/she 将能够通过哈希执行连接并显示我的数据。
在 SQL Server 2016 SP
标准版中,我们有 Always Encrypted
允许对列值使用 Deterministic Encryption
- 这意味着相等比较有效并且可以创建索引。
我正在寻找一种通过其他技术优化搜索的方法,或者一种使用 CLR 实现确定性加密的方法?
知道没有变通方法对我来说也很好。我想我会用性能来支付数据保护。
我发布了一个解决方法 - 这不是理想的解决方案,但它是速度和安全性之间的折衷。
详情
- a 列必须加密(比方说电子邮件地址)
- 必须实现快速搜索(假设电子邮件用于登录,我们需要尽快找到记录)
- 我们无法使用 Always Encrypted 确定性加密(由于各种原因)
- 我们不想将散列函数与 salt 一起使用 - 如果每个用户都有 salt,ze 可能能够使用大型样本数据库读取散列值
安全等级
有多种实现安全层次结构的方法。 MSDN 中的以下架构对其进行了很好的描述。
在我们的环境中,我们使用 Database Mater Key -> Certificate -> Symmetric Key 层次结构。只有 DBA know
DMK 密码,才能访问证书和对称密钥。一些开发人员可以处理 encrypt/decrypt 数据(使用纯 T-SQL)而其他人则不能。
请注意,使用 Always Encrypted 可以进行角色分离 - 使用数据的人员无权访问密钥,有权访问密钥的人员无权访问数据。在我们的案例中,我们希望保护我们的数据不受外界影响,并拥有其他技术 granting/logging 内部数据访问。
有权访问加密数据的开发人员
可以访问受保护数据的开发人员可以对其进行加密和解密。他们无权访问对称密钥值。如果可以访问对称密钥值,则 ze 能够 decrypt 没有用于保护对称密钥的证书的数据事件。基本上,只有 sys.admins 和 db_owners 可以访问对称密钥值。
如何哈希
我们需要哈希来进行快速搜索,但我们不能使用未加密的盐。从安全角度来看,没有加盐的哈希就像纯文本。因此,我们决定使用对称密钥值作为盐。是这样的:
SELECT @SymmetricKeyValue = CONVERT(VARCHAR(128), DECRYPTBYCERT(C.[certificate_id], KE.[crypt_property]), 1)
FROM [sys].[symmetric_keys] SK
INNER JOIN [sys].[key_encryptions] KE
ON SK.[symmetric_key_id] = KE.[key_id]
INNER JOIN [sys].[certificates] C
ON KE.[thumbprint] = C.[thumbprint]
WHERE SK.[name] = @SymmetricKeyName;
并将该值连接到您的电子邮件地址,然后计算哈希值。这对我们有好处,因为我们将哈希绑定到安全层次结构。并且它不是每条记录的不同盐,它是相同的 - 但如果知道对称密钥值,则 ze 能够直接解密数据。
注意事项
您需要创建使用 EXECUTE AS OWNER
子句按散列值搜索或计算散列的例程(存储过程、触发器)。否则,开发人员将无法执行它们,因为只有 sys.admins 和 db_owners 可以访问对称密钥值。