代码签名不再有效

时间:2018-02-20 21:04:20

标签: c# windows digital-signature signature cryptoapi

我们有一个传统的Windows工作流程流程,使用SignerSign将数字签名应用于EXE。我们正在远离Windows Workflow流程,因此我一直在新流程的上下文中准备一个工具来执行相同的签名操作。我将代码签名代码从Workflow Activity复制/粘贴到新项目中的类中,但是当我尝试运行它时遇到错误。

代码的大致概述是:

  • CertOpenStore用于打开包含私钥和证书的PFX文件。
  • 通过在生成的证书存储句柄上调用CertEnumCertificatesInStore来获取证书上下文。
  • 调用
  • SignerSignSIGNER_SUBJECT_INFO指向目标EXE文件,SIGNER_CERT指向上一步的证书上下文,SIGNATURE_SIGNER_INFO指定SHA应该使用-1算法。 (我尝试将算法更改为SHA-2 512,但结果没有变化。)pProviderInfo参数为NULL
  • 单独调用SignerTimeStamp以对签名应用时间戳。代码中的注释表示如果使用pwszHttpTimeStamp SignerSign参数,则返回HRESULT 0x80070020(“正在使用的文件”?)

当我尝试在Windows 10 64位上运行此代码时,无论是从32位还是64位进程,我都会收到错误HRESULT 0x80092006“没有为商店或对象指定提供程序。”。我尝试提供pProviderInfo,将提供程序名称设置为“Microsoft Strong Cryptographic Provider”(在SignTool.exe签署可执行文件的API监视器跟踪输出中看到 - 这有效),但它不会影响结果。

有谁知道这个错误究竟意味着什么,以及如何解决它?

1 个答案:

答案 0 :(得分:0)

我完全不知道为什么会这样,但是通过按摩我的代码就可以看到SignTool在Rohitab的API监视器中执行的操作,然后将其丢弃到看似最小的工作集,现在这个再次签署文件:

  • 而不是CertOpenStorePFXImportCertStore用于打开PFX文件并生成HCERTSTORE。这需要将PFX加载到内存中,以便它可以作为CRYPT_DATA_BLOB传递 - 没什么大不了的。
  • 以前使用CertEnumCertificatesInStore获取证书上下文。
  • CertGetCertificateChain用于生成的证书上下文,其中包含不受限制的CERT_CHAIN_PARA和标记CERT_CHAIN_DISABLE_PASS1_QUALITY_FILTERING | CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT。没有指定其他商店。当我最初写这篇文章时,基于API监视器的结果,我定义CERT_CHAIN_PARA_HAS_EXTRA_FIELDS并按照API Monitor捕获显示的方式填充它们,但我继续从S_OK获取SignerSignCERT_CHAIN_PARA结构。
  • 像以前一样调用
  • SignerSign,除了作为嵌套在hCertStore内的SIGNER_CERT_STORE_INFO结构的SIGNER_CERT传入虚拟集合类型存储。通过调用CertOpenStore两次创建此虚拟集合类型存储,一次使用CERT_STORE_PROV_COLLECTION并标记CERT_STORE_CREATE_NEW_FLAG,一次使用CERT_STORE_PROV_MEMORY指定编码PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,然后添加使用CertAddStoreToCollection将内存存储到集合存储区。

如果未指定虚拟集合类型存储,则SignerSign会抱怨它无法找到受信任根的路径。请注意,我在测试中使用的证书是自签名的,因此没有到受信任根的路径。也许虚拟集合类型存储对于具有到受信任根的路径的代码签名证书是不必要的,我目前没有办法测试。

无论如何,我希望这有助于解决可能遇到SignerSign问题的其他人的问题。 : - )