在数据库和实例之间共享密码加密的证书

Dav*_*mes 7 sql-server-2005 security sql-server signature certificate

题:

我正在尝试创建一个(自签名)证书并跨多个数据库和实例进行部署。

我创建和备份证书:

USE MASTER
CREATE CERTIFICATE DavesCert ENCRYPTION BY PASSWORD ='S3creT!' WITH SUBJECT = 'The master cert'

BACKUP CERTIFICATE DavesCert TO FILE = 'd:\DavesCert.cer' 
WITH PRIVATE KEY ( DECRYPTION BY PASSWORD = 'S3creT!' ,
FILE = 'd:\DavesCert.pvk' , 
ENCRYPTION BY PASSWORD = 'S3creT!' );
Run Code Online (Sandbox Code Playgroud)

我用

USE FOO
GO

CREATE CERTIFICATE ERecruitStatsGatheringCert       
FROM FILE = 'd:\DavesCert.cer'      
WITH PRIVATE KEY (FILE = 'd:\DavesCert.pvk', 
DECRYPTION BY PASSWORD = 'S3creT!')
Run Code Online (Sandbox Code Playgroud)

并收到以下错误:“请在数据库中创建主密钥或在执行此操作之前在会话中打开主密钥。”

我不想创建数据库主密钥。我很高兴根据需要通过密码解密证书。

背景: SaaS 应用程序。数据库和实例之间的多对多关系。

我需要每个数据库都能够通过执行一个存储过程来查询它自己的统计信息,该存储过程包含对 DMV 的一些调用以返回统计信息。

应用程序在低权限帐户下运行。DMV 需要 VIEW SERVER STATE 权限,因此,我正在使用证书实现存储过程的签名。

设置它的基本方法是:

  1. 在用户数据库中创建证书。
  2. 备份/恢复该证书以掌握。
  3. 在 master 中创建登录,分配该权限等。
  4. 将证书添加到存储过程。

我有上面的测试代码并且它运行良好,但是该模型不能很好地扩展到跨多个实例/数据库的部署。

因此,我我想在所有数据库/实例中使用相同的证书。

很高兴有其他建议/方法。

-- 最初发布到 Stack Exchange 然后从另一个用途提出建议

Rem*_*anu 5

您只需指定用于解密私钥文件的密码。您需要添加一个密码来存储证书:

CREATE CERTIFICATE ERecruitStatsGatheringCert        
ENCRYPTION BY PASSWORD = 'S3creT!
FROM FILE = 'd:\DavesCert.cer'       
WITH PRIVATE KEY (
    FILE = 'd:\DavesCert.pvk',  
    DECRYPTION BY PASSWORD = 'S3creT!');
Run Code Online (Sandbox Code Playgroud)

但是您的背景信息使整个练习徒劳无功。你这样做是错的。正确的动作顺序是:

  1. 在用户数据库中创建证书
  2. 将签名添加到存储过程
  3. 删除证书的私钥
  4. 将该证书备份/恢复到master(仅限公钥!)
  5. 创建登录名master,分配该权限等。

请注意,不仅私钥永远不会离开数据库,而且实际上在签署过程后立即被明确删除。这是必需的,以防止进一步使用此证书签署其他程序并滥用在步骤 5 中创建的登录权限。您在每个数据库上重复这些步骤并在每个数据库上使用不同的证书。每次修改任何签名过程时都重复这些步骤并每次生成新证书。

作为一般规则,任何需要私钥副本的签名/加密公钥/私钥 (RSA) 方案都会被破坏。这就是为什么被称为私有的,这就是赋予签名价值的原因:知道世界上只存在这个私钥的一个实例,因此任何由它签名的东西都证明它来自唯一的所有者/持有者的唯一私钥。


我知道有些人回避我的建议,即在用于签署程序后立即丢弃私钥。我支持我的建议,但对于您的问题,重要的是不需要将私钥复制到其中[master]以利用您想要的代码签名权限。您可以(并且应该)仅使用公钥创建从证书派生的登录名。

关于自动化:在我看来,它基本上是一个需要两个输入的工具(脚本、应用程序):一个安全(程序、功能、模块)和一个权限(VIEW SERVER STATE)。其他一切都是一个自动化过程(创建一次性使用的一次性证书、签名、导出证书、导入证书[master]、创建登录、授予权限)。隐含的名称(证书名称、登录名)都可以生成。

姓名的激增是一个合理的问题。另一种方法是仅使用一个证书和关联的私钥,签名工具可以在需要时(在签署过程时)添加私钥,然后在签名后将其删除。这实际上取决于您如何经营商店以及您保护的资产的重要性。但重要的是您不需要将私钥导入[master].


Cra*_*ein 1

我在生产中没有太多使用证书和密钥,但我理解这个概念的方式是,使用私钥创建证书意味着使用数据库主密钥来加密证书的私钥。

我在 technet 上找到了这篇文章:http ://technet.microsoft.com/en-us/library/bb964742.aspx

数据库主密钥是对称密钥,用于保护数据库中存在的证书私钥和非对称密钥。

为了查看是否可以在另一台服务器上使用您的证书,我在没有私钥的情况下创建了您的证书。

CREATE CERTIFICATE DavesCert WITH SUBJECT = 'The master cert'
Run Code Online (Sandbox Code Playgroud)

然后我备份了

BACKUP CERTIFICATE DavesCert TO FILE = 'D:\MSSQL\davescert.cer'
Run Code Online (Sandbox Code Playgroud)

我将证书移至另一台服务器并将其恢复。

CREATE CERTIFICATE davescert FROM FILE = 'd:\mssql\davescert.cer'
Run Code Online (Sandbox Code Playgroud)

查看证书

SELECT name, certificate_id, pvt_key_encryption_type_desc from sys.certificates


name    certificate_id  pvt_key_encryption_type_desc
davescert   257 NO_PRIVATE_KEY
Run Code Online (Sandbox Code Playgroud)

如果您不使用私钥来加密您的证书,则不需要数据库主密钥。如果您确实使用私钥,则必须在使用证书的每个数据库上创建主密钥。