CSP多USBkey操作获取信息

此程序已通过文鼎创USBkey多key测试。


#include <stdio.h>
#include <direct.h>
#include <string.h>
#include <vector>
#include <Windows.h>
#include <Wincrypt.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(lib, "Crypt32")
#define PROV_LENGTH 255
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

struct keyInfo
{
    string certUserName;
    string providerName;
    string containerName;
};

void GetListProvider(vector<string> &vProList)
{
    DWORD dwIndex = 0;
    DWORD dwType = 0;
    char szKeyName[PROV_LENGTH] = {0};
    DWORD dwMaxSubKey = PROV_LENGTH;
    while (CryptEnumProviders(dwIndex++, NULL, 0, &dwType, szKeyName, &dwMaxSubKey))
    {
        if (dwType == PROV_RSA_FULL && strnicmp("Microsoft", szKeyName, 9)) //csp类型 + 不区分大小写比较前9个字符
        {
            //printf("%s\n", szKeyName);
            vProList.push_back(szKeyName);
        }
        memset(szKeyName, 0, PROV_LENGTH);
        dwMaxSubKey = PROV_LENGTH;
    }
}

DWORD GetCertificate(HCRYPTPROV hProv, BYTE* pCertificate, DWORD* pCertificateLen)
{
    if(hProv == NULL) return -1;

    //获取所获取密钥类型的句柄
    //获取公私钥对和交换密钥,公私钥用来签名,而交换密钥用来导出会话密钥
    HCRYPTKEY hSignKey;
    if(CryptGetUserKey(hProv, AT_SIGNATURE, &hSignKey ) == FALSE)
    {
        printf("CSP获取密钥句柄失败\n");
        return -1;
    }
    if(CryptGetKeyParam(hSignKey, KP_CERTIFICATE, pCertificate, pCertificateLen, 0) == FALSE)
    {
        printf("CSP得到密钥参数失败\n");
        return -1;
    }
    if(CryptDestroyKey(hSignKey) == FALSE)
    {
        printf("CSP销毁密钥失败\n");
        return -1;
    }
    return 0;
}

DWORD DecodeX509Cert(BYTE* pCertificate, DWORD certificateLen, char keyID[255], char userName[255])
{ 
    PCCERT_CONTEXT pctx = CertCreateCertificateContext(MY_ENCODING_TYPE, pCertificate, certificateLen); //从编码证书中创建一个证书上下文。但这个上下文并不放到证书库里
    if(pctx == NULL)
    {
        printf("解析证书失败\n");
        return -1;
    }

    //找到扩展对象
    PCERT_EXTENSION pCertExt = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, pctx->pCertInfo->cExtension, pctx->pCertInfo->rgExtension); //通过OID来查找扩展
    if (!pCertExt)
    {
        printf("证书属性不存在\n");
        return -1;
    }

    //解码对象,得到属性结构体
    DWORD ulDataLen = 512;
    BYTE btData[512] = {0};
    CHAR csProperty[512] = {0};
    PCERT_AUTHORITY_KEY_ID2_INFO pAuthorityKeyID2 = (PCERT_AUTHORITY_KEY_ID2_INFO)btData;
    if (CryptDecodeObject(MY_ENCODING_TYPE, szOID_AUTHORITY_KEY_IDENTIFIER2,
    pCertExt->Value.pbData, pCertExt->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, pAuthorityKeyID2, &ulDataLen)) //对属性结构体进行解码
    {
        //获取颁发机构标识符
        for (ULONG ulIndex = 0; ulIndex < pAuthorityKeyID2->KeyId.cbData; ulIndex++)
        {
            CHAR csKeyID[8] = {0};
            sprintf_s(csKeyID, 8, "%02x ", pAuthorityKeyID2->KeyId.pbData[ulIndex]);
            strcat_s(csProperty, 512, csKeyID);
        }
        csProperty[strlen(csProperty)-1] = 0;
        strcpy(keyID, csProperty);

        //获取userName
        TCHAR sName[255];
        DWORD nNameSize = 255;
        DWORD nNameType = 0;
        CertGetNameString(pctx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, &nNameType, sName, nNameSize); //得到证书的主题或颁发者名称并且把它转换成字符串
        strcpy(userName, sName);
        CertFreeCertificateContext(pctx);
        return 0;
    }
    else
    {
        CertFreeCertificateContext(pctx);
        return -1;
    }
}


int getKeyList()
{
    //1.获取注册表中的Provider
    printf("\n**1**---------------------------------获取Provider-------------------------------\n");
    vector<string> vProvList;
    GetListProvider(vProvList);
    int numProv = vProvList.size();
    if (numProv == 0)
    {
        printf("获取注册表中的Provider失败\n");
        return -1;
    }
    for (int i = 0; i < numProv; i++)
    {
        printf("%s\n", vProvList[i].c_str());
    }
    printf("\n");

    vector<string> vContainer;

    printf("\n**2**---------------------------------取出Container-------------------------------\n");
    //2.获取Provider对应的句柄,枚举Container
    for (int i = 0; i < numProv; i++)
    {
        HCRYPTPROV hProv = NULL;
        if (CryptAcquireContext(&hProv, NULL, vProvList[i].c_str(), PROV_RSA_FULL, 0)) //获取Provider对应的句柄
        {
            printf("%s---ok\n", vProvList[i].c_str());
            BYTE pbData[512] = {0};
            DWORD cbData = 512;
            if (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, pbData, &cbData, CRYPT_FIRST)) //枚举container
            {
                printf("[%s]\n", pbData);
                vContainer.push_back((char*)pbData);
                memset(pbData, 0, sizeof(pbData));
                cbData = 512;
                while (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, pbData, &cbData, CRYPT_NEXT))
                {
                    printf("[%s]\n", pbData);
                    vContainer.push_back((char*)pbData);

                    memset(pbData, 0, sizeof(pbData));
                    cbData = 512;
                }
            }
            else
            {
                DWORD errcode=GetLastError();
                printf("[%s]CryptGetProvParam失败!--%d\n",vProvList[i].c_str(),errcode);
            }

            CryptReleaseContext(hProv, 0);
            printf("\n");
        }
        else
        {
            DWORD errcode=GetLastError();
            printf("[%s]------CryptAcquireContext失败!---%d\n",vProvList[i].c_str(),errcode);
        }
    }

    printf("\n**3**---------------------------------取出Container对应证书-------------------------------\n");
    //3.打开Container、Provider对应的加密设备,取出签名证书,取出证书信息(颁发机构标识符等)
    for (size_t i = 0; i < vContainer.size(); i++)
    {
        for (int j = 0; j < numProv; j++)
        {
            HCRYPTPROV hProv = NULL;
            if (CryptAcquireContext(&hProv, vContainer[i].c_str(), vProvList[j].c_str(), PROV_RSA_FULL, 0))
            {
                printf("[%s]------open container ok\n", vContainer[i].c_str());
                BYTE pbData[512] = {0};
                DWORD cbData = 512;

                BYTE pCertificate[4096] = {0};
                DWORD certificateLen = 4096;
                if (!GetCertificate(hProv, pCertificate, &certificateLen)) //获取签名证书
                {
                    char userName[255] = {0};
                    char keyID[255] = {0};
                    if (!DecodeX509Cert(pCertificate, certificateLen, keyID, userName)) //获取证书【颁发机构标识符】-【用户名】
                    {
                        printf(">>>>>>>>>>>>>证书信息\n");
                        printf("keyID=%s\n", keyID);
                        printf("userName=%s\n", userName);
                    }
                }
                CryptReleaseContext(hProv, 0);
                printf("\n");
            }
            else
            {
                printf("[%s]------CryptAcquireContext失败!\n",vProvList[j].c_str());
            }
        }
    }
    return 0;
}

int main()
{
    char buffer[100] = {0};
    getcwd(buffer, 100);
    printf("%s\n", buffer);

    getKeyList();
    printf("\n\n########################################################################\n\n");
    Sleep(1000);

    getKeyList();
    getchar();
    return 0;
}
插入两个文鼎创USBkey运行效果如图所示:

这里写图片描述

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

离水的鱼儿

一分也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值