bri*_*ery 20 c++ windows ssl winapi ssl-certificate
我想使用C++在Win32中验证SSL证书.我想我想使用Cert*API,以便我可以获得Windows证书存储的好处.这就是我想出来的.
bool IsValidSSLCertificate( PCCERT_CONTEXT certificate, LPWSTR serverName )
{
LPTSTR usages[] = { szOID_PKIX_KP_SERVER_AUTH };
CERT_CHAIN_PARA params = { sizeof( params ) };
params.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
params.RequestedUsage.Usage.cUsageIdentifier = _countof( usages );
params.RequestedUsage.Usage.rgpszUsageIdentifier = usages;
PCCERT_CHAIN_CONTEXT chainContext = 0;
if ( !CertGetCertificateChain( NULL,
certificate,
NULL,
NULL,
¶ms,
CERT_CHAIN_REVOCATION_CHECK_CHAIN,
NULL,
&chainContext ) )
{
return false;
}
SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslPolicy = { sizeof( sslPolicy ) };
sslPolicy.dwAuthType = AUTHTYPE_SERVER;
sslPolicy.pwszServerName = serverName;
CERT_CHAIN_POLICY_PARA policy = { sizeof( policy ) };
policy.pvExtraPolicyPara = &sslPolicy;
CERT_CHAIN_POLICY_STATUS status = { sizeof( status ) };
BOOL verified = CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL,
chainContext,
&policy,
&status );
CertFreeCertificateChain( chainContext );
return verified && status.dwError == 0;
}
Run Code Online (Sandbox Code Playgroud)
Jan*_*ins 16
您应该了解RFC3280第6.1节和RFC5280第6.1节.两者都描述了验证证书路径的算法.尽管Win32 API会为您处理一些事情,但一般来说了解该过程仍然很有价值.
此外,这是一个(在我看来)相当值得信赖的参考:Chromium证书验证码.
总的来说,我认为你的代码并不正确.但是,如果我是你,我会调查/改变一些事情:
Chromium将证书公用名与链分开验证.显然他们已经注意到了一些问题.请参阅评论的理由:
cert_verify_proc.win.cc:731 // Certificate name validation happens separately, later, using an internal
cert_verify_proc.win.cc:732 // routine that has better support for RFC 6125 name matching.
Run Code Online (Sandbox Code Playgroud)
Chromium还使用CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT标志而不是CERT_CHAIN_REVOCATION_CHECK_CHAIN.在我找到他们的代码之前,我实际上开始研究这个问题,并且它强化了我的信念,即你应该使用CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT.
即使前面提到的RFC都指定自签名信任锚不被视为链的一部分,但CertGetCertificateChain的文档(http://msdn.microsoft.com/en-us/library/windows/desktop/aa376078(v= vs.85).aspx)表示如果可能的话,它会构建一个链,直到可信的根证书.受信任的根证书(在同一页面上)定义为受信任的自签名证书.
这消除了*EXCLUDE_ROOT可能跳过非root信任锚的撤销检查的可能性(Win32实际上需要信任锚自签名,即使任何RFC都不需要它.虽然这没有正式记录).
现在,由于根CA证书无法撤销(CRL无法签名/验证),因此在我看来这两个标志是相同的.
我做了一些谷歌搜索,偶然发现了这个论坛帖子:http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/9f95882a-1a68-477a-80ee-0a7e3c7ae5cf/x509revocationflag-question?forum= windowssecurity..NET产品组的成员(据称)声称实际中的标志行为相同,如果根是自签名的(理论上,如果根证书包含CDP扩展名,ENTIRE_CHAIN标志将检查根证书是否撤销,但是不可能发生).
他还建议使用*EXCLUDE_ROOT标志,因为如果自签名根CA包含CDP扩展,则另一个标志可能会导致不必要的网络请求.
不幸:
为了完全确定可以使用CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,我搜索了一下,找到了我在回复顶部链接到的Chromium SSL证书验证码.
作为额外的好处,Chromium cert_verify_proc_win.cc文件包含有关IE验证代码的以下提示:
618: // IE passes a non-NULL pTime argument that specifies the current system
619: // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the
620: // chain_flags argument.
Run Code Online (Sandbox Code Playgroud)
不知道他们怎么知道这个,但是在这一点上我觉得使用CERT_CHAIN_REVOCATION_CHECK_EXCLUDE_ROOT感觉很舒服.
我注意到Chromium还指定了3个证书用法而不是1个:
szOID_PKIX_KP_SERVER_AUTH,
szOID_SERVER_GATED_CRYPTO,
szOID_SGC_NETSCAPE
Run Code Online (Sandbox Code Playgroud)
从我可以通过谷歌收集的内容来看,旧的网络浏览器可能需要其他用法,否则他们可能无法建立安全连接.
如果Chromium认为适合包括这些用法,我会效仿.
请注意,如果更改代码,还应将params.RequestedUsage.dwType设置为USAGE_MATCH_TYPE_OR而不是USAGE_MATCH_TYPE_AND.
-
我现在想不出任何其他评论.但如果我是你,我会自己查看Chromium来源(也可能是Firefox) - 只是为了确保我没有错过任何东西.
我认为最好的答案取决于您到底想做什么。
我要提醒您的是,SSL 基于两个端点都需要安全连接的假设。如果任一端点对维护安全性不感兴趣,那么就没有端点。
将字节码放入分布式代码中只需为此函数返回 true 即可,这是一项微不足道的工作。这就是 Windows 将大量验证移至内核的原因。但他们没有预料到人们会在虚拟硬件上运行 Windows,这使得绕过操作系统变得微不足道。
现在考虑一下您希望从某个来源获得证书,但假装无法从可靠来源提供相同的信息。然后交给你。因此,您不能依赖证书来“证明”任何人是特定的任何人。
从证书获得的唯一保护是防止外部人员(而不是端点)破坏所传输消息的机密性。
任何其他用途都注定会失败,并且最终会失败并带来潜在的灾难性后果。
抱歉发了这么大的帖子。评论区有字数限制。
| 归档时间: |
|
| 查看次数: |
6611 次 |
| 最近记录: |