Exemple de programme C : encodage et décodage d’un message contre-signé
L’exemple suivant montre comment encoder et décoder un message contre-signé. Cet exemple utilise la fonction d’exemple MyHandleError . Le code de la fonction MyHandleError et d’autres fonctions auxiliaires est également répertorié sous usage général Fonctions.
#include <stdafx.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <wincrypt.h>
// Link with the Crypt32.lib file.
#pragma comment (lib, "crypt32")
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
//-------------------------------------------------------------------
// Define the names of two certificate subjects.
// To use this program, the definitions of SIGNER_NAME and
// COUNTER_SIGNER_NAME must be changed to the names of
// the subjects of certificates that have access to private keys.
// These certificates must have either the
// CERT_KEY_PROV_INFO_PROP_ID or CERT_KEY_CONTEXT_PROP_ID
// property set for the contexts to provide access to private
// signature keys.
#define SIGNER_NAME L"Insert_signer_name_here"
#define COUNTER_SIGNER_NAME L"Insert_counter_signer_name_here"
#define MAX_NAME 256
void MyHandleError(char *s);
int _tmain(int argc, _TCHAR* argv[])
{
//---------------------------------------------------------------
// Declare and initialize variables. This includes declaring and
// initializing a pointer to message content to be countersigned
// and encoded. Usually, the message content will exist somewhere
// and a pointer to it is passed to the application.
BYTE* pbContent;
DWORD cbContent;
HCRYPTPROV hCryptProv;
HCERTSTORE hStoreHandle;
PCCERT_CONTEXT pSignerCert;
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[1];
CERT_BLOB SignerCertBlob;
CERT_BLOB SignerCertBlobArray[1];
CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
DWORD cbEncodedBlob;
BYTE* pbEncodedBlob;
HCRYPTMSG hMsg;
DWORD cbDecoded;
BYTE *pbDecoded;
PCCERT_CONTEXT pCntrSigCert;
CMSG_SIGNER_ENCODE_INFO CountersignerInfo;
CMSG_SIGNER_ENCODE_INFO CntrSignArray[1];
DWORD cbSignerInfo;
PBYTE pbSignerInfo;
DWORD cbCountersignerInfo;
PCRYPT_ATTRIBUTES pCountersignerInfo;
char pszNameString[MAX_NAME];
CRYPT_VERIFY_MESSAGE_PARA VerifyParams;
BYTE *pbDecodedMessageBlob;
DWORD cbDecodedMessageBlob;
DWORD dwKeySpec;
// The message.
pbContent = (BYTE*)"I must go back to where all messages start.";
//---------------------------------------------------------------
// Begin processing.
//---------------------------------------------------------------
// Initialize cbContent to the length of pbContent
// including the terminating NULL character.
cbContent = lstrlenA((char *) pbContent) + 1;
printf("The example message is ->.\n");
printf("%s\n\n", pbContent);
//---------------------------------------------------------------
// Open the MY system certificate store.
if(!(hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"MY")))
{
MyHandleError("Could not open the MY system store.");
}
//---------------------------------------------------------------
// Get a pointer to a signer's signature certificate.
if(pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_ENCODING_TYPE,
0,
CERT_FIND_SUBJECT_STR,
SIGNER_NAME,
NULL))
{
//-----------------------------------------------------------
// A certificate was found. Get and print the name of the
// subject of the certificate.
if(CertGetNameStringA(
pSignerCert,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszNameString,
MAX_NAME) > 1)
{
printf("The message signer is %s.\n",pszNameString);
}
else
{
MyHandleError("Getting the signer name failed.\n");
}
}
else
{
MyHandleError("Cert not found.\n");
}
//---------------------------------------------------------------
// Initialize the CMSG_SIGNER_ENCODE_INFO structure.
//---------------------------------------------------------------
// Get a handle to a cryptographic provider.
if(!(CryptAcquireCertificatePrivateKey(
pSignerCert,
0,
NULL,
&hCryptProv,
&dwKeySpec,
NULL)))
{
MyHandleError("CryptAcquireContext failed.");
}
memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
SignerEncodeInfo.pCertInfo = pSignerCert->pCertInfo;
SignerEncodeInfo.hCryptProv = hCryptProv;
SignerEncodeInfo.dwKeySpec = dwKeySpec;
SignerEncodeInfo.HashAlgorithm.pszObjId = szOID_RSA_MD5;
SignerEncodeInfo.pvHashAuxInfo = NULL;
//---------------------------------------------------------------
// Initialize the first element of an array of signers.
// Note: Currently, there is only one signer.
SignerEncodeInfoArray[0] = SignerEncodeInfo;
//---------------------------------------------------------------
// Initialize the CMSG_SIGNED_ENCODE_INFO structure.
SignerCertBlob.cbData = pSignerCert->cbCertEncoded;
SignerCertBlob.pbData = pSignerCert->pbCertEncoded;
//---------------------------------------------------------------
// Initialize the first element of an array of signer BLOBs.
// Note: In this program, only one signer BLOB is used.
SignerCertBlobArray[0] = SignerCertBlob;
memset(&SignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
SignedMsgEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
SignedMsgEncodeInfo.cSigners = 1;
SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray;
SignedMsgEncodeInfo.cCertEncoded = 1;
SignedMsgEncodeInfo.rgCertEncoded = SignerCertBlobArray;
//---------------------------------------------------------------
// Get the size of the encoded message BLOB.
cbEncodedBlob = CryptMsgCalculateEncodedLength(
MY_ENCODING_TYPE,
0,
CMSG_SIGNED,
&SignedMsgEncodeInfo,
NULL,
cbContent);
if(!cbEncodedBlob)
{
MyHandleError("Getting cbEncodedBlob length failed.");
}
//---------------------------------------------------------------
// Allocate memory for the encoded BLOB.
pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob);
if(!pbEncodedBlob)
{
MyHandleError("malloc operation failed.");
}
//---------------------------------------------------------------
// Open a message to encode.
hMsg = CryptMsgOpenToEncode(
MY_ENCODING_TYPE,
0,
CMSG_SIGNED,
&SignedMsgEncodeInfo,
NULL,
NULL);
if(!hMsg)
{
MyHandleError("OpenToEncode failed.");
}
//---------------------------------------------------------------
// Update the message with the data.
if(!(CryptMsgUpdate(
hMsg,
pbContent,
cbContent,
TRUE)))
{
MyHandleError("CryptMsgUpdate failed.");
}
//---------------------------------------------------------------
// Get the resulting message.
if(CryptMsgGetParam(
hMsg,
CMSG_CONTENT_PARAM,
0,
pbEncodedBlob,
&cbEncodedBlob))
{
printf("Message successfully signed.\n");
}
else
{
MyHandleError("CryptMsgGetParam failed.");
}
//---------------------------------------------------------------
// The message is signed and encoded.
// Close the message handle and the certificate store.
CryptMsgClose(hMsg);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
CryptReleaseContext(hCryptProv,0);
//---------------------------------------------------------------
// Next, countersign the signed message.
// Assume that pbEncodedBlob, the message just created, was sent
// to an intended recipient.
// From the recipient's point of view, the following code
// completes these steps:
// 1. Decodes the message
// 2. Verifies the signature on the message
// 3. Adds a countersignature to the signed message
//
// The counter-signed message is returned to the original signer
// of the message, where the counter-signature is verified.
//---------------------------------------------------------------
// Open a message for decoding.
hMsg = CryptMsgOpenToDecode(
MY_ENCODING_TYPE,
0,
0,
NULL,
NULL,
NULL);
if(!hMsg)
{
MyHandleError("CryptOpenToDecode failed.");
}
//---------------------------------------------------------------
// Update the message with the encoded BLOB.
if(!(CryptMsgUpdate(
hMsg,
pbEncodedBlob,
cbEncodedBlob,
TRUE)))
{
MyHandleError("Decode CryptMsgUpdate failed.");
}
//---------------------------------------------------------------
// Get the size of the message.
if(CryptMsgGetParam(
hMsg,
CMSG_CONTENT_PARAM,
0,
NULL,
&cbDecoded))
{
printf("The message is %d bytes long.\n", cbDecoded);
}
else
{
MyHandleError("Decode CMSG_CONTENT_PARAM failed.");
}
//---------------------------------------------------------------
// Allocate memory.
pbDecoded = (BYTE*)malloc(cbDecoded);
if(!pbDecoded)
{
MyHandleError("Decode memory allocation failed.");
}
//---------------------------------------------------------------
// Copy the message to the buffer.
if(CryptMsgGetParam(
hMsg,
CMSG_CONTENT_PARAM,
0,
pbDecoded,
&cbDecoded))
{
printf("The successfully decoded message is -> ");
printf("%s\n", pbDecoded);
}
else
{
MyHandleError("Decode CMSG_CONTENT_PARAM #2 failed.");
}
//---------------------------------------------------------------
// Check the signature.
// Initialize the VerifyParams data structure.
VerifyParams.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);
VerifyParams.dwMsgAndCertEncodingType = MY_ENCODING_TYPE;
VerifyParams.hCryptProv = 0;
VerifyParams.pfnGetSignerCertificate = NULL;
VerifyParams.pvGetArg = NULL;
if(!(CryptVerifyMessageSignature(
&VerifyParams,
0,
pbEncodedBlob,
cbEncodedBlob,
NULL,
&cbDecodedMessageBlob,
NULL)))
{
printf("Getting the size of the verification message " \
"failed.\n");
}
pbDecodedMessageBlob = (BYTE*)malloc(cbDecodedMessageBlob);
if(!pbDecodedMessageBlob)
{
MyHandleError("Memory allocation failed.");
}
if(CryptVerifyMessageSignature(
&VerifyParams,
0,
pbEncodedBlob,
cbEncodedBlob,
pbDecodedMessageBlob,
&cbDecodedMessageBlob,
NULL))
{
printf("The Signature verified message is -> \n");
printf("%s \n\n",pbDecodedMessageBlob);
}
else
{
MyHandleError("Verification message failed.");
}
//---------------------------------------------------------------
// Proceed with the countersigning.
// First, open a certificate store.
if(!(hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"MY")))
{
MyHandleError("Could not open the MY system store.");
}
//---------------------------------------------------------------
// Get the countersigner's certificate.
if(pCntrSigCert = CertFindCertificateInStore(
hStoreHandle,
MY_ENCODING_TYPE,
0,
CERT_FIND_SUBJECT_STR,
COUNTER_SIGNER_NAME,
NULL))
{
if(CertGetNameStringA(
pCntrSigCert ,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszNameString,
MAX_NAME) > 1)
{
printf("The counter signer is %s.\n", pszNameString);
}
else
{
MyHandleError("Getting the countersigner name " \
"failed.\n");
}
}
else
{
MyHandleError("Could not find the countersigner's " \
"certificate.");
}
//---------------------------------------------------------------
// Initialize the CMSG_SIGNER_ENCODE_INFO structure.
if(!(CryptAcquireCertificatePrivateKey(
pCntrSigCert,
0,
NULL,
&hCryptProv,
&dwKeySpec,
NULL)))
{
MyHandleError("CryptAcquireContext failed.");
}
memset(&CountersignerInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
CountersignerInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
CountersignerInfo.pCertInfo = pCntrSigCert->pCertInfo;
CountersignerInfo.hCryptProv = hCryptProv;
CountersignerInfo.dwKeySpec = dwKeySpec;
CountersignerInfo.HashAlgorithm.pszObjId = szOID_RSA_MD5;
CntrSignArray[0] = CountersignerInfo;
//---------------------------------------------------------------
// Countersign the message.
if(CryptMsgCountersign(
hMsg,
0,
1,
CntrSignArray))
{
printf("CryptMsgCountersign succeeded.\n");
}
else
{
MyHandleError("CryptMsgCountersign failed.");
}
//---------------------------------------------------------------
// Get a pointer to the new, countersigned message BLOB.
// Get the size of memory required.
if(CryptMsgGetParam(
hMsg,
CMSG_ENCODED_MESSAGE,
0,
NULL,
&cbEncodedBlob))
{
printf("The size of the encoded BLOB is %d.\n",
cbEncodedBlob);
}
else
{
MyHandleError("Sizing of cbSignerInfo failed.");
}
//---------------------------------------------------------------
// Allocate memory.
pbEncodedBlob = (BYTE*) malloc(cbEncodedBlob);
if(pbEncodedBlob)
{
printf("%d bytes allocated.\n", cbEncodedBlob);
}
else
{
MyHandleError("cbSignerInfo memory allocation failed.");
}
//---------------------------------------------------------------
// Get the new message encoded BLOB.
if(CryptMsgGetParam(
hMsg,
CMSG_ENCODED_MESSAGE,
0,
pbEncodedBlob,
&cbEncodedBlob))
{
printf("The message is complete. \n");
}
else
{
MyHandleError("Getting pbEncodedBlob failed.");
}
//---------------------------------------------------------------
// The message is complete. Close the handle.
CryptMsgClose(hMsg);
//---------------------------------------------------------------
// Verify the countersignature.
// Assume that the countersigned message
// went back to the originator,
// where, again, it will be decoded.
//---------------------------------------------------------------
// Before verifying the countersignature,
// the message must first
// be decoded.
//---------------------------------------------------------------
// Open a message for decoding.
if(hMsg = CryptMsgOpenToDecode(
MY_ENCODING_TYPE,
0,
0,
0,
NULL,
NULL))
{
printf("The message to decode has been opened.\n");
}
else
{
MyHandleError("CryptMsgOpenToDecode failed.");
}
//---------------------------------------------------------------
// Update the message with the encoded BLOB.
if(CryptMsgUpdate(
hMsg,
pbEncodedBlob,
cbEncodedBlob,
TRUE))
{
printf("The message to decode has been updated.\n");
}
else
{
MyHandleError("Updating the countersignature message " \
"failed.");
}
//---------------------------------------------------------------
// Get a pointer to the CERT_INFO member of
// countersigner's certificate.
//---------------------------------------------------------------
// Retrieve the signer information from the message.
// Get the size of memory required.
if(CryptMsgGetParam(
hMsg,
CMSG_ENCODED_SIGNER,
0,
NULL,
&cbSignerInfo))
{
printf("Signer information is %d bytes.\n", cbSignerInfo);
}
else
{
MyHandleError("Sizing of cbSignerInfo failed.");
}
//---------------------------------------------------------------
// Allocate memory.
pbSignerInfo = (BYTE*) malloc(cbSignerInfo);
if(!pbSignerInfo)
{
MyHandleError("cbSignerInfo memory allocation failed.");
}
//---------------------------------------------------------------
// Get the message signer information.
if(!(CryptMsgGetParam(
hMsg,
CMSG_ENCODED_SIGNER,
0,
pbSignerInfo,
&cbSignerInfo)))
{
MyHandleError("Getting pbSignerInfo failed.");
}
//---------------------------------------------------------------
// Retrieve the countersigner information from the message.
// Get the size of memory required.
if(CryptMsgGetParam(
hMsg,
CMSG_SIGNER_UNAUTH_ATTR_PARAM,
0,
NULL,
&cbCountersignerInfo))
{
printf("Counter Signer information is %d bytes.\n",
cbCountersignerInfo);
}
else
{
MyHandleError("Sizing of cbCountersignerInfo failed.");
}
//---------------------------------------------------------------
// Allocate memory.
pCountersignerInfo =
(CRYPT_ATTRIBUTES*)malloc(cbCountersignerInfo);
if(!pCountersignerInfo)
{
MyHandleError("pbCountersignInfo memory allocation failed.");
}
//---------------------------------------------------------------
// Get the message counter signer info.
if(!(CryptMsgGetParam(
hMsg,
CMSG_SIGNER_UNAUTH_ATTR_PARAM,
0,
pCountersignerInfo,
&cbCountersignerInfo)))
{
MyHandleError("Getting pbCountersignerInfo failed.");
}
//---------------------------------------------------------------
// Verify the countersignature.
if(CryptMsgVerifyCountersignatureEncoded(
0,
MY_ENCODING_TYPE,
pbSignerInfo,
cbSignerInfo,
pCountersignerInfo->rgAttr->rgValue->pbData,
pCountersignerInfo->rgAttr->rgValue->cbData,
pCntrSigCert->pCertInfo))
{
printf("Verification of countersignature succeeded.\n");
}
else
{
printf("Verification of countersignature failed.\n");
if(GetLastError() == NTE_BAD_SIGNATURE)
{
printf("Bad signature.\n");
}
else
{
printf("Other verification error.\n");
}
}
//---------------------------------------------------------------
// Clean up.
free(pbEncodedBlob);
free(pbDecoded);
free(pbSignerInfo);
free(pCountersignerInfo);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
CryptMsgClose(hMsg);
CryptReleaseContext(hCryptProv,0);
return 0;
}
//-------------------------------------------------------------------
// Define function MyHandleError
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);
}
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour