【问题标题】:Is it possible to determine ENCRYPTBYKEY maximum returned value by the clear text type?是否可以通过明文类型确定 ENCRYPTBYKEY 最大返回值?
【发布时间】: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 类型长度?

【问题讨论】:

    标签: sql-server tsql encryption sql-server-2016 sqldatatypes


    【解决方案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 是消息输入。


    注意事项:

    • 注意头中的第一个字节包含方案的版本号;如果使用不同的内部消息格式或加密方案,此答案是否 notcannot 指定将添加或删除多少字节;
    • 强烈建议您使用完整性字节,以防您希望保护您的数据库字段不被更改(保持帐户中的金额保密不如确保金额无法更改重要)。
    • 页面上的示例假定文本字符采用单字节编码。

    【讨论】:

    • 请在继续之前确认这是正确的,我是加密专家,而不是数据库专家。
    • 我只是想知道这部分: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 以考虑异常情况。

    【讨论】:

      猜你喜欢
      • 2019-05-06
      • 1970-01-01
      • 2011-12-18
      • 2020-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多