使用 C++ 和 CryptoApi/SChannel 从 SChannel 中提取证书链
Extract Certificate Chain from SChannel with C++ and CryptoApi/SChannel
是否可以在 TLS 1.0 握手中提取远程计算机发送的证书链?
具有SECPKG_ATTR_REMOTE_CERT_CONTEXT值的APIQueryContextAttributes,returns只有结束证书。
是否可以通过一些方法提取所有的链证书?
使用 CryptoApi 和 SChannel 的环境 Windows 和 C++。
谢谢!
是的,是的。
将 QueryContextAttributes()
与 SECPKG_ATTR_REMOTE_CERT_CONTEXT
结合使用,返回的服务器证书会将 hCertStore
成员设置为包含所有服务器中间 CA 证书的证书存储区。 (请参阅 MSDN 处的备注。)
查看下面的代码片段(来源:WebClient.c,Microsoft Platform SDK)如何解析链:
static
void
DisplayCertChain(
PCCERT_CONTEXT pServerCert,
BOOL fLocal)
{
CHAR szName[1000];
PCCERT_CONTEXT pCurrentCert;
PCCERT_CONTEXT pIssuerCert;
DWORD dwVerificationFlags;
printf("\n");
// display leaf name
if(!CertNameToStr(pServerCert->dwCertEncodingType,
&pServerCert->pCertInfo->Subject,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, sizeof(szName)))
{
printf("**** Error 0x%x building subject name\n", GetLastError());
}
if(fLocal)
{
printf("Client subject: %s\n", szName);
}
else
{
printf("Server subject: %s\n", szName);
}
if(!CertNameToStr(pServerCert->dwCertEncodingType,
&pServerCert->pCertInfo->Issuer,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, sizeof(szName)))
{
printf("**** Error 0x%x building issuer name\n", GetLastError());
}
if(fLocal)
{
printf("Client issuer: %s\n", szName);
}
else
{
printf("Server issuer: %s\n\n", szName);
}
// display certificate chain
pCurrentCert = pServerCert;
while(pCurrentCert != NULL)
{
dwVerificationFlags = 0;
pIssuerCert = CertGetIssuerCertificateFromStore(pServerCert->hCertStore,
pCurrentCert,
NULL,
&dwVerificationFlags);
if(pIssuerCert == NULL)
{
if(pCurrentCert != pServerCert)
{
CertFreeCertificateContext(pCurrentCert);
}
break;
}
if(!CertNameToStr(pIssuerCert->dwCertEncodingType,
&pIssuerCert->pCertInfo->Subject,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, sizeof(szName)))
{
printf("**** Error 0x%x building subject name\n", GetLastError());
}
printf("CA subject: %s\n", szName);
if(!CertNameToStr(pIssuerCert->dwCertEncodingType,
&pIssuerCert->pCertInfo->Issuer,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, sizeof(szName)))
{
printf("**** Error 0x%x building issuer name\n", GetLastError());
}
printf("CA issuer: %s\n\n", szName);
if(pCurrentCert != pServerCert)
{
CertFreeCertificateContext(pCurrentCert);
}
pCurrentCert = pIssuerCert;
pIssuerCert = NULL;
}
}
是否可以在 TLS 1.0 握手中提取远程计算机发送的证书链?
具有SECPKG_ATTR_REMOTE_CERT_CONTEXT值的APIQueryContextAttributes,returns只有结束证书。
是否可以通过一些方法提取所有的链证书? 使用 CryptoApi 和 SChannel 的环境 Windows 和 C++。
谢谢!
是的,是的。
将 QueryContextAttributes()
与 SECPKG_ATTR_REMOTE_CERT_CONTEXT
结合使用,返回的服务器证书会将 hCertStore
成员设置为包含所有服务器中间 CA 证书的证书存储区。 (请参阅 MSDN 处的备注。)
查看下面的代码片段(来源:WebClient.c,Microsoft Platform SDK)如何解析链:
static
void
DisplayCertChain(
PCCERT_CONTEXT pServerCert,
BOOL fLocal)
{
CHAR szName[1000];
PCCERT_CONTEXT pCurrentCert;
PCCERT_CONTEXT pIssuerCert;
DWORD dwVerificationFlags;
printf("\n");
// display leaf name
if(!CertNameToStr(pServerCert->dwCertEncodingType,
&pServerCert->pCertInfo->Subject,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, sizeof(szName)))
{
printf("**** Error 0x%x building subject name\n", GetLastError());
}
if(fLocal)
{
printf("Client subject: %s\n", szName);
}
else
{
printf("Server subject: %s\n", szName);
}
if(!CertNameToStr(pServerCert->dwCertEncodingType,
&pServerCert->pCertInfo->Issuer,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, sizeof(szName)))
{
printf("**** Error 0x%x building issuer name\n", GetLastError());
}
if(fLocal)
{
printf("Client issuer: %s\n", szName);
}
else
{
printf("Server issuer: %s\n\n", szName);
}
// display certificate chain
pCurrentCert = pServerCert;
while(pCurrentCert != NULL)
{
dwVerificationFlags = 0;
pIssuerCert = CertGetIssuerCertificateFromStore(pServerCert->hCertStore,
pCurrentCert,
NULL,
&dwVerificationFlags);
if(pIssuerCert == NULL)
{
if(pCurrentCert != pServerCert)
{
CertFreeCertificateContext(pCurrentCert);
}
break;
}
if(!CertNameToStr(pIssuerCert->dwCertEncodingType,
&pIssuerCert->pCertInfo->Subject,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, sizeof(szName)))
{
printf("**** Error 0x%x building subject name\n", GetLastError());
}
printf("CA subject: %s\n", szName);
if(!CertNameToStr(pIssuerCert->dwCertEncodingType,
&pIssuerCert->pCertInfo->Issuer,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, sizeof(szName)))
{
printf("**** Error 0x%x building issuer name\n", GetLastError());
}
printf("CA issuer: %s\n\n", szName);
if(pCurrentCert != pServerCert)
{
CertFreeCertificateContext(pCurrentCert);
}
pCurrentCert = pIssuerCert;
pIssuerCert = NULL;
}
}