Exemple de programme C : sérialisation des certificats
L’exemple suivant illustre la sérialisation d’un contexte de certificat et de ses propriétés dans un formulaire qui peut être stocké dans un fichier, envoyé avec un e-mail ou transmis à un autre utilisateur. L’exemple montre également comment le certificat sérialisé peut être recondigné en certificat et ajouté à un magasin de certificats. Le même processus fonctionne également avec les listes de révocation decertificats et de certificats à l’aide de CertSerializeCRLStoreElement et CertSerializeCTLStoreElement.
Cet exemple illustre les tâches et fonctions CryptoAPI suivantes :
- Ouverture d’un magasin de certificats système à l’aide de CertOpenSystemStore.
- Ouverture d’un magasin de certificats à l’aide de CertOpenStore.
- Récupération d’un certificat à partir d’un magasin à l’aide de CertEnumCertificatesInStore.
- Obtention du nom de l’objet du certificat à l’aide de CertGetNameString.
- Création d’une forme sérialisée d’un contexte de certificat et de ses propriétés à l’aide de CertSerializeCertificateStoreElement.
- Création d’un certificat à partir d’une chaîne sérialisée et ajout de celui-ci dans un magasin de certificats à l’aide de CertAddSerializedElementToStore.
- Utilisation de CertAddEncodedCertificateToStore pour créer un certificat à partir de la partie encodée d’un certificat existant.
- Utilisation de CertCloseStore pour fermer un magasin de certificats.
//------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Example that uses CertSerializeCertificateStoreElement to
// serialize the data from a certificate,
// and CertAddSerializedElementToStore to add that data as a new
// certificate to a store.
// CertAddEncodeCertificateToStore is also demonstrated.
#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(char *s);
void main(void)
{
//-------------------------------------------------------------------
// Declare and initialize variables.
HCERTSTORE hSystemStore;
HCERTSTORE hFileStore;
PCCERT_CONTEXT pCertContext = NULL;
char pszNameString[256];
BYTE* pbElement;
DWORD cbElement;
//-------------------------------------------------------------------
// Open a system certificate store.
if(hSystemStore = CertOpenSystemStore(
0,
"CA"))
{
printf("The CA system store is open. Continue.\n");
}
else
{
MyHandleError("The first system store did not open.");
}
//-------------------------------------------------------------------
// Open a second store.
// In order to work, a file-based certificate store named
// teststor.sto must be available in the working directory.
if(hFileStore = CertOpenStore(
CERT_STORE_PROV_FILENAME,
MY_ENCODING_TYPE,
NULL,
0,
L"testStor.sto" ))
{
printf("The file store is open. Continue.\n");
}
else
{
MyHandleError("The file store did not open.");
}
//-------------------------------------------------------------------
// Retrieve the first certificate from the Root store.
// CertFindCertificateInStore could be used here to find
// a certificate with a specific property.
if(pCertContext=CertEnumCertificatesInStore(
hSystemStore,
pCertContext))
{
printf("A certificate is available. Continue.\n");
}
else
{
MyHandleError("No certificate available. "
"The store may be empty.");
}
//-------------------------------------------------------------------
// 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);
}
else
{
printf("CertGetName failed. \n");
}
//-------------------------------------------------------------------
// Find out how much memory to allocate for the serialized element.
if(CertSerializeCertificateStoreElement(
pCertContext, // The existing certificate.
0, // Accept default for dwFlags,
NULL, // NULL for the first function call.
&cbElement)) // Address where the length of the
// serialized element will be placed.
{
printf("The length of the serialized string is %d.\n",
cbElement);
}
else
{
MyHandleError("Finding the length of the serialized "
"element failed.");
}
//-------------------------------------------------------------------
// Allocate memory for the serialized element.
if(pbElement = (BYTE*)malloc(cbElement))
{
printf("Memory has been allocated. Continue.\n");
}
else
{
MyHandleError("The allocation of memory failed.");
}
//-------------------------------------------------------------------
// Create the serialized element from a certificate context.
if(CertSerializeCertificateStoreElement(
pCertContext, // The certificate context source for the
// serialized element.
0, // dwFlags. Accept the default.
pbElement, // A pointer to where the new element will
// be stored.
&cbElement)) // The length of the serialized element,
{
printf("The encoded element has been serialized. \n");
}
else
{
MyHandleError("The element could not be serialized.");
}
//-------------------------------------------------------------------
// pbElement could be written to a file or be sent by email
// to another user.
// The following process uses the serialized
// pbElement and its length, cbElement, to
// add a new certificate to a store.
if(CertAddSerializedElementToStore(
hFileStore, // Store where certificate is to be added.
pbElement, // The serialized element for another
// certificate.
cbElement, // The length of pbElement.
CERT_STORE_ADD_REPLACE_EXISTING,
// Flag to indicate what to do if a matching
// certificate is already in the store.
0, // dwFlags. Accept the default.
CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
NULL,
NULL
))
{
printf("The new certificate is added to the second store.\n");
}
else
{
MyHandleError("The new element was not added to a store.");
}
//-------------------------------------------------------------------
// Next, another certificate will be retrieved from the system store
// and its encoded part, pCertContext->pbCertEncoded, will be
// used to create a new certificate to be added to the file store.
if(pCertContext=CertEnumCertificatesInStore(
hSystemStore,
pCertContext))
{
printf("Another certificate is available. Continue.\n");
}
else
{
MyHandleError("No certificate is available. "
"The store may be empty.");
}
//-------------------------------------------------------------------
// 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);
}
else
{
printf("CertGetName failed. \n");
}
//-------------------------------------------------------------------
// Create a new certificate from the encoded portion of pCertContext
// and add it to the file-based store.
if(CertAddEncodedCertificateToStore(
hFileStore,
MY_ENCODING_TYPE,
pCertContext->pbCertEncoded,
pCertContext->cbCertEncoded,
CERT_STORE_ADD_USE_EXISTING,
NULL))
{
printf("Another certificate is added to the file store.\n");
}
else
{
MyHandleError("The new certificate was not added to the "
"file store.");
}
//-------------------------------------------------------------------
// Free memory.
free(pbElement);
CertCloseStore(hSystemStore,0);
CertCloseStore(hFileStore,0);
printf("The program ran without error to the end.\n");
} // End of main
//-------------------------------------------------------------------
// This example uses the function MyHandleError, a simple error
// handling function, to print an error message to the standard
// error (stderr) file and exit the program.
// For most applications, replace this function with one
// that does more extensive error reporting.
void MyHandleError(char *s)
{
fprintf(stderr,"An error occurred in running the program. \n");
fprintf(stderr,"%s\n",s);
fprintf(stderr, "Error number %x.\n", GetLastError());
fprintf(stderr, "Program terminating. \n");
exit(1);
} // End of MyHandleError