在证书链验证期间,我需要将自定义的自签名根证书标记为受信任的,总的来说,我希望尽可能依赖系统API。
我创建了一个临时内存存储。
HCERTSTORE certStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, 0);
然后我将自定义根证书放入存储中。
CertAddCertificateContextToStore(certStore, rootCertContext, CERT_STORE_ADD_REPLACE_EXISTING, 0);
CertGet证书链MSDN留档表示
HadAdditional存储任何附加存储的句柄,以搜索支持证书和证书信任列表(CTL)。
据我所知,如果我用根证书创建一个CTL并将其放置到存储中,CertGet证书链将信任它。因此,我在分配的缓冲区中创建根证书CTL条目,然后将其复制到std::矢量ctlEntry
CertCreateCTLEntryFromCertificateContextProperties(rootCertContext, 0, nullptr, CTL_ENTRY_FROM_PROP_CHAIN_FLAG, nullptr, ctlEntry, &size);
然后我创建CTL本身。
const std::wstring ctlID(L"TrustedRoots");
// I do not know what OIDs to use here. I tried different options.
std::vector<LPSTR> usageList;
usageList.push_back(szOID_SORTED_CTL);
usageList.push_back(szOID_PKIX_KP_CLIENT_AUTH);
usageList.push_back(szOID_PKIX_KP_SERVER_AUTH);
CTL_INFO ctlInfo;
ZeroMemory(&ctlInfo, sizeof(ctlInfo));
ctlInfo.dwVersion = CTL_V1;
ctlInfo.SubjectUsage.cUsageIdentifier = static_cast<DWORD>(usageList.size());
ctlInfo.SubjectUsage.rgpszUsageIdentifier = usageList.data();
ctlInfo.ListIdentifier.cbData = static_cast<DWORD>((ctlID.size() + 1) * sizeof(wchar_t));
ctlInfo.ListIdentifier.pbData = static_cast<BYTE*>(static_cast<void*>(const_cast<wchar_t*>(ctlID.data())));
ctlInfo.SubjectAlgorithm.pszObjId = szOID_OIWSEC_sha1;
ctlInfo.cCTLEntry = static_cast<DWORD>(ctlEntries.size());
ctlInfo.rgCTLEntry = const_cast<PCTL_ENTRY>(ctlEntries.data());
// From MSDN:
// The message can be encoded without signers if the cbSize member of the structure is set to the
// size of the structure and all of the other members are set to zero.
CMSG_SIGNED_ENCODE_INFO encode;
ZeroMemory(&encode, sizeof(encode));
encode.cbSize = sizeof(encode);
DWORD size = 0, flags = CMSG_ENCODE_SORTED_CTL_FLAG | CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG;
if (CryptMsgEncodeAndSignCTL(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &ctlInfo, &encode, flags, nullptr, &size) == TRUE)
{
std::string data;
data.resize(size);
BYTE* p = static_cast<BYTE*>(static_cast<void*>(&data.front()));
if (CryptMsgEncodeAndSignCTL(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &ctlInfo, &encode, flags, p, &size) == TRUE)
{
PCCTL_CONTEXT ctlContext = CertCreateCTLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, p, size);
if (ctlContext)
{
if (CertAddCTLContextToStore(certStore, ctlContext, CERT_STORE_ADD_REPLACE_EXISTING, nullptr) == TRUE)
{
// success
}
}
}
}
上面的所有API调用都成功完成,但是当我调用CertGet证书链时,它仍然返回CERT_TRUST_IS_UNTRUSTED_ROOTTrustStatus.dw错误状态。
潜在的解决办法
如果我得到CERT_TRUST_IS_UNTRUSTED_ROOT错误,我只需从证书存储中提取CTL,并检查结果链(由CertGetCertificateChain返回)中的根是否在CTL中。它是有效的,但对我来说仍然不能完全接受。我想依靠CertGetCertificateChain。
这个解决方案有什么问题?我必须使用什么特定的证书信任列表?在这种情况下,是否需要信任根证书(如特定扩展)?
p、 s.使用本说明创建测试证书https://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309
UPD:2020-01-31
CertModify证书ToTrust没有帮助。它成功完成,但链仍然被报告为具有不可信的根。问题可能在不同的领域。
PCCERT_CONTEXT copiedCert = nullptr;
BOOL result = CertAddCertificateContextToStore(certStore,
cert, CERT_STORE_ADD_REPLACE_EXISTING, &copiedCert);
CertFreeCertificateContext(cert);
if (result)
{
// Save the certificate to create a CTL entry later
trustedRoots.push_back(copiedCert);
}
...
// Creating the CTL entries
...
std::vector<LPSTR> usageList;
usageList.push_back(szOID_CTL); // I really do not know what IDs I must use here
...
CTL_INFO ctlInfo;
ZeroMemory(&ctlInfo, sizeof(ctlInfo));
ctlInfo.dwVersion = CTL_V1;
ctlInfo.SubjectUsage.cUsageIdentifier = static_cast<DWORD>(usageList.size());
ctlInfo.SubjectUsage.rgpszUsageIdentifier = usageList.data();
...
// Should I use any of the flags?
DWORD size = 0, flags = 0; /*CMSG_ENCODE_SORTED_CTL_FLAG | CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG;*/
if (CryptMsgEncodeAndSignCTL(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &ctlInfo, &encode, flags, nullptr, &size) == TRUE)
...
if (CertAddCTLContextToStore(certStore, ctlContext, CERT_STORE_ADD_REPLACE_EXISTING, nullptr) == TRUE)
{
// Check that the CTL is in the store and the root certificate is in the CTL
CTL_FIND_USAGE_PARA usagePara;
ZeroMemory(&usagePara, sizeof(usagePara));
usagePara.cbSize = sizeof(usagePara);
usagePara.SubjectUsage.cUsageIdentifier = 0;
usagePara.ListIdentifier.cbData = static_cast<DWORD>((ctlID.size() + 1) * sizeof(wchar_t));
usagePara.ListIdentifier.pbData = static_cast<BYTE*>(static_cast<void*>(const_cast<wchar_t*>(ctlID.data())));
PCCTL_CONTEXT foundCTLContext = CertFindCTLInStore(certStore,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CTL_FIND_USAGE,
static_cast<void*>(&usagePara), nullptr);
if (foundCTLContext != nullptr)
{
PCTL_ENTRY ctlEntry = CertFindSubjectInCTL(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
CTL_CERT_SUBJECT_TYPE, const_cast<void*>(*trustedRoots.begin()), foundCTLContext, 0);
if (ctlEntry != nullptr)
{
// It means the root certificate has been correctly added to the CTL and the CTL is in the store.
std::cout << "Found the certificate in the CTL" << std::endl;
}
}
// Make the certificate trusted via CertModifyCertificatesToTrust
HMODULE module = LoadLibrary(L"CryptDlg.dll");
if (module)
{
CertModifyCertificatesToTrustPfn pfn =
(CertModifyCertificatesToTrustPfn)GetProcAddress(hModule, "CertModifyCertificatesToTrust");
if (pfn != nullptr)
{
CTL_MODIFY_REQUEST req;
// Only one certificate is in the trustedRoots store curretly
req.pccert = static_cast<PCCERT_CONTEXT>(*trustedRoots.begin());
req.dwOperation = CTL_MODIFY_REQUEST_ADD_TRUSTED;
req.dwError = 0;
HRESULT hr = pfn(1, &req, szOID_CTL, NULL, certStore, nullptr);
if (hr == S_OK)
{
// Success
std::cout << "Modified" << std::endl;
}
}
}
}
您可以尝试使用以下api:CertModifyCertificateSTorust
请注意
此函数没有关联的导入库。您必须使用LoadGallery和GetProc地址函数来动态链接到CryptDlg.dll.
设置CTL\u MODIFY\u请求
dwOperation
到标志CTL\u MODIFY\u REQUEST\u ADD\u TRUSTED
将证书添加到CTL。证书是显式受信任的。
我遇到了一个奇怪的问题——供应商使用TLS SSLv3,同时使用自签名客户端和服务器证书。Java1.5和Java1.6没有这个问题——只需将客户端证书和私钥导入密钥库,将服务器公共证书导入信任库。一切都很好。然而,在Java7中,服务器证书无法被信任,即使使用的是同一个信任库。我尝试过使用Java7 (1.7.03, 04和05、x86和x64版本)的视窗和红帽,但没有成功。 我从头开始重新创建
目前,我在我的用户目录中的中有以下条目。 这将设置与git服务器交互时使用的证书(我公司的git服务器需要)。 但现在我无法克隆其他存储库(例如GitHub上的公共存储库),因为客户端总是使用配置好的证书,而该证书会被其他服务器拒绝。 我如何规避此认证问题?我可以将Git配置为使用Windows证书存储进行身份验证吗?
证书、私钥(客户端)和客户端证书都是pem格式的,我必须将它们添加到信任存储区和密钥存储区中。我该怎么做呢?到目前为止,我在cmd(windows)中有命令: > 要生成PKC(key:客户端私钥,cert:客户端cert,CA:CACERT):openssl pkcs12-inKey key.pem-in cert.pem-export-out keystored.p12-certfile CA
我有一个纯Java的应用程序,目前使用基于. jks的密钥和信任存储。据我所知,Bluemix下的SSL协议处理是在网络端使用单个端口和用于主机和域标识的通配符证书完成的。我关心的是信任存储的使用,在那里我用来添加可信伙伴节点的证书,例如身份提供者。是否有高级上传工具可以帮助安装受信任的证书?有了这些功能,Java可以将其功能限制在非常基本的HTTP实现上,并由云及其在动态端口上发生的HTTP到H
我想写一些可以枚举和使用(签名)证书在货币用户/我和LocalMachine/我,但我还没有能够找到任何Windows证书存储,只有Java自己的秘密存储。这个链接看起来很有希望,但我只能使用Java。 我以前在SO上发现过这个问题,但这是五年前的问题,在计算机时代是很长的时间了。谢谢!
问题内容: 我有一个Web应用程序,该应用程序调用通过SSL保护的SOAP Web服务。)。 服务器发送两个证书(Root和Leaf),因此我使用属性导入了两个证书:。 要在Websphere上启用ssl验证,我只需将证书添加到websphere中: SSL证书和密钥管理->密钥库和证书-> NodeDefaultTrustStore->签署者证书->从端口检索: 主机:主机名 端口:443 别名