CryptoAPI將證書實體新增到證書庫

凝望著發表於2015-05-04

檢視電腦上安裝過的證書方法

IE瀏覽器 點選【工具】——>【Internet選項】——>【內容】——>【證書】 如下圖所示 enter image description here

下面示例中的證書是在中國鐵路12306上下載

主要運用到的方法為 CryptStringToBinaryA、CertCreateCertificateContext、CertOpenStore、CertAddCertificateContextToStore、CertCloseStore、CertFreeCertificateContext

只用介紹兩個方法即可

CertCreateCertificateContext函式原型:

    PCCERT_CONTEXT WINAPI CertCreateCertificateContext(
      _In_       DWORD dwCertEncodingType,
      _In_ const BYTE  *pbCertEncoded,
      _In_       DWORD cbCertEncoded
    );
功能:
      將證書實體轉化為證書上下文結構
引數:
      dwCertEncodingType  指定所用編碼型別
      pbCertEncoded       指向證書實體緩衝區的指標
      cbCertEncoded       這裡其實就是長度

CertAddCertificateContextToStore函式原型

    BOOL WINAPI CertAddCertificateContextToStore(
     _In_      HCERTSTORE     hCertStore,
     _In_      PCCERT_CONTEXT pCertContext,
     _In_      DWORD          dwAddDisposition,
     _Out_opt_ PCCERT_CONTEXT *ppStoreContext
    );

功能:
     將證書上下文新增到證書儲存區
引數:
     hCertStore           證書儲存庫控制程式碼
     pCertContext         指向要新增到儲存區的 CERT_CONTEXT 結構的指標
     dwAddDisposition     指定如果匹配的證書或連結到匹配的證書儲存區中已經存在要執行的操作
     ppStoreContext       指向新增到儲存區的證書副本的指標的指標。

接下來用VC++6.0做個例子 新手入門

新建Win32 Application 工程 enter image description here 【下一步】——>【A simple Win32 application】完成後如下: enter image description here

新增以下完整程式碼:

#include <malloc.h>
#include <WinCrypt.h>
#pragma comment(lib,"crypt32.lib")
#define ENCODING_TYPE (PKCS_7_ASN_ENCODING |X509_ASN_ENCODING)

//以下為12306的SRCA base64證書實體
const char * SRCARootCert = " -----BEGIN CERTIFICATE-----\
                        MIICmjCCAgOgAwIBAgIIbyZr5/jKH6QwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE\
                        BhMCQ04xKTAnBgNVBAoTIFNpbm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5\
                        MQ0wCwYDVQQDEwRTUkNBMB4XDTA5MDUyNTA2NTYwMFoXDTI5MDUyMDA2NTYwMFow\
                        RzELMAkGA1UEBhMCQ04xKTAnBgNVBAoTIFNpbm9yYWlsIENlcnRpZmljYXRpb24g\
                        QXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\
                        iQKBgQDMpbNeb34p0GvLkZ6t72/OOba4mX2K/eZRWFfnuk8e5jKDH+9BgCb29bSo\
                        tqPqTbxXWPxIOz8EjyUO3bfR5pQ8ovNTOlks2rS5BdMhoi4sUjCKi5ELiqtyww/X\
                        gY5iFqv6D4Pw9QvOUcdRVSbPWo1DwMmH75It6pk/rARIFHEjWwIDAQABo4GOMIGL\
                        MB8GA1UdIwQYMBaAFHletne34lKDQ+3HUYhMY4UsAENYMAwGA1UdEwQFMAMBAf8w\
                        LgYDVR0fBCcwJTAjoCGgH4YdaHR0cDovLzE5Mi4xNjguOS4xNDkvY3JsMS5jcmww\
                        CwYDVR0PBAQDAgH+MB0GA1UdDgQWBBR5XrZ3t+JSg0Ptx1GITGOFLABDWDANBgkq\
                        hkiG9w0BAQUFAAOBgQDGrAm2U/of1LbOnG2bnnQtgcVaBXiVJF8LKPaV23XQ96HU\
                        8xfgSZMJS6U00WHAI7zp0q208RSUft9wDq9ee///VOhzR6Tebg9QfyPSohkBrhXQ\
                        envQog555S+C3eJAAVeNCTeMS3N/M5hzBRJAoffn3qoYdAO1Q8bTguOi+2849A==\
                        -----END CERTIFICATE-----";

int APIENTRY WinMain(HINSTANCE hInstance,
                 HINSTANCE hPrevInstance,
                 LPSTR     lpCmdLine,
                 int       nCmdShow)
{
unsigned char* pbCertData = NULL;
unsigned long dwCertData = 0;
PCCERT_CONTEXT m_pctx = NULL;
HCERTSTORE hStore;    
unsigned long dwRootCert = 0;
dwRootCert = strlen(SRCARootCert);


if (!CryptStringToBinaryA(SRCARootCert,dwRootCert,CRYPT_STRING_BASE64HEADER,NULL,&dwCertData,NULL,NULL))
{
    MessageBox(NULL,"獲取解碼資料長度失敗","提示",MB_OK);
    return FALSE;
}

pbCertData = (unsigned char*)malloc(dwCertData);
if (pbCertData!=NULL)
{
    memset(pbCertData,0x00,dwCertData);
}else{
    MessageBox(NULL,"記憶體分配失敗","提示",MB_OK);
    return FALSE;
}

if (!CryptStringToBinaryA(SRCARootCert,dwRootCert,CRYPT_STRING_BASE64HEADER,pbCertData,&dwCertData,NULL,NULL))
{

    MessageBox(NULL,"Base64解碼失敗","提示",MB_OK);
    free(pbCertData);
    pbCertData = NULL;
    return FALSE;
}


m_pctx = CertCreateCertificateContext(ENCODING_TYPE,pbCertData,dwCertData);
if(m_pctx == NULL)
{
    MessageBox(NULL,"CERT_CONTEXT結構轉換失敗","提示",MB_OK);
    free(pbCertData);
    pbCertData = NULL;
    return FALSE;
}

hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM, 
                        0, 
                        0, 
                        CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE,
                        L"root");//my 個人  ca 中間證書頒發機構 root 受信任的根證書頒發機構
                                 //顯然中國鐵路的根證書要安裝在root裡面
if (!hStore)
{
    CertFreeCertificateContext(m_pctx);
    free(pbCertData);
    pbCertData = NULL;
    return FALSE;
}
if(!CertAddCertificateContextToStore(hStore, m_pctx, CERT_STORE_ADD_NEW, 0))
{

    DWORD err = GetLastError();
    if (CRYPT_E_EXISTS == err)
    {
        MessageBox(NULL,"該證書已經安裝過","提示",MB_OK);
        CertFreeCertificateContext(m_pctx);
        CertCloseStore(hStore,0);
        free(pbCertData);
        pbCertData = NULL;
        return FALSE;
    }
}else
{
    MessageBox(NULL,"證書安裝成功","提示",MB_OK);
}

if (m_pctx)
    CertFreeCertificateContext(m_pctx);
if (hStore)
    CertCloseStore(hStore,0);    

if (pbCertData)
 {
    free(pbCertData);
    pbCertData = NULL;
 }
return 0;
}

Release編譯後,

劃擦!一個可執行的程式生成了,簡單的方法向root證新增根證書,只需要雙擊程式,

而不是12306網站上的下載中的word文件裡面的八個步驟。

安裝方法在這,可以自行封裝成lib靜態庫、dll動態庫、com元件等等。

我只會這點,不能再多了……

相關文章