写入证书到USBKEY

来源:互联网 发布:椭圆机品牌 知乎 编辑:程序博客网 时间:2024/04/30 04:16
// ZdActivexCtrl.cpp : CZdActivexCtrl ActiveX 控件类的实现。

#include "stdafx.h"
#include "ZdActivex.h"
#include "ZdActivexCtrl.h"
#include "ZdActivexPropPage.h"
#include "afxdialogex.h"
#include <stdio.h>
#include <windows.h>
#include <wininet.h>

#define MAXSIZE 4096
#pragma comment(lib, "Wininet.lib")

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//CSP
#include <wincrypt.h>
#pragma comment(lib,"crypt32.lib")

#define MALLOC(l) (BYTE*)malloc(l)



IMPLEMENT_DYNCREATE(CZdActivexCtrl, COleControl)

// 消息映射

BEGIN_MESSAGE_MAP(CZdActivexCtrl, COleControl)
    ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()



// 调度映射

BEGIN_DISPATCH_MAP(CZdActivexCtrl, COleControl)
    DISP_FUNCTION_ID(CZdActivexCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
    DISP_FUNCTION_ID(CZdActivexCtrl, "ImportPFX", dispidImportPFX, ImportPFX, VT_EMPTY, VTS_BSTR VTS_BSTR VTS_BSTR VTS_BSTR)
    DISP_FUNCTION_ID(CZdActivexCtrl, "DownLoadToLocal", dispidDownLoadToLocal, DownLoadToLocal, VT_I4, VTS_BSTR VTS_BSTR)
    DISP_FUNCTION_ID(CZdActivexCtrl, "ImportExchangePFX", dispidImportExchangePFX, ImportExchangePFX, VT_EMPTY, VTS_BSTR VTS_BSTR VTS_BSTR VTS_BSTR)
    DISP_FUNCTION_ID(CZdActivexCtrl, "EnumCspProvider", dispidEnumCspProvider, EnumCspProvider, VT_BSTR, VTS_NONE)
END_DISPATCH_MAP()



// 事件映射

BEGIN_EVENT_MAP(CZdActivexCtrl, COleControl)
END_EVENT_MAP()



// 属性页

// TODO: 按需要添加更多属性页。请记住增加计数!
BEGIN_PROPPAGEIDS(CZdActivexCtrl, 1)
    PROPPAGEID(CZdActivexPropPage::guid)
END_PROPPAGEIDS(CZdActivexCtrl)



// 初始化类工厂和 guid

IMPLEMENT_OLECREATE_EX(CZdActivexCtrl, "ZDACTIVEX.ZdActivexCtrl.1",
    0x5f0ece95, 0x9bbb, 0x4f87, 0xb2, 0xc6, 0x2d, 0x7e, 0xb0, 0xf0, 0xf4, 0x54)



// 键入库 ID 和版本

IMPLEMENT_OLETYPELIB(CZdActivexCtrl, _tlid, _wVerMajor, _wVerMinor)



// 接口 ID

const IID IID_DZdActivex = { 0xA8294AA6, 0x8C40, 0x4029, { 0xB9, 0x5E, 0xAB, 0x71, 0xFC, 0xC, 0xB7, 0xEF } };
const IID IID_DZdActivexEvents = { 0x47A58B2B, 0xCDD8, 0x4BF9, { 0xBB, 0xE3, 0x13, 0xDB, 0x32, 0xB8, 0x5E, 0x6A } };


// 控件类型信息

static const DWORD _dwZdActivexOleMisc =
    OLEMISC_ACTIVATEWHENVISIBLE |
    OLEMISC_SETCLIENTSITEFIRST |
    OLEMISC_INSIDEOUT |
    OLEMISC_CANTLINKINSIDE |
    OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CZdActivexCtrl, IDS_ZDACTIVEX, _dwZdActivexOleMisc)



// CZdActivexCtrl::CZdActivexCtrlFactory::UpdateRegistry -
// 添加或移除 CZdActivexCtrl 的系统注册表项

BOOL CZdActivexCtrl::CZdActivexCtrlFactory::UpdateRegistry(BOOL bRegister)
{
    // TODO: 验证您的控件是否符合单元模型线程处理规则。
    // 有关更多信息,请参考 MFC 技术说明 64。
    // 如果您的控件不符合单元模型规则,则
    // 必须修改如下代码,将第六个参数从
    // afxRegApartmentThreading 改为 0。

    if (bRegister)
        return AfxOleRegisterControlClass(
            AfxGetInstanceHandle(),
            m_clsid,
            m_lpszProgID,
            IDS_ZDACTIVEX,
            IDB_ZDACTIVEX,
            afxRegApartmentThreading,
            _dwZdActivexOleMisc,
            _tlid,
            _wVerMajor,
            _wVerMinor);
    else
        return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}



// CZdActivexCtrl::CZdActivexCtrl - 构造函数

CZdActivexCtrl::CZdActivexCtrl()
{
    InitializeIIDs(&IID_DZdActivex, &IID_DZdActivexEvents);
    // TODO: 在此初始化控件的实例数据。
}



// CZdActivexCtrl::~CZdActivexCtrl - 析构函数

CZdActivexCtrl::~CZdActivexCtrl()
{
    // TODO: 在此清理控件的实例数据。
}



// CZdActivexCtrl::OnDraw - 绘图函数

void CZdActivexCtrl::OnDraw(
            CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
    if (!pdc)
        return;

    // TODO: 用您自己的绘图代码替换下面的代码。
    pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
    pdc->Ellipse(rcBounds);
}



// CZdActivexCtrl::DoPropExchange - 持久性支持

void CZdActivexCtrl::DoPropExchange(CPropExchange* pPX)
{
    ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
    COleControl::DoPropExchange(pPX);

    // TODO: 为每个持久的自定义属性调用 PX_ 函数。
}



// CZdActivexCtrl::OnResetState - 将控件重置为默认状态

void CZdActivexCtrl::OnResetState()
{
    COleControl::OnResetState();  // 重置 DoPropExchange 中找到的默认值

    // TODO: 在此重置任意其他控件状态。
}



// CZdActivexCtrl::AboutBox - 向用户显示“关于”框

void CZdActivexCtrl::AboutBox()
{
    CDialogEx dlgAbout(IDD_ABOUTBOX_ZDACTIVEX);
    dlgAbout.DoModal();
}



// CZdActivexCtrl 消息处理程序


/*
导入pfx——》签名密钥
* @param CSP_NAME: CSP Provider 标识
* @param FILEDIR: 本地pfx文件路径
* @param PFX_PASS:  pfx文件密码
* @param CONTAINERNAME: 导入容器名称
*/
void CZdActivexCtrl::ImportPFX(LPCTSTR CSP_NAME,LPCTSTR FILEDIR,LPCTSTR PWD,LPCTSTR CONTAINERNAME){
    //使用公开密钥算法产生公/私密钥对,有以下两个:AT_SIGNATURE 用于进行数字签名而产生的密钥对。 AT_KEYEXCHANGE 用于进行加解密(密钥交换)产生的密钥对;
    int keyType = 0;
    
    //文件操作句柄
    HANDLE hFile = NULL;

    hFile = CreateFile(FILEDIR,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
    if (hFile == INVALID_HANDLE_VALUE){
        ::AfxMessageBox(_T("获取用户证书 出错!"));
        return;  
    }
    //分配内存
    DWORD dwSize = ::GetFileSize(hFile, NULL);

    BYTE *pP12 = NULL;

    if (!(pP12 = new BYTE[dwSize]))
    {
        ::CloseHandle(hFile);
        ::AfxMessageBox(_T("构建用户证书 出错!"));
        return;  
    }

    //读取证书内容
    DWORD dwRead = 0;
    if (!::ReadFile(hFile, pP12, dwSize, &dwRead, NULL)){
        ::CloseHandle(hFile);
        ::AfxMessageBox(_T("读取用户证书 出错!"));
        return;  
    }
    //关闭文件
    ::CloseHandle(hFile);

    //生成结构体
    CRYPT_DATA_BLOB CDB;
    CDB.cbData = dwSize;
    CDB.pbData = pP12;

    //转换密码格式
    USES_CONVERSION;
    LPCWSTR PW = T2CW(PWD);

    //将证书导入临时证书库
    HCERTSTORE hStore = NULL;
    
    if (!(hStore = PFXImportCertStore(&CDB, PW, CRYPT_EXPORTABLE))){
        if (!hStore)
            hStore = PFXImportCertStore(&CDB, L"", CRYPT_EXPORTABLE);
        if (!hStore)
            hStore = PFXImportCertStore(&CDB, NULL, CRYPT_EXPORTABLE);
    }
    if(!hStore){
        delete pP12; pP12 = NULL;
        ::AfxMessageBox(_T("将用户证书导入临时证书库 出错!"));
        return;
    }
    delete pP12; pP12 = NULL;

    //枚举临时证书库中导入的证书
    PCCERT_CONTEXT pCertContext = NULL;
    HCRYPTPROV hCertProv = NULL;
    HCRYPTKEY hKey = NULL;
    BYTE *pPK = NULL;
    HCRYPTKEY hPrvKey = NULL;
    HCRYPTPROV hProv = NULL;

    while (pCertContext = CertEnumCertificatesInStore(hStore, pCertContext)){
        //对比“颁发给”和“颁发者”是否一致(对于根证书是一致的,不要导入根证书)
        if (!CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
            &pCertContext->pCertInfo->Issuer,
            &pCertContext->pCertInfo->Subject))
        {
        //获取私钥临时 CSP 句柄
                DWORD dwKeySpec = 0;
                if (!CryptAcquireCertificatePrivateKey(pCertContext,
                    CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
                    NULL,
                    &hCertProv,
                    &dwKeySpec,
                    NULL)){
                        DWORD dwRet = GetLastError();
                        ::AfxMessageBox(_T("获取私钥临时 CSP 句柄 出错!"));
                        goto cleanup;
                }

                //获取密钥对,前者加密,后者签名,自签名的hPubKey一定是AT_SIGNATURE
                if (!CryptGetUserKey(hCertProv, ((keyType == 0) ? AT_KEYEXCHANGE : AT_SIGNATURE), &hKey)) {
                    DWORD dwRet = GetLastError();
                    ::AfxMessageBox(_T("获取密钥对 出错!"));
                    goto cleanup;
                }

                //获取私钥长度
                DWORD dwPKSize = 0;
                if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPKSize)){
                    DWORD dwRet = GetLastError();
                    ::AfxMessageBox(_T("获取私钥大小 出错!"));
                    goto cleanup;
                }

                //分配内存
                if (!(pPK = new BYTE[dwPKSize])){
                    DWORD dwRet = GetLastError();
                    ::AfxMessageBox(_T("构建用户证书结构体 出错!"));
                    goto cleanup;
                }

                //导出私钥
                if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pPK, &dwPKSize)){
                    DWORD dwRet = GetLastError();
                    ::AfxMessageBox(_T("导出私钥 出错!"));
                    goto cleanup;
                }

                /*Algid
                [in] An value that identifies the algorithm for which the key is to be generated. 该参数的值将根据CSP的作用而不同。ALG_ID 表明产生私钥所使用的算法。有如下参数:
                微软提供的基本算法
                CALG_MD2,CALG_MD5,CALG_SHA,CALG_SHA1,CALG_MAC,CALG_HMAC,CALG_SSL3_SHAMD5,CALG_MD2,CALG_MD2
                CALG_RSA_SIGN,CALG_RSA_KEYX,CALG_RC2,CALG_RC4,CALG_DES
                微软提供的增强型算法:
                CALG_MD2,CALG_MD5,CALG_SHA,CALG_SHA1
                CALG_MAC,CALG_HMAC ,CALG_SSL3_SHAMD5,CALG_RSA_SIGN,CALG_RSA_KEYX,CALG_RC2,CALG_RC4,CALG_DES,CALG_3DES_112,CALG_3DES
                使用DH的CSP有如下两个参数,CALG_DH_EPHEM,CALG_DH_SF
                使用公开密钥算法产生公/私密钥对,有以下两个:AT_SIGNATURE 用于进行数字签名而产生的密钥对。 AT_KEYEXCHANGE 用于进行加解密(密钥交换)产生的密钥对;
                */

                PUBLICKEYSTRUC* p = (PUBLICKEYSTRUC*)pPK;
                p->aiKeyAlg = CALG_RSA_SIGN;

                //获取 UKEY 的 CSP 句柄
                if(!CryptAcquireContext(&hProv, CONTAINERNAME,  CSP_NAME,  PROV_RSA_FULL,  0)) {
                    //构建新容器的 CSP 句柄
                    if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET)){
                        //创建密钥容器成功,并得到CSP句柄
                         DWORD dwRst = ::GetLastError();  
                        ::AfxMessageBox(_T("构建新容器 出错!"));
                         goto cleanup;  
                    }else{
                        if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey)){
                            DWORD dwRet = GetLastError();
                            ::AfxMessageBox(_T("将私钥导入到 CSP 出错!"));
                            goto cleanup;
                        }else{
                            //将证书导入到密钥容器
                            if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0)){
                                DWORD dwRet = GetLastError();
                                ::AfxMessageBox(_T("将证书导入到密钥容器 出错!"));
                                goto cleanup;
                            }
                            ::AfxMessageBox(_T("用户证书 导入成功 !"));
                        }
                    }

                }else{
                    ::AfxMessageBox("是否将用户证书导入已存在容器,该操作会删除现有容器证书?",MB_YESNO|MB_ICONQUESTION);
                        int a = MessageBox( "是否确认导入现有容器?" , "警告!该操作会删除现有容器证书!",MB_YESNO|MB_ICONWARNING);
                        if (a == IDYES){
                            if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_DELETEKEYSET)){
                                DWORD dwRst = ::GetLastError();  
                                ::AfxMessageBox(_T("删除现有容器 出错!"));
                                goto cleanup;  
                            }else{
                               //构建新容器的 CSP 句柄
                                if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET)){
                                    //创建密钥容器成功,并得到CSP句柄
                                     DWORD dwRst = ::GetLastError();  
                                    ::AfxMessageBox(_T("构建新容器 出错!"));
                                     goto cleanup;  
                                }else{
                                    if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey)){
                                        DWORD dwRet = GetLastError();
                                        ::AfxMessageBox(_T("将私钥导入到 CSP 出错!"));
                                        goto cleanup;
                                    }else{
                                        //将证书导入到密钥容器
                                        if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0)){
                                            DWORD dwRet = GetLastError();
                                            ::AfxMessageBox(_T("将证书导入到密钥容器 出错!"));
                                            goto cleanup;
                                        }
                                        ::AfxMessageBox(_T("用户证书 导入成功 !"));
                                    }
                                }
                            }
                        }else{
                            ::AfxMessageBox(_T("用户证书未成功导入,容器中已包含其它用户证书 !"));
                        }
                }
        }
    }
    goto cleanup;
cleanup:

    //销毁私钥句柄
    CryptDestroyKey(hPrvKey);

    //关闭硬件加密设备CSP操作句柄
    CryptReleaseContext(hProv, 0);

    //释放私钥内存
    delete pPK; pPK = NULL;

    //销毁密钥对句柄
    CryptDestroyKey(hKey);

    //释放证书句柄
    CertFreeCertificateContext(pCertContext);

    //关闭临时证书库
    CertCloseStore(hStore, 0);

    //删除临时用户证书文件
    DeleteFile(FILEDIR);
}

/*
导入pfx——》交换密钥
* @param CSP_NAME: CSP Provider 标识
* @param FILEDIR: 本地pfx文件路径
* @param PFX_PASS:  pfx文件密码
* @param CONTAINERNAME: 导入容器名称
*/
void CZdActivexCtrl::ImportExchangePFX(LPCTSTR CSP_NAME,LPCTSTR FILEDIR,LPCTSTR PWD,LPCTSTR CONTAINERNAME){
    //使用公开密钥算法产生公/私密钥对,有以下两个:AT_SIGNATURE 用于进行数字签名而产生的密钥对。 AT_KEYEXCHANGE 用于进行加解密(密钥交换)产生的密钥对;
    int keyType = 0;
    
    //文件操作句柄
    HANDLE hFile = NULL;

    hFile = CreateFile(FILEDIR,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
    if (hFile == INVALID_HANDLE_VALUE){
        ::AfxMessageBox(_T("获取用户证书 出错!"));
        return;  
    }
    //分配内存
    DWORD dwSize = ::GetFileSize(hFile, NULL);

    BYTE *pP12 = NULL;

    if (!(pP12 = new BYTE[dwSize])){
        ::CloseHandle(hFile);
        ::AfxMessageBox(_T("构建用户证书 出错!"));
        return;  
    }

    //读取证书内容
    DWORD dwRead = 0;
    if (!::ReadFile(hFile, pP12, dwSize, &dwRead, NULL)){
        ::CloseHandle(hFile);
        ::AfxMessageBox(_T("读取用户证书 出错!"));
        return;  
    }
    //关闭文件
    ::CloseHandle(hFile);

    //生成结构体
    CRYPT_DATA_BLOB CDB;
    CDB.cbData = dwSize;
    CDB.pbData = pP12;

    //转换密码格式
    USES_CONVERSION;
    LPCWSTR PW = T2CW(PWD);

    //将证书导入临时证书库
    HCERTSTORE hStore = NULL;

    if (!(hStore = PFXImportCertStore(&CDB, PW, CRYPT_EXPORTABLE))){
        if (!hStore)
            hStore = PFXImportCertStore(&CDB, L"", CRYPT_EXPORTABLE);
        if (!hStore)
            hStore = PFXImportCertStore(&CDB, NULL, CRYPT_EXPORTABLE);
    }
    if(!hStore){
        delete pP12; pP12 = NULL;
        ::AfxMessageBox(_T("将用户证书导入临时证书库 出错!"));
        return;
    }

    //枚举临时证书库中导入的证书
    PCCERT_CONTEXT pCertContext = NULL;
    HCRYPTPROV hCertProv = NULL;
    HCRYPTKEY hKey = NULL;
    BYTE *pPK = NULL;
    HCRYPTKEY hPrvKey = NULL;
    HCRYPTPROV hProv = NULL;

    while (pCertContext = CertEnumCertificatesInStore(hStore, pCertContext)){
        //对比“颁发给”和“颁发者”是否一致(对于根证书是一致的,不要导入根证书)
        if (!CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
            &pCertContext->pCertInfo->Issuer,
            &pCertContext->pCertInfo->Subject))
        {
        //获取私钥临时 CSP 句柄
                DWORD dwKeySpec = 0;
                if (!CryptAcquireCertificatePrivateKey(pCertContext,
                    CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
                    NULL,
                    &hCertProv,
                    &dwKeySpec,
                    NULL)){
                        DWORD dwRet = GetLastError();
                        ::AfxMessageBox(_T("获取私钥临时 CSP 句柄 出错!"));
                        goto cleanup;
                }

                //获取密钥对,前者加密,后者签名,自签名的hPubKey一定是AT_SIGNATURE
                if (!CryptGetUserKey(hCertProv, ((keyType == 0) ? AT_KEYEXCHANGE : AT_SIGNATURE), &hKey)) {
                    DWORD dwRet = GetLastError();
                    ::AfxMessageBox(_T("获取密钥对 出错!"));
                    goto cleanup;
                }

                //获取私钥长度
                DWORD dwPKSize = 0;
                if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPKSize)){
                    DWORD dwRet = GetLastError();
                    ::AfxMessageBox(_T("获取私钥大小 出错!"));
                    goto cleanup;
                }

                //分配内存
                if (!(pPK = new BYTE[dwPKSize])){
                    DWORD dwRet = GetLastError();
                    ::AfxMessageBox(_T("构建用户证书结构体 出错!"));
                    goto cleanup;
                }

                //导出私钥
                if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pPK, &dwPKSize)){
                    DWORD dwRet = GetLastError();
                    ::AfxMessageBox(_T("导出私钥 出错!"));
                    goto cleanup;
                }

                /*Algid
                [in] An value that identifies the algorithm for which the key is to be generated. 该参数的值将根据CSP的作用而不同。ALG_ID 表明产生私钥所使用的算法。有如下参数:
                微软提供的基本算法
                CALG_MD2,CALG_MD5,CALG_SHA,CALG_SHA1,CALG_MAC,CALG_HMAC,CALG_SSL3_SHAMD5,CALG_MD2,CALG_MD2
                CALG_RSA_SIGN,CALG_RSA_KEYX,CALG_RC2,CALG_RC4,CALG_DES
                微软提供的增强型算法:
                CALG_MD2,CALG_MD5,CALG_SHA,CALG_SHA1
                CALG_MAC,CALG_HMAC ,CALG_SSL3_SHAMD5,CALG_RSA_SIGN,CALG_RSA_KEYX,CALG_RC2,CALG_RC4,CALG_DES,CALG_3DES_112,CALG_3DES
                使用DH的CSP有如下两个参数,CALG_DH_EPHEM,CALG_DH_SF
                使用公开密钥算法产生公/私密钥对,有以下两个:AT_SIGNATURE 用于进行数字签名而产生的密钥对。 AT_KEYEXCHANGE 用于进行加解密(密钥交换)产生的密钥对;
                */

                /*
                PUBLICKEYSTRUC* p = (PUBLICKEYSTRUC*)pPK;
                p->aiKeyAlg = CALG_RSA_SIGN;
                */

                //获取 UKEY 的 CSP 句柄
                if(!CryptAcquireContext(&hProv, CONTAINERNAME,  CSP_NAME,  PROV_RSA_FULL,  0)) {
                    //构建新容器的 CSP 句柄
                    if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET)){
                        //创建密钥容器成功,并得到CSP句柄
                         DWORD dwRst = ::GetLastError();  
                        ::AfxMessageBox(_T("构建新容器 出错!"));
                         goto cleanup;  
                    }else{
                        if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey)){
                            DWORD dwRet = GetLastError();
                            ::AfxMessageBox(_T("将私钥导入到 CSP 出错!"));
                            goto cleanup;
                        }else{
                            //将证书导入到密钥容器
                            if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0)){
                                DWORD dwRet = GetLastError();
                                ::AfxMessageBox(_T("将证书导入到密钥容器 出错!"));
                                goto cleanup;
                            }
                            ::AfxMessageBox(_T("用户证书 导入成功 !"));
                        }
                    }

                }else{
                    ::AfxMessageBox("是否将用户证书导入已存在容器,该操作会删除现有容器证书?",MB_YESNO|MB_ICONQUESTION);
                        int a = MessageBox( "是否确认导入现有容器?" , "警告!该操作会删除现有容器证书!",MB_YESNO|MB_ICONWARNING);
                        if (a == IDYES){
                            if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_DELETEKEYSET)){
                                DWORD dwRst = ::GetLastError();  
                                ::AfxMessageBox(_T("删除现有容器 出错!"));
                                goto cleanup;  
                            }else{
                               //构建新容器的 CSP 句柄
                                if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET)){
                                    //创建密钥容器成功,并得到CSP句柄
                                     DWORD dwRst = ::GetLastError();  
                                    ::AfxMessageBox(_T("构建新容器 出错!"));
                                     goto cleanup;  
                                }else{
                                    if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey)){
                                        DWORD dwRet = GetLastError();
                                        ::AfxMessageBox(_T("将私钥导入到 CSP 出错!"));
                                        goto cleanup;
                                    }else{
                                        //将证书导入到密钥容器
                                        if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0)){
                                            DWORD dwRet = GetLastError();
                                            ::AfxMessageBox(_T("将证书导入到密钥容器 出错!"));
                                            goto cleanup;
                                        }
                                        ::AfxMessageBox(_T("用户证书 导入成功 !"));
                                    }
                                }
                            }
                        }else{
                            ::AfxMessageBox(_T("用户证书未成功导入,容器中已包含其它用户证书 !"));
                        }
                }
        }
    }
    goto cleanup;
cleanup:

    //销毁私钥句柄
    CryptDestroyKey(hPrvKey);

    //关闭硬件加密设备CSP操作句柄
    CryptReleaseContext(hProv, 0);

    //释放私钥内存
    delete pPK; pPK = NULL;

    //销毁密钥对句柄
    CryptDestroyKey(hKey);

    //释放证书句柄
    CertFreeCertificateContext(pCertContext);

    //关闭临时证书库
    CertCloseStore(hStore, 0);

    //删除临时用户证书文件
    DeleteFile(FILEDIR);
}

/**
 * 执行 文件下载 操作
 * @param Url: 目标URL下载地址
 * @param LOCALPATH:本地保存路径
 */
LONG CZdActivexCtrl::DownLoadToLocal(LPCTSTR Url,LPCTSTR LOCALPATH){
    //清除URL 缓存
    DeleteUrlCacheEntry(Url);
    //下载文件
    //Url 下载地址
    //LOCALPATH 本地保存地址
    if (S_OK ==URLDownloadToFile(NULL,Url,LOCALPATH,0,NULL))
        return 1;//下载成功
    else
        return -1;//下载失败
}

/*
 遍历系统CSP Provider
*/
BSTR CZdActivexCtrl::EnumCspProvider(void)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    CString strResult = "";
    
    CString result = "";
    long  i = 0;

    //枚举CSP设备
    DWORD       cbName;
    DWORD       dwType;
    DWORD       dwIndex;
    CHAR        *pszName = NULL;
    
    // 遍历列举CSP
    dwIndex = 0;
    while(CryptEnumProviders(
        dwIndex,
        NULL,
        0,
        &dwType,
        NULL,
        &cbName
        ))
    {
        
        //--------------------------------------------------------------------
        //  cbName returns the length of the name of the next provider.
        //  Allocate memory in a buffer to retrieve that name.
        
        if (!(pszName = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, cbName)))
        {
            ::AfxMessageBox(_T("ERROR - LocalAlloc failed!"));
            exit(1);
        }
        //--------------------------------------------------------------------
        //  Get the provider name.
        if (CryptEnumProviders(
            dwIndex++,
            NULL,
            0,
            &dwType,
            pszName,
            &cbName
            )){
            if(PROV_RSA_FULL == dwType){
                i++;
                CString value = _T(pszName);
                strResult +="{'value':'"+value+"'},";
            }
        }else{
            ::AfxMessageBox(_T("ERROR - CryptEnumProviders"));
            exit(1);
        }
        LocalFree(pszName);
    }
    strResult = strResult.Mid(0,strResult.GetLength()-1);

    char c[7];
    itoa(i,c,10);

    result.Append("{'total':");
    result.Append(c);
    result.Append(", 'rows': [");
    result.Append(strResult+"]}");

    // TODO: 在此添加调度处理程序代码

    return result.AllocSysString();
}

0 0