我想自动化一些 ClickOnce 部署工件的代码签名 - 应用程序 exe 和清单。我正在使用signtool来完成此操作。为了使私钥可用于签名并保护包含私钥的证书文件(.pfx 文件),我的计划是使用不可导出的密钥将证书安装到本地计算机证书存储中。(我知道有一些方法可以导出密钥,即使它被标记为不可导出。)这台机器是一个持续集成服务器,只有少数人可以访问。我希望以这样一种方式设置它,即任何时候需要使用私钥时,都需要输入私钥密码。然后我会设置一个自动化工作(使用Jenkins) 这将需要一个构建参数来收集私钥密码。Mask Passwords 插件将用于在输入和控制台输出时屏蔽密码。
但是,我遇到了几个障碍。首先,即使有“启用强私钥保护。如果启用此选项,每次应用程序使用私钥时都会提示您”。导入证书时,它似乎仅在将其导入当前用户存储时可用,而不是本地机器存储。其次,即使此选项可用,signtool 工具也不提供在使用商店中的证书进行签名时设置密码的选项。密码参数“/p”仅在使用 pfx 文件作为私钥源(“/f”选项)时适用。鉴于此,这似乎不是一个可行的选择。注意:即使“启用强私钥保护”。可用于机器商店中的证书,我的测试表明,在启用此选项的情况下尝试使用证书只会弹出一个对话框,询问是否允许使用它,这显然不适用于自动化作业。我最初认为“提示”意味着它会要求输入密码。
我考虑过的另一种选择是创建 ACL 以保护证书存储中的私钥。这可以通过右键单击证书并选择所有任务来完成... | 管理私钥...对话框。这会将私钥的使用限制为仅授权的人。(注意:当没有私钥权限的用户尝试使用它进行签名时,他们会收到消息“SignTool 错误:未找到符合所有给定条件的证书。”)但是,我不想授予访问权限到 Jenkins 构建服务使用的凭据,因为这样任何构建作业都可以签署代码。我可以创建一个作业,该作业将执行脚本以以特定用户身份运行签名命令。这需要将域用户名和密码作为构建参数。我可以使用 Jenkins Mask Passwords 插件来做到这一点。不过,我真的不喜欢这样,因为我对 Mask Passwords 足以防止暴露域凭据感到不舒服,如果域凭据受到破坏,将获得的访问权限不仅仅是私钥。
如果我放弃将证书存储在机器存储中的最初想法,则可以选择将证书 pfx 文件放在构建机器上的 ACL 安全文件夹中,只有构建过程和签名用户有权访问该文件夹。这样做将允许我创建一个构建作业以使用包含的私钥,同时不会将文件暴露给有权访问该机器的其他人。要使用私钥,构建参数需要收集私钥密码。
最后,可以选择使用智能卡来存储证书,但我们决定不这样做。
所以,我的问题是,有没有其他方法可以做到这一点:1)保护私钥不被复制,2)防止未经授权的用户使用私钥来签署代码,3)假设私钥密码是由授权用户提供,使构建服务签名的私钥?