如何将USBKey中的证书注册到Windows系统中、分享一个 证书 C++安装

USBKey是一种USB接口的硬件设备。如坚石诚信的ET199Auto,内置16位国外进口高性能智能卡芯片,有一定的存储空间,可以存储用户的私钥以及数字证书,利用USBKey内置的RSA公私钥算法实现对用户身份的认证。由于用户私钥保存在ET199Auto中,同时智能卡可以很好的防止物理攻击/边频攻击等窃取手段,从而有效保证任何方式都无法读取ET199Auto中的私钥,因此保证了用户认证的安全性。

目前,USBKey已广泛应用在网上银行,网上办公,证券交易,网络游戏等众多系统中。那么USBKey又怎么与应用系统连接而进行身份认证的呢?实际上,USBKey中存储着代表用户身份的数字证书。

一张数字证书包括:证书信息+公钥+私钥,其中证书+公钥是可以公开的,私钥是在USBKey中,任何人都无法获取的。当USBKey插入计算机后,USBKey厂商提供的中间件程序会将证书信息注册到Windows系统中,应用系统中在认证时通过Windows系统找到用户证书该证书通过USBKey厂商的中间件找到USBKey中对应的私钥,然后在USBKey中使用私钥进行签名运算,将结果传给服务器认证。过程如下:

网银àWindows系统中用户证书àUSBKey中间件à私钥签名à服务器验证

本篇文章就介绍一下如何使用微软CAPI接口完成将USBKey中的证书注册到Windows系统中。


(1)        获取CSP句柄。

CryptAcquireContext(
&hTokenProv,NULL,
“EnterSafe ET199Auto CSP V1.0”, 
PROV_RSA_FULL,
NULL)

(2)        获取USBKey内密钥句柄,这时要注意锁内密钥的类型是签名密钥(AT_SIGNATURE)或者交换密钥(AT_KEYEXCHANGE)。

CryptGetUserKey(hTokenProv,AT_KEYEXCHANGE,&hKeyCAPI)

(3)        获取证书数据(只是证书信息数据,不包括私钥),这时可以通过两次调用,先获取证书数据的长度,分配空间,然后再调用一次。

CryptGetKeyParam(hKeyCAPI, KP_CERTIFICATE, pbCert, &dwCertLen, 0)

(4)        创建CERT_CONTEXT结构

pCertContext = CertCreateCertificateContext(
                PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                pbCert,
                dwCertLen)


//+-------------------------------------------------------------------------
//  Certificate context.
//
//  A certificate context contains both the encoded and decoded representation
//  of a certificate. A certificate context returned by a cert store function
//  must be freed by calling the CertFreeCertificateContext function. The
//  CertDuplicateCertificateContext function can be called to make a duplicate
//  copy (which also must be freed by calling CertFreeCertificateContext).
//--------------------------------------------------------------------------
// certenrolls_begin -- CERT_CONTEXT
typedef struct _CERT_CONTEXT {
    DWORD                   dwCertEncodingType;
    BYTE                    *pbCertEncoded;
    DWORD                   cbCertEncoded;
    PCERT_INFO              pCertInfo;
    HCERTSTORE              hCertStore;
} CERT_CONTEXT, *PCERT_CONTEXT;
typedef const CERT_CONTEXT *PCCERT_CONTEXT;


(5)        打开MY存储区,这个就是Windows系统中“个人”证书存放的区域。

hSysStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_REGISTRY,
        0,
        0,
        CERT_SYSTEM_STORE_CURRENT_USER,
        L"MY");

(6)        设置证书上下文属性。这时要先声明CRYPT_KEY_PROV_INFO结构

CRYPT_KEY_PROV_INFO ckpi = {0};

        ckpi.pwszProvName = L" EnterSafe ET199Auto CSP V1.0";
        ckpi.pwszContainerName = pbWideContainer;
        ckpi.dwProvType = PROV_RSA_FULL;
        ckpi.dwKeySpec = AT_KEYEXCHANGE;
        ckpi.dwFlags = CERT_KEY_CONTEXT_PROP_ID;
        ckpi.cProvParam = 0;
        ckpi.rgProvParam = NULL;

CertSetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG, 
&ckpi)

(7)        将证书注册到Windows系统中。

CertAddCertificateContextToStore(
hSysStore,
        pCertContext,
        CERT_STORE_ADD_REPLACE_EXISTING,
        NULL);

(8)        释放CSP句柄。

CryptReleaseContext(hTokenProv,0)

通过上述步骤就可以将ET199Auto中的证书注册到Windows系统中了。我们可以在IEInternet选项内容证书个人下面查看到ET199Auto中的证书。

以上系转载,感谢原作者。


========================================================================

今天写了一个关于证书安装的程序,现在把主要代码分享出来!
注:
   在读取到证书文件,如果是 BASE64 文件,就需要通过 CryptStringToBinaryA 转化成 二进制,然后再CertCreateCertificateContext,才能成功,不然会 出现 CRYPT_E_ASN1_BADTAG 错误!

#include "stdafx.h"
#include "CertImportx.h"

#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)


void CCertImport::PrintfError(DWORD err , LPCTSTR szError)
{
    if( err == 0 )
    {
        MessageBox(NULL,_T("安装成功!"),_T("证书安装"),MB_OK);
    }
    else
    {//
        MessageBox(NULL,_T("安装失败!"),_T("证书安装"),MB_OK);
    }
}

// Global function for free handles...
void CCertImport::FreeHandles(HCERTSTORE hFileStore, PCCERT_CONTEXT pctx,     HCERTSTORE pfxStore, HCERTSTORE myStore )
{

    if (myStore)
        CertCloseStore(myStore, 0);

    if (pfxStore)
        CertCloseStore(pfxStore, CERT_CLOSE_STORE_FORCE_FLAG);

    if(pctx)
        CertFreeCertificateContext(pctx);

    if (hFileStore)
        CertCloseStore(hFileStore, 0);
}

int CCertImport::ImportCACert()
{
    const char* pCert= "-----BEGIN CERTIFICATE-----\
                       MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML\
                       RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp\
                       bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5\
                       IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp\
                       ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy\
                       MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3\
                       LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp\
                       YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG\
                       A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp\
                       MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq\
                       K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe\
                       sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX\
                       MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT\
                       XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/\
                       HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH\
                       4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA\
                       vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G\
                       CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA\
                       WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo\
                       oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ\
                       h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18\
                       f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN\
                       B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy\
                       vUxFnmG6v4SBkgPR0ml8xQ==\
                       -----END CERTIFICATE-----";

    BYTE pBinByte[8192]={0};
    unsigned long binBytes = 4096;

    CryptStringToBinaryA( pCert , strlen(pCert) ,CRYPT_STRING_BASE64HEADER , pBinByte , &binBytes ,NULL,NULL);

    return ImportCACert(pBinByte , binBytes );
}

// This function imports a CA certificate...
int CCertImport::ImportCACert(LPCTSTR szFileName)
{
    HANDLE hfile = INVALID_HANDLE_VALUE;

    BYTE pByte[4096] = {0} , pBinByte[8192]={0};
    unsigned long bytesRead = 0;
    unsigned long binBytes = 4096;

    // Open it...
    hfile = CreateFile(szFileName, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    if (INVALID_HANDLE_VALUE == hfile)
        return -1;
   
    ReadFile( hfile , pByte, 4096, &bytesRead ,NULL );
    CloseHandle(hfile);

    CryptStringToBinaryA( (LPCSTR)pByte , bytesRead ,CRYPT_STRING_BASE64HEADER , pBinByte , &binBytes ,NULL,NULL);

    return ImportCACert(pBinByte , binBytes );
}

int CCertImport::ImportCACert(BYTE* pBinByte , unsigned long binBytes)
{
    HCERTSTORE pfxStore = 0;
    HCERTSTORE myStore = 0;
    HCERTSTORE hFileStore = 0;
    PCCERT_CONTEXT pctx = NULL;
    DWORD err = 0;

    pctx = CertCreateCertificateContext(MY_ENCODING_TYPE, (BYTE*)pBinByte , binBytes );
    if(pctx == NULL)
    {
        DWORD err = GetLastError();
        FreeHandles(hFileStore,pctx, pfxStore, myStore);   
        PrintfError( err ,  _T("Error in 'CertCreateCertificateContext'") );
        return err;
    }

    // we open the store for the CA
    hFileStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Root" );
    if (!hFileStore)
    {
        DWORD err = GetLastError();
        FreeHandles(hFileStore,pctx, pfxStore, myStore);   
        PrintfError( err ,  _T("Error in 'CertOpenStore'") );
        return err;
    }

    if( !CertAddCertificateContextToStore(hFileStore, pctx, CERT_STORE_ADD_NEW, 0) )
    {
        err = GetLastError();
        if( CRYPT_E_EXISTS == err )
        {
//            if( AfxMessageBox("An equivalent previous personal certificate already exists. Overwrite ? (Yes/No)", MB_YESNO) == IDYES)
            {
                if( !CertAddCertificateContextToStore(hFileStore, pctx , CERT_STORE_ADD_REPLACE_EXISTING, 0))
                {
                    err = GetLastError();
                    FreeHandles(hFileStore,pctx, pfxStore, myStore);
                    PrintfError( err ,  _T("Error in 'CertAddCertificateContextToStore'") );                       
                    return err;
                }
            }
        }
        else
        {
            FreeHandles(hFileStore, pctx , pfxStore , myStore);
            PrintfError( err ,  _T("Error in 'CertAddCertificateContextToStore'") );
            return err;
        }
    }
    FreeHandles(hFileStore,pctx, pfxStore, myStore);
    PrintfError(0 , NULL) ;
    return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值