自动代码签名 - 保护私钥

时间:2014-03-16 00:31:58

标签: security jenkins certificate code-signing signtool

我想自动化一些ClickOnce部署工件的代码签名 - 应用程序exe和清单。我正在使用signtool来完成此任务。为了使私钥可用于签名并保护包含私钥(.pfx文件)的证书文件,我的计划是使用不可导出的密钥将证书安装到本地计算机证书存储中。 (我知道有一些方法可以导出密钥,即使它被标记为不可导出。)该机器是一个持续集成服务器,只有少数人可以访问。我希望以这样一种方式进行设置,即只要需要使用私钥,就需要输入私钥密码。然后我会设置一个自动作业(使用Jenkins),这需要一个可以收集私钥密码的构建参数。 Mask Passwords plugin将用于在输入时和控制台输出中屏蔽密码。

但是,我遇到了几个障碍。首先,即使存在“启用强私钥保护。如果启用此选项,每次应用程序使用私钥时都会提示您。”导入证书时,它似乎仅在将其导入当前用户存储而不是本地计算机存储时可用。其次,即使此选项可用,在使用商店中的证书进行签名时,signtool工具也不提供设置密码的选项。密码参数'/ p'仅在使用pfx文件作为私钥源('/ f'选项)时适用。鉴于此,这似乎不是一个可行的选择。注意:即使“启用强私钥保护”。可用于机器商店中的证书,我的测试表明,尝试使用带有此选项的证书只会弹出一个对话框,要求获得使用它的权限,这显然不适用于自动化作业。我原本以为“提示”意味着它会要求输入密码。

我考虑过的另一个选项是创建ACL以保护证书存储区中的私钥。这可以通过右键单击证书并选择All Tasks ... |来完成管理私钥...对话框。这会将私钥使用限制为仅限授权。 (注意:当没有私钥权限的用户尝试使用它进行签名时,他们会收到消息“SignTool错误:找不到符合所有给定条件的证书。”)但是,我不想提供访问权限到Jenkins构建服务使用的凭据,因为任何构建作业都可以签署代码。我可以创建一个作业来执行脚本以作为特定用户运行签名命令。这需要将域用户名和密码作为构建参数。我可以使用Jenkins Mask Passwords插件来做到这一点。不过,我真的不喜欢这样,因为我觉得掩码密码足以防止暴露域名凭证,如果受到损害,它可以提供远远超过私钥的访问权限。

如果我放弃了将证书存储在计算机存储中的原始想法,可以选择将证书pfx文件放在构建计算机上的ACL安全文件夹中,只有构建过程和签名用户具有权限。这样做可以让我创建一个构建作业来使用包含的私钥,同时不将文件暴露给有权访问该机器的其他人。要使用私钥,构建参数需要收集私钥密码。

最后,可以选择使用智能卡存储证书,但我们已决定反对。

所以,我的问题是,有没有其他方法可以做到这一点1)保护私钥不被复制,2)防止未经授权的用户使用私钥签署代码和3),给定私有密钥密码由授权用户提供,私钥是否由构建服务签名?

3 个答案:

答案 0 :(得分:4)

首先,我将尝试分别回答您的问题:

  1. 保护私钥不被复制:
    只有加密硬件(智能卡或hsm)才能真正保护密钥不被复制。 Windows证书存储(即使您正确记录了不可导出的选项)或PKCS#12(PFX)文件也只提供错误的保护感。
  2. 防止未经授权的用户使用私钥对代码进行签名:
  3. 鉴于私钥密码由授权用户提供,请使用构建服务进行签名的私钥:
    通过CSP(Windows证书存储区)可访问的加密硬件(智能卡或hsm) )交互式输入的PIN应该与signtool一起使用,没有任何问题。
  4. 我同意用户交互的要求对于自动构建服务可能不太方便,但您可能必须在安全解决方案与用户交互和不太安全的解决方案之间进行选择而无需用户交互

    方便但不太安全的解决方案没有。 1 :在我看来,您已经找到了一个可接受的解决方案,因为您没有提供任何缺点。

      

    如果我放弃了将证书存储在计算机存储中的原始想法,可以选择将证书pfx文件放在构建计算机上的ACL安全文件夹中,只有构建过程和签名用户具有权限。这样做可以让我创建一个构建作业来使用包含的私钥,同时不将文件暴露给有权访问该机器的其他人。要使用私钥,构建参数需要收集私钥密码。

    但请注意,不仅可以从实时系统而且从备份中无法检测到PFX文件。

    方便但不太安全的解决方案没有。 2 :将私钥存储在不需要输入PIN的智能卡上,并且只允许系统访问受信任的用户。这将确保您的私钥无法复制,而signtool仍然可以轻松访问。但是,它可能需要您有两个单独的构建服务器 - 一个没有智能卡可供所有用户访问,另一个智能卡只能由可信用户访问。

    难以置信的安全解决方案:将私钥存储在需要输入PIN的智能卡上,并在构建过程中要求用户交互(输入PIN)。

    您还可以考虑在自动模式下使用自签名代码签名证书签署开发版本,并在手动模式下使用可信代码签名证书签署公共版本版本。

答案 1 :(得分:0)

我看到的唯一选择是使用HSM。

您可以生成受操作员卡/卡组保护的私钥(例如,Thales有这种HSM)。可以使用仲裁设置操作员卡集,该仲裁指定在请求使用此私钥的应用程序可以使用私钥之前,有多少操作员必须插入卡。 Thales还有一个支持此功能的CSP。

问题可能是CSP将调用窗口向用户显示必须插入卡(以及输入该卡的可选密码)。当您使用可以登录的桌面的某个用户帐户运行构建服务器时,可能会解决此问题。当您以此用户身份登录并启动构建服务器时,它必须请求使用私钥(例如,通过签署一些虚拟文件或其他内容)。 Windows将弹出,操作员(法定人数所需的数量)将逐个插入卡并可选择输入密码。插入所有必需的卡后,您的构建服务器将可以使用该密钥。任何其他应用程序(可能由其他用户启动)将通过相同的过程来使用该密钥。如果您的构建服务器崩溃(构建服务器崩溃吗?),您将完成相同的过程。

HSM还具有篡改保护功能,因此私钥是IMHO安全的。很抱歉只谈论Thales HSM,但我个人没有任何其他HSM的经验。

答案 2 :(得分:0)

似乎依赖受密码保护的PFX文件而不是证书存储是安全的。即使在PFX所在的硬盘文件夹中没有ACL保护,也没有人使用PFX文件可以使用它来签署任何内容,除非他们也有密码。

然后,在该计算机上设置一个参数化的Jenkins“签名”作业,完全封装PFX密码,这样任何人都无法看到它。 (我正在考虑某种类型的脚本,Powershell可能会转换为黑盒EXE。)授权的Jenkins工作可以链接到签名工作以完成签名。 EXE会在每次使用时记录,作为审计功能。只需要弄清楚如何防止未经授权使用签名工作......必须有办法做到这一点吗?

相关问题