按关键行为进行对称加密

时间:2016-03-02 22:21:05

标签: sql-server encryption sql-server-2012

我刚刚进行了以下测试,我很困惑:

我创建了一个像这样的表:

CREATE TABLE [dbo].[enxtest](
    [id] [int] NOT NULL,
    [cleara] [varchar](50) NULL,
    [encrypta] [varbinary](2000) NULL,
    [clearb] [varchar](50) NULL,
 CONSTRAINT [PK_enxtest] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

我用这样的数据填充了它:

id | cleara        | encrypta | clearb
1  | teststring!1  | NULL     | NULL
2  | teststring!1  | NULL     | NULL
3  | teststring!2  | NULL     | NULL
4  | teststring!2  | NULL     | NULL

我运行了一个脚本来加密cleara的内容,使用SQL Server对称密钥和证书对一次一个(仅限相关代码,sproc内部)并将加密值插入encrypta字段:

OPEN SYMMETRIC KEY THIS_IS_THE_KEY
    DECRYPTION BY CERTIFICATE THIS_IS_THE_CERT
CONVERT(varbinary(2000), EncryptByKey(Key_GUID('THIS_IS_THE_KEY'), cleara), 1)

然后我们删除了数据库主密钥,对称密钥和证书,并重新创建它们,使它们具有与之前相同的名称。我运行了一个脚本来解密varbinary,类似于上面的加密代码,并将其插入clearb。

此查询为我提供了以下结果:

SELECT id, cleara, clearb
FROM enxtest;

id | cleara        | encrypta | clearb
1  | teststring!1  | NULL     | teststring!1
2  | teststring!1  | NULL     | teststring!1
3  | teststring!2  | NULL     | teststring!2
4  | teststring!2  | NULL     | teststring!2

问题:

  1. 这怎么可能?我期待得到clearb == clearb但是 clearb!= cleara。我希望切换键会产生 始终不正确的varchar值。
  2. 有没有办法将备份还原到另一台服务器,同时保持表中的二进制数据不变,创建新密钥,可以可靠地解密该数据,使其一致但不正确(相对于原始明文值)值?< / LI>

    编辑:这是我们分批运行的完整脚本。

    --Batch 1
    declare @e1 varbinary(2000);
    declare @c1 varchar(50);
    select @c1 = cleara from enxtest where id = 1;
    exec dbo.spEncryptString @cleartextString = @c1, @encryptedString = @e1 OUTPUT;
    
    declare @e2 varbinary(2000);
    declare @c2 varchar(50);
    select @c2 = cleara from enxtest where id = 2;
    exec dbo.spEncryptString @cleartextString = @c2, @encryptedString = @e2 OUTPUT;
    
    declare @e3 varbinary(2000);
    declare @c3 varchar(50);
    select @c3 = cleara from enxtest where id = 3;
    exec dbo.spEncryptString @cleartextString = @c3, @encryptedString = @e3 OUTPUT;
    
    declare @e4 varbinary(2000);
    declare @c4 varchar(50);
    select @c4 = cleara from enxtest where id = 4;
    exec dbo.spEncryptString @cleartextString = @c4, @encryptedString = @e4 OUTPUT;
    
    update enxtest
    set encrypta = @e1
    where id = 1;
    
    update enxtest
    set encrypta = @e2
    where id = 2;
    
    update enxtest
    set encrypta = @e3
    where id = 3;
    
    update enxtest
    set encrypta = @e4
    where id = 4;
    
    
    /*
    --Batch 2
    drop symmetric key THIS_IS_THE_KEY;
    drop certificate THIS_IS_THE_CERT;
    drop master key;
    
    create master key encryption by password = 'somepassword';
    create certificate THIS_IS_THE_CERT with subject = 'subject' expiry_date = '20161231';
    create symmetric key THIS_IS_THE_KEY with algorithm = AES_256
        key_source = 'source' identity_value = 'identity' encryption by certificate THIS_IS_THE_CERT;
    */
    
    --Batch 3
    declare @e1 varbinary(2000);
    declare @c1 varchar(50);
    select @e1 = encrypta from enxtest where id = 1;
    exec dbo.spDecryptString @encryptedString = @e1, @cleartextString = @c1 OUTPUT;
    
    declare @e2 varbinary(2000);
    declare @c2 varchar(50);
    select @e2 = encrypta from enxtest where id = 2;
    exec dbo.spDecryptString @encryptedString = @e2, @cleartextString = @c2 OUTPUT;
    
    declare @e3 varbinary(2000);
    declare @c3 varchar(50);
    select @e3 = encrypta from enxtest where id = 3;
    exec dbo.spDecryptString @encryptedString = @e3, @cleartextString = @c3 OUTPUT;
    
    declare @e4 varbinary(2000);
    declare @c4 varchar(50);
    select @e4 = encrypta from enxtest where id = 4;
    exec dbo.spDecryptString @encryptedString = @e4, @cleartextString = @c4 OUTPUT;
    
    update enxtest
    set clearb = @c1
    where id = 1;
    
    update enxtest
    set clearb = @c2
    where id = 2;
    
    update enxtest
    set clearb = @c3
    where id = 3;
    
    update enxtest
    set clearb = @c4
    where id = 4;
    
    --Check
    select * from enxtest;
    

1 个答案:

答案 0 :(得分:1)

你没有完全生成一个repro脚本(例如,我没有你的存储过程的主体),但我看到了问题。当您使用相同的KEY_SOURCE参数创建对称密钥时,您实际上是在创建完全相同的密钥。一旦你知道,修复很容易 - 每次创建密钥时为KEY_SOURCE提供不同的值。