这些方法执行的加密是以块的形式完成的,最大块大小是密钥长度减去一些内部开销(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 年的限制。