如何使用根证书签署我的证书?

我在我的服务器和客户端之间使用基于证书的authentication。 我已经生成了根证书。 我的客户在安装时会生成一个新的证书,并使用根证书对其进行签名。 我需要使用Windows API。 不能使用任何Windows工具,如makecert。

到目前为止,我已经能够在商店中安装根证书。 下面的代码

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; } 

然后最终创build了证书并使用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); 

通过上面的代码,我可以创build证书,但看起来不是由根证书签名的。 我无法确定我所做的是正确与否..任何帮助,不胜感激..

谢谢阿西夫

首先几年前,我写了一些产品,其中也包含您要求的完整代码:创建一个新的证书并在其他根证书上签名。 此代码只使用Microsoft CryptoAPI 。 但是,在我给你详细的答案或发布一些代码之前,我想知道,你的问题是否是真实的:你的问题是一个半月大。

一般来说,要做你想做的事情,不要使用CertCreateSelfSignCertificate()函数,而要创建一个关于其他CryptoAPI的证书。 CertCreateSelfSignCertificate()函数只能用于创建和签名自签名证书。 它不能使用您创建的其他证书签署证书。 而且, CertCreateSelfSignCertificate()函数对创建的私钥的长度有一个严格的限制(至少在几年之前)。 因此,人们必须手动完成CertCreateSelfSignCertificate()函数所做的相同的事情。 在API的最后一个API是什么一个是CryptSignAndEncodeCertificate()就像在另一个答案写在你的问题卢克。

而且我有一个很大的嫌疑,那就是为了你的目的创建一个证书链是不正确的。 如果您只需要进行身份验证,则不需要在客户端创建证书。 在我看来,这将是足够的工作与单片消息。 一个使用证书而不是密钥对的情况下,您需要使用某些功能(例如仅用于代码签名而不用于数据加密)的密钥撤销或密钥限制等功能。

如果您确实需要实施基于认证的身份验证,那么您至少必须创建客户端计算机的证书,将其发送到服务器计算机,并在服务器计算机上唱客户端证书,因为只有服务器计算机可以持有根证书的私钥。

也可以通过证书注册API来实现您的要求? 这不会是你所要求的,但它可以解决你的主要问题。

对其他问题的回答(评论) :我不明白你打算实现的构造是“双向认证”还是这个概念是错误的。

  1. 我不明白如何以及何时规划从所有客户端到服务器的传输根客户端证书。
  2. 你想用客户机根CA来签署客户机证书,所以你必须在客户机上保存客户机根CA证书的私钥(!!! ???)。
  3. 如果服务器没有任何关于客户端的验证信息,比如它的根CA证书,那么您不能真正使用客户端证书进行客户端授权。 任何拥有证书的客户都将被“授权”。
  4. 使用没有客户端证书的标准SSL,您可以确保您始终与同一个客户端进行通信。 所以,如果你不解决客户端根CA传输到服务器的问题,那么你将无法像在标准(没有客户端证书)的SSL那样获得更高的安全性。
  5. 你写的东西好像你不想在服务器和客户端之间使用标准的通信协议。 而不是你试图引入一个新的自己的协议。 这是非常危险的! 如果你不是一个密码学专家,你会实现一个看起来像安全的协议,而不是这样。 诸如私钥的保存,客户端到服务器或公钥的安全传输等“小”问题是非常重要的密码主题。 这里有不同的密码协议。 所以不要试图在这个领域实施新的东西!
  6. 再想一想为什么你真的想使用客户端证书。 你真的用这种方式实现客户端认证吗? 例如,在标准的SSL中,可以肯定的是,一个人与相同的客户端进行通信,并为此使用随机的随机数和为会话生成的对称密钥。 您是否想要为每个客户端或每个会话生成证书?

我可以写更多的问题。 如果你实施他自己的基于证书的通信协议,在理解你的概念之前,我有很大的问题给我推荐。

我不认为自己签署的证书是你在这里所需要的。 你想创建一个由你的“根”证书签名的新“客户”证书,对吗? 我想你需要使用CryptSignAndEncodeCertificate来做到这一点。