範例 C 程式:取得和設定憑證屬性
下列範例會取得及設定憑證屬性,並說明下列工作和 CryptoAPI 函式。
- 使用 CertOpenSystemStore開啟系統存放區。
- 使用 CertEnumCertificatesInStore 列出開啟存放區中的所有憑證。
- 使用 CertGetNameString從憑證擷取和列印主體名稱。
- 使用CertAddEnhancedKeyUsageIdentifier函式,在憑證上設定增強金鑰使用屬性。
- 使用 CertSetCertificateCoNtextProperty在憑證上設定顯示名稱屬性。
- 使用 CertGetCertificateCoNtextProperty擷取憑證的屬性。
- 使用 CertCloseStore 搭配 CERT_CLOSE_STORE_CHECK_FLAG 旗標關閉憑證存放區。
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")
//--------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Declare functions MyHandleError and My_Wait.
// These functions are defined at the end of the file.
void MyHandleError(char *s );
void My_Wait();
//--------------------------------------------------------------------
// Begin main.
void main (void)
{
//--------------------------------------------------------------------
// This program shows all of the certificates in a
// certificate store and lists all of the property ID numbers of all
// of the certificate contexts.
// It also adds an enhanced key usage identifier to every other
// certificate.
//--------------------------------------------------------------------
// Declare and initialize local variables.
HANDLE hCertStore;
PCCERT_CONTEXT pCertContext=NULL;
CRYPT_KEY_PROV_INFO *pCryptKeyProvInfo;
char pszNameString[256];
char pszStoreName[256];
char fResponse;
char fExtra;
BYTE *pName = (BYTE *)"Temp Name.";
CRYPT_DATA_BLOB Friendly_Name_Blob={32,pName};
void* pvData;
DWORD cbData;
DWORD dwFlags = CERT_STORE_NO_CRYPT_RELEASE_FLAG;
DWORD dwPropId = 0; // 0 must be used on the first
// call to the function. After that,
// the last returned property ID is
// passed.
LPCSTR pszUsageIdentifier = szOID_RSA_RC4;
int count = 0;
fprintf(stderr,"Please enter the store name :");
scanf_s("%s",pszStoreName);
fprintf(stderr,"The store name is %s .\n",pszStoreName);
My_Wait();
//--------------------------------------------------------------------
// Open the named system certificate store.
if (!( hCertStore = CertOpenSystemStore(
NULL,
pszStoreName)))
{
MyHandleError("Store not opened.");
}
//--------------------------------------------------------------------
// The file is open. Continue.
// In a loop, use CertEnumCertificatesInStore to get the each
// certificate in the store.
while(pCertContext= CertEnumCertificatesInStore(
hCertStore,
pCertContext))
{
//--------------------------------------------------------------------
// First, retrieve and print the subject name from the certificate.
if(CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszNameString,
128))
{
printf("\nNew Cert for %s \n",pszNameString);
}
else
{
printf("The get name failed.\n");
}
//--------------------------------------------------------------------
// Set the enhanced key usage property on every other certificate.
if(count == 0)
{
count++;
if(CertAddEnhancedKeyUsageIdentifier(
pCertContext,
pszUsageIdentifier))
{
printf("Enhanced key usage set.\n");
}
else
{
printf("Enhanced key usage was not set.\n");
}
}
else
//--------------------------------------------------------------------
// Do not set the usage, but reset the counter so that the property
// will be set on the next certificate.
// Ask if the user would like to set a display name.
{
printf("Would you like to set the display name ?");
scanf_s("%c%c",&fResponse,&fExtra);
if(fResponse == 'y')
{
if(CertSetCertificateContextProperty(
pCertContext,
CERT_FRIENDLY_NAME_PROP_ID,
0,
&Friendly_Name_Blob))
{
printf("A name has been set.\n");
}
else
{
printf("The display name was not set.\n");
}
}
count = 0;
}
//--------------------------------------------------------------------
// In a loop, find all of the property IDs for the given certificate.
// The loop continues until the CertEnumCertificateContextProperties
// returns 0.
while(dwPropId = CertEnumCertificateContextProperties(
pCertContext, // the context whose properties are to be listed.
dwPropId)) // number of the last property found. Must be
// 0 to find the first property ID.
{
//--------------------------------------------------------------------
// Each time through the loop, a property ID has been found.
// Print the property number and information about the property.
printf("Property # %d found->", dwPropId);
switch(dwPropId)
{
case CERT_FRIENDLY_NAME_PROP_ID:
{
//--------------------------------------------------------------------
// Retrieve the actual display name certificate property.
// First, get the length of the property setting the
// pvData parameter to NULL to get a value for cbData
// to be used to allocate memory for the pvData buffer.
printf("FRIENDLY_NAME_PROP_ID ");
if(!(CertGetCertificateContextProperty(
pCertContext,
dwPropId,
NULL,
&cbData)))
{
MyHandleError("Call #1 to property length failed.");
}
//--------------------------------------------------------------------
// The call succeeded. Use the size to allocate memory for the
// property.
if(!(pvData = (void*)malloc(cbData)))
{
MyHandleError("Memory allocation failed.");
}
//--------------------------------------------------------------------
// Allocation succeeded. Retrieve the property data.
if(!(CertGetCertificateContextProperty(
pCertContext,
dwPropId,
pvData,
&cbData)))
{
MyHandleError("Call #2 getting the data failed.");
}
else
{
printf("\n The display name is -> %s.", pvData);
free(pvData);
}
break;
}
case CERT_SIGNATURE_HASH_PROP_ID:
{
printf("Signature hash ID. ");
break;
}
case CERT_KEY_PROV_HANDLE_PROP_ID:
{
printf("KEY PROVE HANDLE.");
break;
}
case CERT_KEY_PROV_INFO_PROP_ID:
{
printf("KEY PROV INFO PROP ID.");
if(!(CertGetCertificateContextProperty(
pCertContext, // A pointer to the certificate
// where the property will be set.
dwPropId, // An identifier of the property to get.
// In this case,
// CERT_KEY_PROV_INFO_PROP_ID
NULL, // NULL on the first call to get the
// length.
&cbData))) // The number of bytes that must be
// allocated for the structure.
{
MyHandleError("The property length was not retrieved.");
}
if(!(pCryptKeyProvInfo =
(CRYPT_KEY_PROV_INFO *)malloc(cbData)))
{
MyHandleError("Error in allocation of memory.");
}
if(CertGetCertificateContextProperty(
pCertContext,
dwPropId,
pCryptKeyProvInfo,
&cbData))
{
printf("\n The current key container is %S.",
pCryptKeyProvInfo->pwszContainerName);
free(pCryptKeyProvInfo);
}
else
{
free(pCryptKeyProvInfo);
MyHandleError("The property was not retrieved.");
}
break;
}
case CERT_SHA1_HASH_PROP_ID:
{
printf("SHA1 HASH id.");
break;
}
case CERT_MD5_HASH_PROP_ID:
{
printf("md5 hash id. ");
break;
}
case CERT_KEY_CONTEXT_PROP_ID:
{
printf("KEY CONTEXT PROP id.");
break;
}
case CERT_KEY_SPEC_PROP_ID:
{
printf("KEY SPEC PROP id.");
break;
}
case CERT_ENHKEY_USAGE_PROP_ID:
{
printf("ENHKEY USAGE PROP id.");
break;
}
case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
{
printf("NEXT UPDATE LOCATION PROP id.");
break;
}
case CERT_PVK_FILE_PROP_ID:
{
printf("PVK FILE PROP id. ");
break;
}
case CERT_DESCRIPTION_PROP_ID:
{
printf("DESCRIPTION PROP id. ");
break;
}
case CERT_ACCESS_STATE_PROP_ID:
{
printf("ACCESS STATE PROP id. ");
break;
}
case CERT_SMART_CARD_DATA_PROP_ID:
{
printf("SMAART_CARD DATA PROP id. ");
break;
}
case CERT_EFS_PROP_ID:
{
printf("EFS PROP id. ");
break;
}
case CERT_FORTEZZA_DATA_PROP_ID:
{
printf("FORTEZZA DATA PROP id.");
break;
}
case CERT_ARCHIVED_PROP_ID:
{
printf("ARCHIVED PROP id.");
break;
}
case CERT_KEY_IDENTIFIER_PROP_ID:
{
printf("KEY IDENTIFIER PROP id. ");
break;
}
case CERT_AUTO_ENROLL_PROP_ID:
{
printf("AUTO ENROLL id. ");
break;
}
} // end switch
printf("\n");
} // end the inner while loop. This is the end of the display of
// a single property of a single certificate.
My_Wait();
} // end the outer while loop. Move on to the next certificate.
//--------------------------------------------------------------------
// Free Memory and close the open store.
if(pCertContext)
{
CertFreeCertificateContext(pCertContext);
}
CertCloseStore(hCertStore,0);
printf("The function completed successfully.\n");
}
//--------------------------------------------------------------------
// Define functions MyHandleError and My_Wait.
void MyHandleError( char *s)
{
printf("%s\n",s);
exit(1);
}
void My_Wait()
{
printf("Hit enter to continue.");
getchar();
}