【问题标题】:Code signing no longer working代码签名不再起作用
【发布时间】:2018-02-20 21:04:19
【问题描述】:
我们有一个旧的 Windows 工作流进程,它使用 SignerSign 将数字签名应用于 EXE。我们正在从 Windows 工作流流程迁移,因此我一直在准备新流程上下文中的工具来执行相同的签名操作。我将代码签名代码从 Workflow Activity 复制/粘贴到新项目中的一个类,但是当我尝试运行它时遇到错误。
代码作用的大致轮廓是:
-
CertOpenStore 用于打开包含私钥和证书的 PFX 文件。
- 通过在生成的证书存储句柄上调用
CertEnumCertificatesInStore 来获取证书上下文。
-
调用
SignerSign 时,SIGNER_SUBJECT_INFO 指向目标 EXE 文件,SIGNER_CERT 指向上一步的证书上下文,SIGNATURE_SIGNER_INFO 指定应使用 SHA-1 算法。 (我尝试将算法更改为 SHA-2 512,但结果没有变化。)pProviderInfo 参数是 NULL。
- 单独调用
SignerTimeStamp 以将时间戳应用于签名。代码中的注释表示如果使用SignerSign的pwszHttpTimeStamp参数,则返回HRESULT 0x80070020(“File in use”?)
当我尝试在 64 位 Windows 10 上运行此代码时,无论是从 32 位还是 64 位进程,我都会收到错误 HRESULT 0x80092006“没有为商店或对象指定提供程序。”。我尝试提供一个pProviderInfo,并将提供程序名称设置为“Microsoft Strong Cryptographic Provider”(在 SignTool.exe 签署可执行文件时的 API 监视器跟踪输出中看到 - 这有效),但它不影响结果。
有谁知道这个错误的确切含义以及如何解决它?
【问题讨论】:
标签:
c#
windows
digital-signature
signature
cryptoapi
【解决方案1】:
我完全不知道为什么会这样,但是通过按摩我的代码,这样我就可以在 Rohitab 的 API 监视器中看到 SignTool 做同样的事情,然后将部分缩减到看起来是最小的工作集,现在再次签署文件:
- 而不是
CertOpenStore,。 PFXImportCertStore 用于打开 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 Monitor 结果,我定义了CERT_CHAIN_PARA_HAS_EXTRA_FIELDS 并以与 API Monitor 捕获显示相同的方式填充它们,但我继续从 SignerSign 获得 S_OK 与短 CERT_CHAIN_PARA 结构为好吧。
-
SignerSign 像以前一样被调用,除了一个虚拟集合类型存储作为嵌套在SIGNER_CERT 中的SIGNER_CERT_STORE_INFO 结构的hCertStore 传入。这个虚拟集合类型存储是通过调用CertOpenStore 两次创建的,一次使用CERT_STORE_PROV_COLLECTION 和标志CERT_STORE_CREATE_NEW_FLAG,一次使用CERT_STORE_PROV_MEMORY 指定编码PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,然后使用CertAddStoreToCollection 将内存存储添加到集合存储中.
如果未指定虚拟集合类型存储,则SignerSign 会抱怨它找不到指向受信任根的路径。请注意,我在测试中使用的证书是自签名的,因此没有 到受信任根的路径。对于确实具有可信根路径的代码签名证书,可能不需要虚拟集合类型存储,我目前没有测试的方法。
无论如何,我希望这有助于为其他可能遇到SignerSign 问题的人解决此问题。 :-)