Example C Program: Working with Key Identifiers
The following example demonstrates ways of working with key identifiers. This example illustrates the following tasks and CryptoAPI functions:
- Creating a key identifier using CryptCreateKeyIdentifierFromCSP.
- Setting a property on a key identifier using CryptSetKeyIdentifierProperty.
- Retrieving the contents of a key identifier property using CryptGetKeyIdentifierProperty.
- Listing the properties of a key identifier using CryptEnumKeyIdentifierProperties.
- Declaring, defining, and using a callback function.
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
//-------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// This program demonstrates the following Key Identifier functions:
// CryptCreateKeyIdentifierFromCSP
// CryptSetKeyIdentifierProperty
// CryptGetKeyIdentifierProperty
// CryptEnumKeyIdentifierProperties
// The callback function pfnEnum is also demonstrated.
//-------------------------------------------------------------------
// Declare the Callback function
static BOOL WINAPI pfnEnum (
const CRYPT_HASH_BLOB *pKeyIdentifier, // in- pKeyIdentifier
DWORD dwFlags, // in- Flag values
void *pvReserved, // Reserved
void *pvArg, // in- Pass-through argument
DWORD cProp, // in- cProp
DWORD *rgdwPropId, // in- array of PropIds
void **rgpvData, // in- array of
// CRYPT_KEY_PROV_INFO
// structures
DWORD *rgcbData // in- rgcbData
);
//-------------------------------------------------------------------
// Declare the MyHandleError function.
void MyHandleError(char *s);
void main(void)
{
//-------------------------------------------------------------------
// Declare and initialize variables.
PUBLICKEYSTRUC *pPubKeyStruc;
DWORD cbPubKeyStruc= sizeof(PUBLICKEYSTRUC);
if(!(pPubKeyStruc = (PUBLICKEYSTRUC *) malloc (cbPubKeyStruc)))
MyHandleError("Memory allocation failed.");
pPubKeyStruc->bType= PUBLICKEYBLOB;
pPubKeyStruc->bVersion= CUR_BLOB_VERSION;
pPubKeyStruc->reserved= 0;
pPubKeyStruc->aiKeyAlg= CALG_RSA_KEYX;
BYTE *pbHash;
DWORD cbHash;
PCRYPT_KEY_PROV_INFO pData;
CRYPT_HASH_BLOB KeyIdentifier;
DWORD cbData;
void *pvArg; // Pass through argument.
cbHash= 20; // define cbHash to the size of a SHA1
// string- there is no need for a 2 pass
// call to determine size of cbHash.
//-------------------------------------------------------------------
// Allocate memory for the pbHash buffer
if(!(pbHash= (BYTE *) malloc (cbHash))
MyHandleError("Memory allocation failed.");
//-------------------------------------------------------------------
// Create a Key Identifier
if(CryptCreateKeyIdentifierFromCSP(
X509_ASN_ENCODING, // dwCertEncodingType
NULL, // pszPubKeyOID- NULL to
// use default OID.
pPubKeyStruc, // pPubKeyStruc- defined above
cbPubKeyStruc, // cbPubKeyStruc
0, // dwFlags
NULL, // pvReserved
pbHash, // pbHash
&cbHash // pcbHash
))
{
printf("Call to CryptCreateKeyIdentifierFromCSP succeeded.\n");
}
else
{
MyHandleError("A key identifier was not created");
}
//-------------------------------------------------------------------
// Set the members of the key identifier.
KeyIdentifier.cbData= cbHash;
KeyIdentifier.pbData= (BYTE*) pbHash;
//-------------------------------------------------------------------
// Initialize the pdata structure.
if(!(pData= (CRYPT_KEY_PROV_INFO*) malloc
(sizeof(CRYPT_KEY_PROV_INFO))))
MyHandleError("Memory allocation failed.");
pData->pwszContainerName= L"New Key container name";
pData->pwszProvName= MS_ENHANCED_PROV_W;
pData->dwProvType= PROV_RSA_FULL;
pData->dwFlags= 0;
pData->cProvParam= 0;
pData->rgProvParam= NULL;
pData->dwKeySpec= AT_SIGNATURE;
//-------------------------------------------------------------------
// Set a property on the created key identifier.
if(CryptSetKeyIdentifierProperty(
&KeyIdentifier, // in- defined above
CERT_KEY_PROV_INFO_PROP_ID, // in- dwPropId
CRYPT_KEYID_MACHINE_FLAG, // in- dwFlags- use local computer
NULL, // in- pwszComputerName
NULL, // Reserved
pData // in- pointer to a
// CRYPT_KEY_PROV_INFO.
))
{
printf("A property is set on the key identifier.\n");
}
else
{
MyHandleError("Setting the property failed.");
}
//-------------------------------------------------------------------
// Call CryptGetKeyIdentifierProperty to set the size
// of the property to be retrieved.
if(CryptGetKeyIdentifierProperty(
&KeyIdentifier, // in- defined above
CERT_KEY_PROV_INFO_PROP_ID, // in- dwPropId
CRYPT_KEYID_MACHINE_FLAG, // in- dwFlags
NULL, // in, optional- pwszComputerName
NULL, // in, optional- pvReserved
NULL, // out- pvData
&cbData // in, out- pcbData
))
{
printf("First call to get property succeeded.\n");
}
else
{
MyHandleError("Call 1 to CryptGetKeyIdentifierProperty failed.");
}
//-------------------------------------------------------------------
// Free the memory allocated for pData,
free(pData);
//-------------------------------------------------------------------
// Allocate memory for the buffer to receive the property.
if(!(pData= (CRYPT_KEY_PROV_INFO*) malloc (cbData)))
MyHandleError("Memory allocation failed.");
//-------------------------------------------------------------------
// Call CryptGetKeyIdentifierProperty a second time
// To retrieve the property into the allocated buffer.
if(CryptGetKeyIdentifierProperty(
&KeyIdentifier, // pKeyIdentifier
CERT_KEY_PROV_INFO_PROP_ID, // dwPropId
CRYPT_KEYID_MACHINE_FLAG, // dwFlags
NULL, // pwszComputerName
NULL, // Reserved
pData, // pData
&cbData // pcbData
))
{
printf("The property has been retrieved.\n");
}
else
{
MyHandleError("Second call failed.");
}
//-------------------------------------------------------------------
// Print part of the retrieved property.
printf("Some of the properties obtained are;\n");
printf("container name= %S\n",pData->pwszContainerName);
printf("Provider name= %S\n", pData->pwszProvName);
printf("Provider type= %i\n", pData->dwProvType);
printf("length= %i\n\n", cbData);
//-------------------------------------------------------------------
// Set the pass through argument for the callback function.
pvArg= pPubKeyStruc;
//-------------------------------------------------------------------
// Call CryptEnumKeyIdentifierProperties.
printf("\nCalling CryptEnumKeyIdentifierProperties.\n");
if(CryptEnumKeyIdentifierProperties(
&KeyIdentifier, // in- pKeyIdentifier-
0, // in- dwPropId
CRYPT_KEYID_MACHINE_FLAG, // in- dwFlags, use LocalMachine.
NULL, // in, optional- pwszComputerName set
// to NULL to use LocalMachine.
NULL, // Reserved
pvArg, // in, optional- Pointer to the
// pass-through argument
(PFN_CRYPT_ENUM_KEYID_PROP )pfnEnum
// in- Callback function.
))
{
printf("The function call succeeded.\n");
}
else
{
MyHandleError("Call to CryptEnumKeyIdentifierProperties failed.");
}
//-------------------------------------------------------------------
// Free all allocated memory
free (pData);
free (pPubKeyStruc);
printf("all memory free\n");
printf("The program ran to completion without error.\n");
} // end main.
//-------------------------------------------------------------------
// Define the Callback function
static BOOL WINAPI pfnEnum (
const CRYPT_HASH_BLOB *pKeyIdentifier, // in- pKeyIdentifier
DWORD dwFlags, // in- Flag values
void *pvReserved, // Reserved
void *pvArg, // in- Pass-through argument
DWORD cProp, // in- cProp
DWORD *rgdwPropId, // in- rgdwPropId
void **rgpvData, // in- rgpvData- points to an
// array of
// CRYPT_KEY_PROV_INFO
// structures
DWORD *rgcbData // in- rgcbData
)
{
//-------------------------------------------------------------------
// Declare and initialize local variables.
PUBLICKEYSTRUC *pArg= (PUBLICKEYSTRUC *) pvArg;
//-------------------------------------------------------------------
// Begin processing
printf("The argument passed is a structure.\n");
printf("BLOB type= %x ", pArg->bType);
printf("Version= %x\n", pArg->bVersion);
printf("Algorithm= %x\n\n", pArg->aiKeyAlg);
return TRUE;
} // end callback function.
//-------------------------------------------------------------------
// Define MyHandleError
void MyHandleError(char *s)
{
printf("\n An error has occurred. \n");
printf("The error message is %s \n",s);
printf("Last error is %x \n",GetLastError());
exit(1);
} // end MyHandleError.