5. 完整代码
#include "stdafx.h"
#include <windows.h>
#include <WinCrypt.h>
#include <stdio.h>
// Global Csp Handle
HCRYPTPROV hCryptProv = NULL; // Handle for a cryptographic
void ToSmartCard(HCERTSTORE hSystemStore)
{
PCCERT_CONTEXT pCertContext = NULL;
char pszNameString[256];
DWORD dwKeySpec;
HCRYPTKEY UserKey = 0;
DWORD dwBlobLen;
BYTE *pbKeyBlob;
HCRYPTKEY hPubKey = NULL;
int error;
// CryptAcquireCertificatePrivateKey Exported Handle
HCRYPTPROV hCrypt = NULL;
// Just for Test Provider Name
BYTE pbData[1000]; // 1000 will hold the longest
// key container name.
DWORD cbData;
cbData = 1000;
//-------------------------------------------------------------------
// Find the certificates in the system store.
// In fact, just have one.
while(pCertContext= CertEnumCertificatesInStore(
hSystemStore,
pCertContext)) // on the first call to the function,
// this parameter is NULL
// on all subsequent calls,
// this parameter is the last pointer
// returned by the function
{
//----------------------------------------------------------------
// Do whatever is needed for a current certificate.
// ...
//--------------------------------------------------------------------
// Find and print the name of the subject of the certificate
// just retrieved.
if(CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszNameString,
128))
{
printf("Certificate for %s has been retrieved.\n",pszNameString);
if(!( CryptAcquireCertificatePrivateKey(
pCertContext,
0,
NULL,
&hCrypt, //&hCryptProv, // 注意此处 hCrypt 输出不该是hCryptProv,如果没有猜错是Microsoft Base那个
&dwKeySpec,
NULL)))
{
printf("CryptAcquireCertificatePrivateKey.\n");
}
// Test hCrypt, Try to get its name;
// 猜错了,不是Microsoft Base...,而是下面这个
// Microsoft Enhanced Cryptographic Provider v1.0
if(CryptGetProvParam(
hCrypt,
PP_NAME,
pbData,
&cbData,
0))
{
printf("CryptGetProvParam succeeded.\n");
printf("Provider name: %s\n", pbData);
}
if( ! CryptGetUserKey(
hCrypt, //not hCryptProv,
AT_KEYEXCHANGE, //dwKeySpec,
&UserKey
) )
{
printf("CryptGetUserKey Error.\n");
}
//--------------------------------------------------------------------
// Export the public/private key-pair.
if(CryptExportKey(
UserKey,
NULL,
PRIVATEKEYBLOB,
0,
NULL,
&dwBlobLen))
{
printf("Size of the BLOB for the public/private key pair determined. \n");
}
else
{
printf("Error computing BLOB length.\n");
exit(1);
}
//--------------------------------------------------------------------
// Allocate memory for the pbKeyBlob.
if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))
{
printf("Memory has been allocated for the BLOB. \n");
}
else
{
printf("Out of memory. \n");
exit(1);
}
//--------------------------------------------------------------------
// Do the actual exporting into the key BLOB.
if(CryptExportKey(
UserKey,
NULL,
PRIVATEKEYBLOB,
0,
pbKeyBlob,
&dwBlobLen))
{
printf("Contents have been written to the BLOB. \n");
}
else
{
printf("Error exporting key.\n");
exit(1);
}
if(CryptImportKey(
hCryptProv,
pbKeyBlob,
dwBlobLen,
0,
0,
&hPubKey))
{
printf("The key has been imported.\n");
}
else
{
printf("Public key import failed.\n");
exit(1);
}
// Not this one
//if (!CryptSetKeyParam(UserKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0))
if (!CryptSetKeyParam(hPubKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0))
{
error = GetLastError();
printf("CryptSetKeyParam 0x%x\n", error);
if (error != NTE_BAD_TYPE) {
// If error is bad_type then we just can't set the property.
// Likely means our provider isn't a smart card.
// If there was another error, we should report it.
printf("CryptSetKeyParam Failed (0x80090020 usually means no room on card) 0x%x\n",error);
}
}
if(hPubKey) {
CryptDestroyKey(hPubKey);
}
//--------------------------------------------------------------------
// Allocate memory for the pbKeyBlob.
if(pbKeyBlob)
free(pbKeyBlob);
}
else
{
printf("CertGetName failed. \n");
}
CertFreeCertificateContext(pCertContext);
} // End of while
}
void InstallPfx(CHAR *filename, CHAR *password)
{
HANDLE hFile;
BOOL bResult;
BYTE inBuffer[10000];
DWORD nBytesToRead = 0;
DWORD nBytesRead;
WCHAR wszpassword[20];
HCERTSTORE pfxcert = NULL;
hFile = CreateFile(filename, // open MYFILE.TXT
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // no security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Could not open file.\n"); // process error
return;
}
nBytesToRead = GetFileSize (hFile, NULL);
printf("File Size is %d\n", nBytesToRead);
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, NULL) ;
if (bResult) // Reading is OK.
{
CRYPT_DATA_BLOB pfxblob;
pfxblob.cbData = nBytesRead;
pfxblob.pbData = inBuffer;
if( PFXIsPFXBlob( &pfxblob) )
{
printf("It's a Pfx Certificate.\n");
MultiByteToWideChar( CP_ACP, 0, password,
strlen(password)+1, wszpassword,
sizeof(wszpassword)/sizeof(wszpassword[0]) );
if( NULL != PFXImportCertStore(
&pfxblob,
wszpassword,
0x21 //CRYPT_USER_PROTECTED
)
)
{
printf("It's a Pfx imPORT OK.\n");
pfxcert = PFXImportCertStore(
&pfxblob,
wszpassword,
0x21 //CRYPT_USER_PROTECTED
);
ToSmartCard(pfxcert);
// 列出所有My的证书
//ToSmartCard(hSystemStore);
}
}
}
CloseHandle(hFile);
}
void OpenCert(HCRYPTPROV hprov)
{
//--------------------------------------------------------------------
// Declare and initialize variables.
HCERTSTORE hSystemStore; // system store handle
//--------------------------------------------------------------------
// Open the MY system certificate store. The same call can be
// used with the name of a different system store, such as My or Root,
// as the second parameter.
if(hSystemStore = CertOpenSystemStore(
hprov,
"MY"))
{
printf("The MY system store is open. Continue.\n");
}
else
{
printf("The MY system store did not open.\n");
exit(1);
}
// Use the store as needed.
// ...
InstallPfx("d:\\exported.pfx", "123456");
// When done using the store, close it.
if(!CertCloseStore(hSystemStore,CERT_CLOSE_STORE_CHECK_FLAG))
{
printf("Unable to close the MY system store.\n");
exit(1);
}
}
int main(int argc, CHAR* argv[])
{
//--------------------------------------------------------------------
// Declare and initialize variables.
// provider context.
LPCSTR UserName = "MyKeyContainer"; // Name of the key container
LPCSTR ProviderName = "eSafe Cryptographic Service Provider v2.0";
// to be used.
//--------------------------------------------------------------------
// Attempt to acquire a context and a key
// container. The context will use the default CSP
// for the RSA_FULL provider type. DwFlags is set to 0
// to attempt to open an existing key container.
if(CryptAcquireContext(
&hCryptProv, // Handle to the CSP
UserName, // Container name
ProviderName, // Use the default provider
PROV_RSA_FULL, // Provider type
0)) // Flag values
{
printf("A crypto context with the %s key container \n", UserName);
printf("has been acquired.\n\n");
OpenCert(hCryptProv);
}
else
{
//--------------------------------------------------------------------
// An error occurred in acquiring the context. This could mean
// that the key container requested does not exist. In this case,
// the function can be called again to attempt to create a new key
// container. Error codes are defined in winerror.h.
if (GetLastError() == NTE_BAD_KEYSET)
{
if(CryptAcquireContext(
&hCryptProv,
UserName,
ProviderName,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
printf("A new key container has been created.\n");
OpenCert(hCryptProv);
}
else
{
printf("Could not create a new key container.\n");
exit(1);
}
}
else
{
printf("A cryptographic service handle could not be acquired.\n");
exit(1);
}
} // End of else
//--------------------------------------------------------------------
// A cryptographic context and a key container is available. Perform
// any functions that require a Cryptographic provider handle.
//--------------------------------------------------------------------
// When the handle is no longer needed, it must be released.
if (CryptReleaseContext(hCryptProv,0))
{
printf("The handle has been released.\n");
}
else
{
printf("The handle could not be released.\n");
}
return 0;
}