是否可以通过明文类型确定 ENCRYPTBYKEY 最大返回值?
Posted
技术标签:
【中文标题】是否可以通过明文类型确定 ENCRYPTBYKEY 最大返回值?【英文标题】:Is it possible to determine ENCRYPTBYKEY maximum returned value by the clear text type? 【发布时间】:2018-08-28 00:37:36 【问题描述】:我将加密现有表中的几个字段。基本上,将使用以下加密技术:
CREATE MASTER KEY ENCRYPTION
BY PASSWORD = 'sm_long_password@'
GO
CREATE CERTIFICATE CERT_01
WITH SUBJECT = 'CERT_01'
GO
CREATE SYMMETRIC KEY SK_01
WITH ALGORITHM = AES_256 ENCRYPTION
BY CERTIFICATE CERT_01
GO
OPEN SYMMETRIC KEY SK_01 DECRYPTION
BY CERTIFICATE CERT_01
SELECT ENCRYPTBYKEY(KEY_GUID('SK_01'), 'test')
CLOSE SYMMETRIC KEY SK_01
DROP SYMMETRIC KEY SK_01
DROP CERTIFICATE CERT_01
DROP MASTER KEY
ENCRYPTBYKEY 返回 varbinary
,最大大小为 8,000 字节。知道要加密的表字段(例如:nvarchar(128)
、varchar(31)
、bigint
)如何定义新的varbinary
类型长度?
【问题讨论】:
【参考方案1】:你可以看到完整的规范here
让我们计算一下:
16
字节密钥UID
_4
字节头
16
字节 IV(对于 AES,16 字节分组密码)
再加上加密消息的大小:
_4
字节幻数
_2
字节完整性字节长度
_0
bytes 完整性字节(警告:可能在表中放错了)
_2
字节(明文)消息长度
_m
字节(明文)消息
CBC 填充字节
CBC 填充字节应按以下方式计算:
16 - ((m + 4 + 2 + 2) % 16)
因为总是应用填充。这将导致 1..16 范围内的填充字节数。一个偷偷摸摸的捷径是只在总数中添加 16 个字节,但这可能意味着您要指定最多 15 个从未使用过的字节。
我们可以将其缩短为 36 + 8 + m + 16 - ((m + 8) % 16)
或 60 + m - ((m + 8) % 16
。或者,如果您使用上面指定的小技巧并且不关心浪费的字节:76 + m
其中 m 是消息输入。
注意事项:
注意头中的第一个字节包含方案的版本号;如果使用不同的内部消息格式或加密方案,此答案是否 not 和 cannot 指定将添加或删除多少字节; 强烈建议您使用完整性字节,以防您希望保护您的数据库字段不被更改(保持帐户中的金额保密不如确保金额无法更改重要)。 页面上的示例假定文本字符采用单字节编码。【讨论】:
请在继续之前确认这是正确的,我是加密专家,而不是数据库专家。 我只是想知道这部分:using integrity bytes is highly recommended
- 你能给我一个链接,我可以在其中找到更多详细信息。
这有点通用:如果您使用对称密钥保护您的数据免于机密性,那么您不妨保护它免受更改(但请注意,交换它可能仍然是可能的)。参见例如 GCM 等 authenticated 密码模式的巨大进展,例如在 TLS 1.3(最新的 SSL 草案)中。是否需要取决于用例和威胁模型。您不希望有人更改银行帐户的值,但即使您可以更改密码,您也无法窃取密码。
那么计算结果检查了吗?我想他们确实接受了?
是的,我已经使用 ASCII 和 Unicode 数据进行了测试。一切都是正确的。我无法加密数字或日期,但这是 T-SQL 函数的限制。【参考方案2】:
根据 SQL Server 2008 中的一些测试,以下公式似乎有效。注意@ClearText 是 VARCHAR():
52 + (16 * ( ((LEN(@ClearText) + 8)/ 16) ) )
这与 Maarten Bodewes 的答案大致兼容,只是我的测试显示 DATALENGTH(myBinary) 始终采用 52 + (z * 16)
的形式,其中 z
是一个整数。
LEN(myVarCharString) DATALENGTH(encryptedString)
-------------------- -----------------------------------------
0 through 7 usually 52, but occasionally 68 or 84
8 through 23 usually 68, but occasionally 84
24 through 39 usually 84
40 through 50 100
“myVarCharString”是定义为 VARCHAR(50) 的表列。该表包含 150,000 条记录。提到“偶尔”是10,000条记录中大约有1条会被撞到更高存储桶的实例;很奇怪。对于 24 或更高的 LEN(),没有足够的记录来获取奇怪的异常。
这是一些 Perl 代码,它采用“myVarCharString”的建议长度作为来自终端的输入,并为 EncryptByKey() 结果生成预期的大小。函数“int()”等价于“Math.floor()”。
while($len = <>)
print 52 + ( 16 * int( ($len+8) / 16 ) ),"\n";
您可能希望使用此公式来计算大小,然后添加 16 以考虑异常情况。
【讨论】:
以上是关于是否可以通过明文类型确定 ENCRYPTBYKEY 最大返回值?的主要内容,如果未能解决你的问题,请参考以下文章