使用主密钥恢复数据库并以纯文本形式存储密码

Chr*_*s L 5 sql-server encryption

我们有一个(SQL 代理)作业,它每晚备份我们的生产数据库(并恢复到测试数据库服务器),并且我们正在为表中的某些列添加加密。我创建了一个主密钥并将其绑定到服务主密钥:

Create MASTER KEY Encryption By Password = 'MyReallyStrongPW'
ALTER MASTER KEY ADD ENCRYPTION BY SERVICE MASTER KEY CLOSE MASTER KEY
Run Code Online (Sandbox Code Playgroud)

我还创建了我的证书:

CREATE CERTIFICATE [My_Cert] With Subject = 'My Certificate'
CREATE SYMMETRIC KEY My_Symm_Key WITH ALGORITHM = AES_256 ENCRYPTION BY CERTIFICATE [MY_Cert];
Run Code Online (Sandbox Code Playgroud)

同一个账号

域\MyBigSqlAccount

正在运行 sql (prod & test) 的两个实例。

能够看到数据(在测试中)的唯一方法是运行这个:

OPEN MASTER KEY DECRYPTION BY PASSWORD = 'MyReallyStringPW'

ALTER MASTER KEY ADD ENCRYPTION BY SERVICE MASTER KEY CLOSE MASTER KEY
Run Code Online (Sandbox Code Playgroud)

然后这将起作用:

OPEN SYMMETRIC KEY My_Symm_Key DECRYPTION BY CERTIFICATE [My_Cert] 

Select Convert(varchar, DecryptByKey(EncryptedColumn)) as DecryptedCol From SomeTable
Run Code Online (Sandbox Code Playgroud)

我能够让它工作的唯一方法是将密码放入纯文本作为 sql 作业中的一个步骤

步骤1:恢复数据库,步骤2:使用密码将Master Key绑定到测试服务器上的Service Master Key。

以纯文本形式存储密码(或解密包含密码的文件的密码)似乎不太明智。

两者都使用 Sql Server 2012。

相关(Q1b)SQL Server 2008 加密的简单实现

问题是我如何绕过以纯文本形式存储我的密码,并且仍然对 prod 和文本使用加密?

Mic*_*her 2

毫无疑问,第 2 步需要新的设计。我建议,第 2 步将使用随机备份数据库主密钥来备份数据库主密钥,而不是传递数据库主密钥密码(该密码通常保持相当恒定并且不会经常更改)。生成足够长度的密码。然后可以在源处对密码进行加密,加密后传递到目标服务器,然后解密并用于恢复数据库主密钥。对于此设计,您需要将过程、证书和视图添加到源服务器 msdb 数据库,并将过程和证书添加到目标服务器 msdb 数据库。您还需要在目标服务器上创建一个共享文件夹,并向产品服务器的 SQL 代理服务帐户授予写入权限。涉及的对象有:

  • ProdServer.msdb.vwGetRandomPass - 生成随机长密码的视图
  • ProdServer.msdb.DMKEncryptionCertificate - 加密 DMK 密码的证书
  • ProdServer.msdb.usp_BackupDMK - 从视图 vwGetRandomPass 检索随机密码,使用它将 DMK 备份到共享,使用证书 DMKEncryptionCertificate 加密密码,将加密的密码作为输出 varbinary 变量返回
  • TargetServer.msdb.DMKEncryptionCertificate - 用于解密从产品服务器上的证书和私钥备份恢复的 DMK 密码的证书
  • TargetServer.msdb.usp_restoreDMK - 接受 varbinary 参数密码,使用 DMKEncryptionCertificate 解密密码,使用解密的密码从共享恢复 DMK,成功恢复后删除 DMK 文件

第 2 步包括调用 prod 服务器过程,然后调用 TargetServer 过程以完成恢复。您可以使用链接服务器、osql 调用或其他方法来调用目标服务器上的过程。

为了进一步提高安全性,您可以在备份后将私钥删除到生产服务器上。这样只有目标服务器才能解密密码。密码每天也会不同且不可预测。另一个好处是 DMK 每次都会被删除,并且仅在步骤 2 的持续时间内存在于共享上,这应该是几秒钟的事情。

这可以成功完成,但是,我还想问是否应该这样做。如果这些数据非常敏感以至于需要加密,那么它是否应该在您的生产系统之外可用?如果您决定不这样做,那么您可以将证书和对称密钥删除到目标数据库中,并创建具有相同名称的新证书和对称密钥以避免异常。任何使用这些的调用都将返回 null。我已包含以下视图:

/*
generates a random 128 character string from all 
valid password characters except single quote

*/
CREATE VIEW dbo.vwGetRandomPass
AS
WITH s1
AS (
    SELECT TOP 32 CHAR(number) AS chr
    FROM master..spt_values
    WHERE number BETWEEN 48
            AND 57 -- number characters
    ORDER BY newid()
    )
    ,s2
AS (
    SELECT TOP 32 CHAR(number) AS chr
    FROM master..spt_values
    WHERE number BETWEEN 65
            AND 90 -- Upper letters
    ORDER BY newid()
    )
    ,s3
AS (
    SELECT TOP 32 CHAR(number) AS chr
    FROM master..spt_values
    WHERE number BETWEEN 97
            AND 122 -- Lower letters
    ORDER BY newid()
    )
    ,s4
AS (
    SELECT TOP 32 CHAR(number) AS chr
    FROM master..spt_values
    WHERE number BETWEEN 33
            AND 38
        OR number BETWEEN 40
            AND 47 -- sign characters
        OR number BETWEEN 58
            AND 64
        OR number BETWEEN 91
            AND 96
        OR number BETWEEN 123
            AND 126
    ORDER BY newid()
    )
    ,final
AS (
    SELECT chr
    FROM s1

    UNION ALL

    SELECT chr
    FROM s2

    UNION ALL

    SELECT chr
    FROM s3

    UNION ALL

    SELECT chr
    FROM s4
    )
SELECT pass = (
        SELECT chr AS [text()]
        FROM final
        ORDER BY newid()
        FOR XML path('')
        )
GO
Run Code Online (Sandbox Code Playgroud)