2

我正在学习 SQL Server 加密,并且我对确定性行为有疑问。

SQL Server 加密函数是否具有确定性?它是否取决于版本(2005,...,2017)?

我不是指“始终加密”功能,而是指encryptedbykey.

4

1 回答 1

1

首先,这可以很容易地测试。您可以将相同的值加密两次并检查输出是否相同。使用下面的代码:

CREATE MASTER KEY ENCRYPTION BY PASSWORD = '23987hxJ#KL95234nl0zBe';  

CREATE CERTIFICATE [CERT_StackOverflow]
WITH SUBJECT = 'example';

CREATE SYMMETRIC KEY [SK_StackOverflow]   
WITH ALGORITHM = AES_256  
ENCRYPTION BY CERTIFICATE [CERT_StackOverflow];  
GO  


OPEN SYMMETRIC KEY [SK_StackOverflow] DECRYPTION BY CERTIFICATE [CERT_StackOverflow];  

SELECT EncryptByKey(Key_GUID('SK_StackOverflow'), 'stackoverflow');  
SELECT EncryptByKey(Key_GUID('SK_StackOverflow'), 'stackoverflow');  


DROP SYMMETRIC KEY [SK_StackOverflow];
DROP CERTIFICATE [CERT_StackOverflow];
DROP MASTER KEY;

因此,结果是ENCRYPTBYKEY函数不是确定性的。

为什么?如果不是这样,暴力破解将非常容易。如果您对幕后发生的事情感兴趣,可以查看以下文章。基本上,输出文本是这样计算的:

CipherTextMessage := KeyGUID + EncryptionHeader + EncryptedMessage

在哪里:

  • KeyGUID := {16 字节} Key_guid。此 GUID 用作密钥的标识符,它存储在元数据中 (SELECT key_guid FROM sys.symmetric_keys)。它在解密期间用于在密钥环中找到相应的密钥。这就是为什么当我们使用DECRYPTBYKEY时,我们不使用来指定加密期间使用的密钥
  • EncryptedMessage 的计算方式如下:

    EncryptedMessage := InitializationVector + _EncryptFunction(SymKey, InitializationVector, InnerMessage)

关键InitializationVector是:

InitializationVector := {1 block} 该字段的长度取决于所使用的算法。所有 AES 系列密钥将是每个块 16 个字节,而 DES 系列密钥是每个块 8 个字节。初始化向量用于初始化块算法。它不打算成为秘密,但对于每次调用加密函数必须是唯一的,以避免泄露模式。

如果您对确定性加密功能感兴趣,例如因为创建索引以优化搜索,并且由于其所有限制而不想使用 Always Encrypted,我可以告诉您如何创建/模拟确定性使用 SQL Server安全层次结构进行加密。

于 2019-02-02T09:23:25.270 回答