C++代码将PFX证书写入智能卡

//====================================================================

// 写入证书
int GetProvider(char* pProvider)
{
SCARDCONTEXT    hSC;
LONG            lReturn;
// Establish the context.
lReturn = SCardEstablishContext(SCARD_SCOPE_USER,
NULL,
NULL,
&hSC);
if (SCARD_S_SUCCESS != lReturn)
{
printf("Failed SCardEstablishContext\n");
return -1;
}


DWORD nLen = SCARD_AUTOALLOCATE;
char* pmszReaders = NULL;
lReturn = SCardListReaders(hSC, NULL, (LPTSTR)&pmszReaders, &nLen);
if (SCARD_S_SUCCESS != lReturn)
{
printf("Failed SCardListReaders\n");
return -1;
}


printf("Reader: %s\n", pmszReaders);


SCARD_READERSTATE scard_state;
scard_state.szReader = pmszReaders;
lReturn = SCardGetStatusChange(hSC, 0, &scard_state, 1);
if (SCARD_S_SUCCESS != lReturn)
{
printf("Failed SCardGetStatusChange\n");
return -1;
}


LPTSTR pmszCards = NULL;
DWORD cch = SCARD_AUTOALLOCATE;


// Retrieve the list of cards.
BYTE atr[] = { 0x3B, 0xD5, 0x18, 0x00, 0x81, 0x31, 0x3A, 0x7D, 0x80, 0x73, 0xC8, 0x21, 0x10, 0x30, 0x00, 0x00 };
lReturn = SCardListCards(hSC,
atr,
NULL,
NULL,
(LPTSTR)&pmszCards,
&cch);
if (SCARD_S_SUCCESS != lReturn)
{
printf("Failed SCardListCards\n");
return -1;
}


printf("Card: %s\n", pmszCards);


LPTSTR szProvider = NULL;
DWORD  chProvider = SCARD_AUTOALLOCATE;


// Retrieve the provider name.
// hContext was set by SCardEstablishContext.
lReturn = SCardGetCardTypeProviderName(hSC,
pmszCards,
SCARD_PROVIDER_CSP, // 0x80000001 SCARD_PROVIDER_CSP SCARD_PROVIDER_KSP
(LPTSTR)&szProvider,
&chProvider);
if (SCARD_S_SUCCESS != lReturn)
{
printf("Failed SCardGetCardTypeProviderName\n");
return -1;
}


strcpy(pProvider, szProvider);
return 0;
}


// 写证书
#define CONTAINER_NAME "BitlockerCert"
int _tmain(int argc, _TCHAR* argv[])
{
// 载入证书数据
FILE* pf = fopen(" D:\\demo.p12", "rb");
if (pf == NULL)
{
printf("Failed fopen\n");
return -1;
}
BYTE data[4096] = { 0 };
fseek(pf, 0, SEEK_END);
long len = ftell(pf);
fseek(pf, 0, SEEK_SET);
size_t count = fread(data, 1, len, pf);
if (count != len)
{
printf("Failed fread\n");
return -1;
}
fclose(pf);


CRYPT_DATA_BLOB pPFX;
pPFX.cbData = len;
pPFX.pbData = data;
if (!PFXIsPFXBlob(&pPFX))
{
printf("Failed PFXIsPFXBlob\n");
return -1;
}


HCERTSTORE hPfxCertStore = PFXImportCertStore(&pPFX, L" 123456", CRYPT_EXPORTABLE | CRYPT_MACHINE_KEYSET);
if (hPfxCertStore == NULL)
{
printf("Failed PFXImportCertStore\n");
return -1;
}


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


while (pCertContext = CertEnumCertificatesInStore(hPfxCertStore, pCertContext))
{
//获取私钥临时 CSP 句柄
DWORD dwKeySpec = 0;
if (!CryptAcquireCertificatePrivateKey(pCertContext,
CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
NULL,
&hCertProv,
&dwKeySpec,
NULL))
{
printf("Failed CryptAcquireCertificatePrivateKey\n");
return -1;
}

//获取密钥对,前者加密,后者签名,自签名的hPubKey一定是AT_SIGNATURE
if (!CryptGetUserKey(hCertProv, AT_KEYEXCHANGE, &hKey)) // AT_KEYEXCHANGE AT_SIGNATURE
{
printf("Failed CryptGetUserKey\n");
return -1;
}


//获取私钥长度
DWORD dwPKSize = 0;
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPKSize))
{
printf("Failed CryptExportKey\n");
return -1;
}


//分配内存
if (!(pPK = new BYTE[dwPKSize]))
{
printf("Failed alloc memory\n");
return -1;
}


//导出私钥
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pPK, &dwPKSize))
{
printf("Failed CryptExportKey\n");
return -1;
}


char provider[MAX_PATH] = { 0 };
if (GetProvider(provider) != 0)
{
printf("Failed GetProvider\n");
return -1;
}


BYTE  pbCertContainerName[10][40] = { 0 };  //容器名称
DWORD  dwCertContainerNameLen = 40;     //容器名称长度
DWORD  dwCertNumber = 0;  //容器数目


HCRYPTPROV hProv = NULL;
if (CryptAcquireContext(&hProv, NULL, provider, PROV_RSA_FULL, CRYPT_SILENT))
{
BOOL blExist = FALSE;
if (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, pbCertContainerName[dwCertNumber], &dwCertContainerNameLen, CRYPT_FIRST))
{
if (dwCertContainerNameLen != 0)
{
printf("Container #%d: %s\n", dwCertNumber + 1, pbCertContainerName[dwCertNumber]);
if (strcmp((char*)pbCertContainerName[dwCertNumber], CONTAINER_NAME) == 0)
{
blExist = TRUE;
}
else
{
dwCertNumber++;


//枚举其它的容器,最后一个参数为0
while (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, pbCertContainerName[dwCertNumber], &dwCertContainerNameLen, 0))
{
if (dwCertContainerNameLen != 0)
{
printf("Container #%d: %s\n", dwCertNumber + 1, pbCertContainerName[dwCertNumber]);
if (strcmp((char*)pbCertContainerName[dwCertNumber], CONTAINER_NAME) == 0)
{
blExist = TRUE;
break;
}


dwCertNumber++;
}
}
}
}
}


if (blExist)
{
// 删除现有证书
if (!CryptAcquireContext(&hProv, CONTAINER_NAME, provider, PROV_RSA_FULL, CRYPT_DELETE_KEYSET))
{
printf("Failed CryptAcquireContext\n");
return -1;
}
}
}


// 新建证书
if (!CryptAcquireContext(&hProv, CONTAINER_NAME, provider, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
printf("Failed CryptAcquireContext\n");
return -1;
}


// 导入私钥
if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey))
{
DWORD dwErr = GetLastError();
printf("Failed CryptImportKey\n");
return -1;
}


//将证书导入到密钥容器
if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0))
{
printf("Failed CryptSetKeyParam\n");
return -1;
}


CryptReleaseContext(hProv, 0);


printf(_T("用户证书 导入成功 !\n"));
}


return 0;

}


参考:

https://blog.csdn.net/Himire/article/details/44002831

https://blog.csdn.net/music313/article/details/39498457

猜你喜欢

转载自blog.csdn.net/ayang1986/article/details/80989799