记录成功通过CSP接口获取Ukey的X509数字证书过程
生活随笔
收集整理的這篇文章主要介紹了
记录成功通过CSP接口获取Ukey的X509数字证书过程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
記錄成功通過CSP接口獲取Ukey的X509數字證書過程
- 通過CSP接口獲取X509數字證書
- 首先確定調用流程
- 悲催過程
- 問題解決
- 補充
- 調用過程代碼
- LastError()解析
通過CSP接口獲取X509數字證書
所謂CPS接口其實就是windowAPI ,其實就是wincrypt.h提供的接口,Visual Studio 直接包含以下內容即可
#include<wincrypt.h> #pragma comment(lib,"Crypt32")首先確定調用流程
開始通過百度總結調用流程如下:
調用流程 /* 1.CryptAcquireContext 2.CryptGetUserKey 3.CryptGetKeyParam 4.CertCreateCertificateContext 5.CryptDestroyKey 6.CryptReleaseContext */悲催過程
- 擼擼擼,把6個過程實現完,開始測試,走到第二步CryptGetUserKey就返回失敗了,通過LastError提示找不到對象。把AT_SIGNATURE : AT_KEYEXCHANGE兩個類型都試了不行。看到由的文章說如果找不到那就調用CryptGenKey,去生成一個key。成功返回key了,下一個CryptGetKeyParam時候找不到了。
- 在試了幾次,尼瑪,直接把我Ukey里面的證書損壞了…
問題解決
首先ukey里面是存在多個容器的,一般證書都不會在這個默認容器里面,所以CryptGetUserKey就失敗了。解決辦法:首先進行枚舉容器,把ukey里面的容器都枚舉出來。在根據容器名稱循環調用上面6個流程,最終把x509證書讀出來了。
//枚舉容器過程if (CryptAcquireContext(&hCryptProv, // Handle to the CSPNULL, // Container namemProviderName, // Use the default providerPROV_RSA_FULL, // Provider typeCRYPT_NEWKEYSET)) // Flag values{BYTE pbData[1000]; // 1000 will hold the longestDWORD cbData = 1000;int count = 0;if (CryptGetProvParam(hCryptProv,PP_ENUMCONTAINERS,(BYTE*)& pbData,&cbData,CRYPT_FIRST)){pbData[cbData] = '\0';printf("%d. ContainName is %s\n", count++, pbData);contain_vector.push_back((char*)pbData);pbData[0] = '\0';cbData = 1000;while (CryptGetProvParam(hCryptProv,PP_ENUMCONTAINERS,(BYTE*)& pbData,&cbData,CRYPT_NEXT)){if (ERROR_NO_MORE_ITEMS == GetLastError()){break;}pbData[cbData] = '\0';printf("%d. ContainName is %s\n", count++, pbData);contain_vector.push_back((char*)pbData);pbData[0] = '\0';cbData = 1000;}}}補充
調用過程代碼
BOOL CryptHelper::GetPublicKey(LPCSTR containName, BYTE** certInfo, DWORD& certLength, LPTSTR& message) {//1.獲得一個CSP句柄HCRYPTPROV hCryptProv;printf("csp name:%s;contain name:%s.\n", mProviderName, containName);BOOL res = CryptAcquireContext(&hCryptProv, containName, mProviderName, PROV_RSA_FULL, 0);if (!res) //如果沒有可用CSP{GetErrorToString(TEXT("CryptAcquireContext"), message);printf(message);return FALSE;}//2.獲取簽名秘鑰HCRYPTKEY hKey;res = CryptGetUserKey(hCryptProv, mAlgId, &hKey);if (!res) //沒有可用的簽名秘鑰{GetErrorToString(TEXT("CryptGetUserKey"), message);printf(message);return FALSE;}//3.獲取證書參數DWORD dwCertLen = 2048;BYTE* pbCert = (BYTE*)malloc(dwCertLen);res = CryptGetKeyParam(hKey, KP_CERTIFICATE, pbCert, &dwCertLen, 0);if (!res){GetErrorToString(TEXT("CryptGetKeyParam"), message);printf(message);return FALSE;}//4.導出證書if (pbCert){PCCERT_CONTEXT pCertContext = NULL;pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbCert, dwCertLen);if (pCertContext){message = "success";certLength = dwCertLen;*certInfo = (BYTE*)malloc(certLength);memcpy(*certInfo, pbCert, certLength);CHAR pszBuff[256];CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE,0, NULL, pszBuff, 128);printf("%s\n", pszBuff); // 顯示名//7.釋放證書CertFreeCertificateContext(pCertContext);}else{GetErrorToString(TEXT("CertCreateCertificateContext"), message);printf(message);return FALSE;}}//6.釋放key;if (hKey){CryptDestroyKey(hKey);printf("The hKey could be released.\n");}//7.釋放容器if (hCryptProv){CryptReleaseContext(hCryptProv, 0);printf("The hCryptProv could be released.\n");}return TRUE; }LastError()解析
lastError()方法放回的是錯誤碼,具體什么錯誤并不知道。具體通過FormatMessage解析
BOOL CryptHelper::GetErrorToString(LPTSTR funcName, LPTSTR& Message) {DWORD lastError = GetLastError();LPVOID lpMsgBuf;LPVOID lpDisplayBuf;FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,NULL,lastError,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)& lpMsgBuf,0, NULL);lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)funcName) + 40) * sizeof(TCHAR));StringCchPrintf((LPTSTR)lpDisplayBuf,LocalSize(lpDisplayBuf),TEXT("%s failure with error %d: %s"),funcName, lastError, lpMsgBuf);Message = (LPTSTR)lpDisplayBuf;LocalFree(lpMsgBuf);LocalFree(lpDisplayBuf);return TRUE; }總結
以上是生活随笔為你收集整理的记录成功通过CSP接口获取Ukey的X509数字证书过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html静态页面作业 我的家乡网站设计—
- 下一篇: vue 局部回到顶部_vue中回到顶部