日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

记录成功通过CSP接口获取Ukey的X509数字证书过程

發布時間:2024/8/1 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 记录成功通过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;}}}

補充

  • cps ukey的providerName 一般為:eSafe Cryptographic Service Provider v1.0
  • 可以通過注冊表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider 查看具體的Provider.
  • CertCreateCertificateContext 出參BYTE * pbCert就是x509證書的二進制,可以直接通過其他x509證書解析庫解析。也可以通過CertGetNameString解析證書相關信息。
  • pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbCert, dwCertLen);

    調用過程代碼

    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数字证书过程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。