0

我的问题是由于我工作场所的政策,我正在尝试加密 SQL Server 数据库中的列。我只能使用简单的加密方法(TDE 似乎超出了我的可能性),所以我尝试使用EncryptByCertor EncryptByKey。我做得很好,因为文档显示上限为 8000,这对于我们正在保存的数据来说已经足够了。

碰巧的是,当我尝试保存任何内容时,它会以大约 200 个字符为上限,生成一个 514 字节长的 varbinary。514 字节长度的 varbinary 可以很好地加密和解密,但不会增长或缩短,单个字符的计数与 200 个字符串相同,从而使相同的 514 字节二进制。在说我要加密的大约 230 个字符之后,它将只保留该列为空。

有谁知道发生了什么?

4

1 回答 1

0

这些方法执行的加密是以块的形式完成的,最大块大小是密钥长度减去一些内部开销(117 字节用于 1024 位密钥,245 字节用于 SQL Server 2016 中首次引入的 2048 位密钥)。

如果您的输入大于此值,则必须将其拆分为多个块并一次加密一个,然后将结果连接起来。

当然,应该相应地执行解密。但是,两者之间的一个重要区别是加密块大小将小于密钥,而对于解密它应该恰好是密钥大小。这是因为任何数据,无论多么短,都将被加密为密钥长块,因此无法通过查看输出来猜测输入长度。

这是我的加密函数的摘录(为 2012 版本编写,因此假定为 1024 位密钥):

create function [dbo].[security_EncryptByCert]
(
    @ClearText varbinary(max)
)

returns varbinary(max) with schemabinding, returns null on null input as begin

-- Returned value
declare @Ret varbinary(max) = 0x,
    -- Length of the ciphertext
    @Lng int = datalength(@ClearText),
    -- Starting offset of the chunk to encrypt
    @i int = 1,
    -- Chunk size, currently it can't be more than 117 bytes
    @Size int = 100,
    -- Certificate to encrypt data with
    @CertId int;


-- Determine the certificate with which to perform encryption
select @CertId = Id from ...

-- Iterate chunk by chunk til the end of the text
while @i < @Lng begin

    set @Ret += encryptbycert(@CertId, substring(@ClearText, @i, @Size));

    -- Move the pointer to the next block
    set @i += @Size;

end;

return @Ret;
end;

在这种情况下,我使用了 100 字节的块,而不是可能的最大块。不记得为什么,但您可以使用 245 字节作为 2016 年的限制。

于 2017-02-27T10:18:16.483 回答