获取证书链到私人根

问题描述:

我试图验证从签名证书链回到特定的根证书,这是而不是受Windows信任(它是应用程序的专用证书)。获取证书链到私人根

我目前的尝试做到这一点涉及创建一个链接引擎,它只信任我想要的特定证书作为根目录,以便不会生成其他链。

HCERTSTORE hPrivateRootStore = CertOpenStore(CERT_STORE_PROV_FILENAME, dwEncoding, 
    NULL, CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, 
    _T("C:\\Test\\PrivateRoot.cer")); 
CERT_CHAIN_ENGINE_CONFIG config; 
memset(&config, 0, sizeof(config)); 
config.cbSize = sizeof(config); 
config.hRestrictedTrust = hPrivateRootStore; 
config.dwFlags = CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL | CERT_CHAIN_ENABLE_SHARE_STORE; 
HCERTCHAINENGINE hEngine; 
CertCreateCertificateChainEngine(&config, &hEngine); 
CERT_CHAIN_PARA params; 
memset(&params, 0, sizeof(params)); 
params.cbSize = sizeof(params); 
PCCERT_CHAIN_CONTEXT chains = NULL; 
if (CertGetCertificateChain(hEngine, pCertContext, NULL, hStore, &params, 
    0, NULL, &chains)) 
    ... 
(检查省略错误清晰度; pCertContexthStoreCryptQueryObject来提取签署的二进制文件的签名和相关证书。)

不幸的是,这似乎并没有工作;尽管使用了自定义链接引擎,但它似乎仍在搜索操作系统存储库,并且没有找到链或找到一个不同的根目录(这是操作系统信任的)。我只能通过将我的私有根证书添加到操作系统信任的商店来获得我想要的链。

我也尝试将config.hRestrictedOther设置为空的内存存储区,因为文档建议非空的hRestrictedTrust会再次引入系统存储区,但这没有任何区别。

有什么我失踪,或更好的方式来做到这一点?

编辑:只是为了给更多的情况下,我试图做类似驱动程序签名的证书,其中签名证书链接回两个不同的东西根:一个标准的CA根由OS信任,一个内部根目录(在驱动程序中也受操作系统信任,但在我的情况下只会受到我的应用程序的信任)。交叉发生在“主”链中间的某个地方;可能会有许多不同的文件都与不同的“真实”CA签署,但仍然链接到我的内部证书。

+0

经过一番调查,我发现在Win7中'hExclusiveRoot'成员被添加到'CERT_CHAIN_ENGINE_CONFIG'。我认为相关的描述清楚地表明'CertCreateCertificateChainEngine'不提供任何机制来忽略旧版本中的系统存储(这让我想知道它到底是什么,但这是一个单独的问题)。所以,新的问题:是否有其他方法来枚举可能的链回到我想要的根?与'CertVerifyCertificateChainPolicy'兼容的东西会很好,尽管如果需要的话我可能没有它。 – Miral

+0

你试图分析的证书文件格式是什么? –

+0

该主题是Authenticode签名的二进制文件,所需的根目录是一个编译到应用程序中的.cer,并作为“PCCERT_CONTEXT”加载。 – Miral

我已经找到了一个半熟的解决方法;这有点难看,但它确实有点用。我从 Chromium's test suite得到了基本的想法;它涉及在Crypt32中安装一个钩子,以便当它试图打开系统存储以构建链时,它将获得我的自定义存储,而只包含我所需的证书。

好的是,这似乎迫使 CertGetCertificateChain去“过去”真正的CA证书链中的所有方法我自定义证书,而不是在CA证书停止(这是它通常不会当是可信的)。

糟糕的是,它似乎并没有阻止它建立链和信任任何其他CA证书。我可以通过明确验证链的根源是我想要的证书来解决这个问题,但这并不理想,而且我不确定是否有情况会导致此问题。

仍在寻找更好的解决方案;我肯定会觉得我在某个地方走错了路。

好的,新的计划。我现在只是手动走链(因为我知道我关心的所有证书都将在从签名中提取的hStore中。基本结构如下:

  • 使用WinVerifyTrust做基本的“是不是篡改”身份验证。
  • 使用CryptQueryObject获得证书存储hStore从.exe
  • 使用CryptMsgGetParamCertFindCertificateInStore找到从hStore签名证书。
  • 从签名证书开始,使用CertFindCertificateInStoreCERT_FIND_SUBJECT_NAME循环查找潜在的颁发者证书;继续前行,直到我点击自签名证书或找到我想要的根(通过CertComparePublicKeyInfo检查比赛)。
  • 如果CertVerifySubjectCertificateContext表示签名不匹配,则放弃特定的分支。

似乎比我以前的方法更清洁。思想/评论/替代品?

(在某些方面似乎更有意义的东西是添加一个额外的自定义联署[类似于时间戳],而不是试图链接这样的证书,但我找不到任何关于这样做的信息,或者有什么优点/缺点)。