我在服务器和客户端之间使用基于证书的身份验证。我已经生成了根证书。我的客户端在安装时将生成一个新证书并使用根证书对其进行签名。我需要使用Windows API。不能使用像makecert这样的任何windows工具。
直到现在我已经能够在商店中安装Root证书了。代码
X509Certificate2 ^ certificate = gcnew X509Certificate2("C:\\rootcert.pfx","test123");
X509Store ^ store = gcnew X509Store( "teststore",StoreLocation::CurrentUser );
store->Open( OpenFlags::ReadWrite );
store->Add( certificate );
store->Close();
然后打开已安装的根证书以获取上下文
GetRootCertKeyInfo(){
HCERTSTORE hCertStore;
PCCERT_CONTEXT pSignerCertContext=NULL;
DWORD dwSize = NULL;
CRYPT_KEY_PROV_INFO* pKeyInfo = NULL;
DWORD dwKeySpec;
if ( !( hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER,L"teststore")))
{
_tprintf(_T("Error 0x%x\n"), GetLastError());
}
pSignerCertContext = CertFindCertificateInStore(hCertStore,MY_ENCODING_TYPE,0,CERT_FIND_ANY,NULL,NULL);
if(NULL == pSignerCertContext)
{
_tprintf(_T("Error 0x%x\n"), GetLastError());
}
if(!(CertGetCertificateContextProperty( pSignerCertContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwSize)))
{
_tprintf(_T("Error 0x%x\n"), GetLastError());
}
if(pKeyInfo)
free(pKeyInfo);
if(!(pKeyInfo = (CRYPT_KEY_PROV_INFO*)malloc(dwSize)))
{
_tprintf(_T("Error 0x%x\n"), GetLastError());
}
if(!(CertGetCertificateContextProperty( pSignerCertContext, CERT_KEY_PROV_INFO_PROP_ID, pKeyInfo, &dwSize)))
{
_tprintf(_T("Error 0x%x\n"), GetLastError());
}
return pKeyInfo;
}
然后最终创建了证书并使用pKeyInfo
签名 // Acquire key container
if (!CryptAcquireContext(&hCryptProv, _T("trykeycon"), NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
{
_tprintf(_T("Error 0x%x\n"), GetLastError());
// Try to create a new key container
_tprintf(_T("CryptAcquireContext... "));
if (!CryptAcquireContext(&hCryptProv, _T("trykeycon"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET))
{
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}
}
else
{
_tprintf(_T("Success\n"));
}
// Generate new key pair
_tprintf(_T("CryptGenKey... "));
if (!CryptGenKey(hCryptProv, AT_SIGNATURE, 0x08000000 /*RSA-2048-BIT_KEY*/, &hKey))
{
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}
//some code
CERT_NAME_BLOB SubjectIssuerBlob;
memset(&SubjectIssuerBlob, 0, sizeof(SubjectIssuerBlob));
SubjectIssuerBlob.cbData = cbEncoded;
SubjectIssuerBlob.pbData = pbEncoded;
// Prepare algorithm structure for self-signed certificate
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm));
SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA;
// Prepare Expiration date for self-signed certificate
SYSTEMTIME EndTime;
GetSystemTime(&EndTime);
EndTime.wYear += 5;
// Create self-signed certificate
_tprintf(_T("CertCreateSelfSignCertificate... "));
CRYPT_KEY_PROV_INFO* aKeyInfo;
aKeyInfo = GetRootCertKeyInfo();
pCertContext = CertCreateSelfSignCertificate(NULL, &SubjectIssuerBlob, 0, aKeyInfo, &SignatureAlgorithm, 0, &EndTime, 0);
使用上面的代码,我可以创建证书,但它看起来不会被根证书签名。我无法确定我所做的是对还是不对.. 非常感谢任何帮助。
由于 阿西
答案 0 :(得分:1)
我认为您不需要自签名证书。您想创建一个由“根”证书签名的新“客户”证书,对吗?我认为您需要使用CryptSignAndEncodeCertificate来执行此操作。
答案 1 :(得分:1)
首先,几年前我写了一些产品,其中还包含您要求的完整代码:创建新证书并根据其他根证书对其进行签名。此代码仅使用 Microsoft CryptoAPI 。但在我给你详细解答或发布一些我想知道的代码之前,你的问题是否真实:你的问题已经有一个半月了。
一般来说,为了做你想做的事,不应该使用CertCreateSelfSignCertificate()
函数,而是创建一个关于其他CryptoAPI的证书。 CertCreateSelfSignCertificate()
函数只能用于创建和签署自签名证书。它无法使用您创建的其他证书签署证书。此外,CertCreateSelfSignCertificate()
函数(或至少在几年前)对创建的私钥的长度进行了严格的限制。因此,必须做出CertCreateSelfSignCertificate()
函数手动执行的相同操作。 API链中的最后一个API是CryptSignAndEncodeCertificate()
,就像你在另一个问题上写的那样回答了你的问题。
此外,我有一个大的嫌疑人,为您的目的创建证书链是不正确的方式。如果只需要进行身份验证,则无需在客户端创建证书。在我看来,使用有罪信息就足够了。一个使用证书而不是密钥对的情况是,您需要关键撤销或密钥限制等功能,仅用于某些目的(例如,仅用于代码签名而不用于数据加密)。
如果您确实需要实施基于认证的身份验证,那么至少您必须创建客户端计算机的证书,将其发送到服务器计算机并在服务器计算机上唱出客户端证书,因为只有服务器计算机可以保存私钥根证书。
您还可以根据证书注册API 实施您的要求吗?它不是你要求的,但它可以解决你的主要问题。
回答其他问题(评论): 要么我不理解您计划实现的构造为“双向认证”或概念是错误的。
我可以写更多我的问题。如果你实施他自己的基于证书的通信协议,那么在我理解你的概念之前,我有很大的问题要提出我的建议。