保护私钥

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

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

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

如果我放弃将证书存储在机器商店中的原始想法,可以选择将证书pfx文件放置在构建计算机上的ACL受保护文件夹中,只有构建过程和签名用户才有权访问该文件夹。 这样做会允许我创建一个构建作业以使用包含的私钥,而不会将该文件暴露给有权访问该机器的其他人。 要使用私钥,构建参数需要收集私钥密码。

最后,可以选择使用智能卡来存储证书,但我们已经决定不这样做。

所以,我的问题是,是否有其他方法可以做到这一点:1)保护私钥不被复制; 2)防止未授权用户使用私钥签名代码; 3)鉴于私钥密码是由授权用户提供,通过构建服务制作私钥以进行签名?


首先我会尝试分别回答你的问题:

  • 保护私钥不被复制:
    只有加密硬件(智能卡或hsm)才能真正保护密钥不被复制。 Windows证书存储(即使使用正确标记的不可导出选项)或PKCS#12(PFX)文件仅提供错误的保护意义。
  • 防止未经授权的用户使用私钥对代码进行签名:
    IMO需要用户进行交互,例如输入密码或PIN。 如果您将密码作为参数传递,则其他进程总是有可能从进程信息,日志等获得它。
  • 鉴于私钥密码是由授权用户提供的,通过构建服务制作私钥用于签名:
    使用交互输入的密码通过CSP(Windows证书存储)访问的密码硬件(智能卡或hsm)应该可以在没有任何问题的情况下与signtool一起使用。
  • 我同意,用户交互的需求可能不是完全方便自动构建服务,但您可能必须选择具有用户交互的安全解决方案和不需要用户交互的不太安全的解决方案

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

    如果我放弃将证书存储在机器商店中的原始想法,可以选择将证书pfx文件放置在构建计算机上的ACL受保护文件夹中,只有构建过程和签名用户才有权访问该文件夹。 这样做会允许我创建一个构建作业以使用包含的私钥,而不会将该文件暴露给有权访问该机器的其他人。 要使用私钥,构建参数需要收集私钥密码。

    但请注意,PFX文件不仅可以从实时系统中进行复制,还可以从备份中复制。

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

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

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


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

    您可以生成受操作员卡/卡组保护的私钥(例如Thales具有此类HSM)。 可以使用仲裁来设置运算符卡片,仲裁可以指定在请求使用此私钥的应用程序可以使用私钥之前,有多少运营商必须插入卡片。 泰雷兹还有一个支持此功能的CSP。

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

    HSM也具有篡改保护功能,因此私钥在那里是安全的。 很抱歉只谈论Thales HSMs,但我个人没有其他HSM的经验。


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

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

    链接地址: http://www.djcxy.com/p/19481.html

    上一篇: Protecting the private key

    下一篇: Should aggregate roots have dependencies?