Example Code Using CryptEncryptMessage

The following example code implements the procedure just presented. Comments show which code fragments pertain to each step in the procedure. The details of the functions and structures can be found in Simplified Message Functions and Data Structures.

//-------------------------------------------------------------
//-------------------------------------------------------------
// EXAMPLE CODE FOR ENCRYPTING DATA AND CREATING AN ENVELOPED
// MESSAGE USING CryptEncryptMessage().
//-------------------------------------------------------------
//-------------------------------------------------------------

// Use this constant definition (or one similar to it) to define
// a single encoding type that can be used in all parameters and
// data members that require one or the other or both.
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

//-------------------------------------------------------------
// Get a pointer to the message - this code creates a message
// and gets a pointer to it. In reality, the content 
// will usually exist somewhere and a pointer will get passed to the
// application (Steps 1 and 2).
//-------------------------------------------------------------
char szContent[] = "A Razzle-Dazzle\n"
                        "Secret Message";    // The message
char* pszContent = szContent;                // A string pointer
BYTE* pbContent = (BYTE*) pszContent;        // A byte pointer
DWORD cbContent = sizeof(szContent);         // Size of message

AfxMessageBox(pszContent);

//-------------------------------------------------------------
// Get a handle to a cryptographic provider (Step 3).
//-------------------------------------------------------------
HCRYPTPROV hCryptProv = NULL; // Handle returned here
BOOL fReturn = FALSE;

fReturn = CryptAcquireContext(
            &hCryptProv,         // Address for handle to be returned.
            NULL,                // Use the current user's logon name.
            NULL,                // Use the default provider.
            PROV_RSA_FULL,       // Need to do both encrypt & sign.
            NULL);               // No flags needed.
if(TRUE != fReturn)
    ; // An error occurred. Call GetLastError and handle.
fReturn = FALSE;

// If the function succeeded, the handle to the cryptographic
// provider resides at hCryptProv.

//-------------------------------------------------------------
// Open the system certificate store (Step 4).
//-------------------------------------------------------------

HCERTSTORE        hStoreHandle = NULL;

// Call CertOpenSystemStore to open the store.
hStoreHandle = CertOpenSystemStore(hCryptProv, "MY");
if (!hStoreHandle)
{
    AfxMessageBox( "Error Getting Store Handle");
    return;
}

// If the call was successful, the certificate store handle now
// resides at the location pointed to by hStoreHandle.


//-------------------------------------------------------------
// Get a pointer to the recipients certificate (Step 5).
//-------------------------------------------------------------
PCCERT_CONTEXT    pRecipientCert = NULL;

// Call GetRecipientCert. See the function code at the end of 
// this code fragment.
pRecipientCert = GetRecipientCert(hStoreHandle);
if(!pRecipientCert)
{
    AfxMessageBox( "Error Getting Recipient Cert");
    return;
}
//-------------------------------------------------------------
// Create a RecipientCertArray (Step 6).
//-------------------------------------------------------------
PCCERT_CONTEXT RecipientCertArray[1];
RecipientCertArray[0] = pRecipientCert;

//-------------------------------------------------------------
// Initialize the Algorithm Identifier structure. (Step 7).
//-------------------------------------------------------------
DWORD                        EncryptAlgSize;
CRYPT_ALGORITHM_IDENTIFIER    EncryptAlgorithm;
EncryptAlgSize = sizeof(EncryptAlgorithm);
// Initialize the structure to zero.
memset(&EncryptAlgorithm, 0, EncryptAlgSize);
// Set the necessary field.
EncryptAlgorithm.pszObjId = szOID_RSA_RC4;  

//-------------------------------------------------------------
// Initialize the CRYPT_ENCRYPT_MESSAGE_PARA structure. (Step 8).
//-------------------------------------------------------------
CRYPT_ENCRYPT_MESSAGE_PARA    EncryptParams;
DWORD    EncryptParamsSize = sizeof(EncryptParams);
memset(&EncryptParams, 0, EncryptParamsSize);

EncryptParams.cbSize =  EncryptParamsSize;
// For details on MY_ENCODING_TYPE, see the constant
// definition at the beginning of this code fragment.
EncryptParams.dwMsgEncodingType = MY_ENCODING_TYPE;
EncryptParams.hCryptProv = hCryptProv;
EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm;

//-------------------------------------------------------------
// Call CryptEncryptMessage() (Step 9).
//-------------------------------------------------------------
//BYTE*    pbEncryptedBlob;
//DWORD    cbEncryptedBlob;

fReturn = CryptEncryptMessage(
          &EncryptParams,
          1,
          RecipientCertArray,
          pbContent,
          cbContent,
          NULL,
          &cbEncryptedBlob);
if(TRUE != fReturn)
{
    AfxMessageBox( "Getting EncrypBlob Size Failed");
    return;
}

// Allocate memory for the returned blob.
pbEncryptedBlob = (BYTE*)malloc(cbEncryptedBlob);
if(!pbEncryptedBlob)
    AfxMessageBox("Memory Allocation Error While Encrypting");

// Call CryptEncryptMessage again to encrypt the content.
fReturn = CryptEncryptMessage(
          &EncryptParams,
          1,
          RecipientCertArray,
          pbContent,
          cbContent,
          pbEncryptedBlob,
          &cbEncryptedBlob);

if(TRUE == fReturn)
    AfxMessageBox( "Encryption Succeeded");
else
    AfxMessageBox( "Encryption Failed");

// If the function call succeeded, the encrypted blob now resides
// at the location pointed to by pbEncryptedBlob.

//-------------------------------------------------------------
// Clean up memory.
//-------------------------------------------------------------
CertFreeCertificateContext(pRecipientCert);
fReturn = CertCloseStore(
          hStoreHandle, 
          CERT_CLOSE_STORE_CHECK_FLAG);
if(FALSE == fReturn)
    AfxMessageBox("Store Closed After Encryption - \n"
                  "Not All Certs or CRLs Were Freed");


//************************************************************
// GetRecipientCert() - A function to enumerate all the certificates 
// in the store and get a handle to one of them.
//************************************************************
PCCERT_CONTEXT GetRecipientCert(HCERTSTORE hCertStore)
{
    PCCERT_CONTEXT       pPrevCertContext = NULL;
    PCCERT_CONTEXT       pCertContext = NULL;
    BOOL                 fReturnFlag = FALSE;
    BOOL                 fTestFlag;
    DWORD                dwSize = NULL;
    CRYPT_KEY_PROV_INFO* pKeyInfo = NULL;


    while(TRUE)
    {
        pCertContext = CertEnumCertificatesInStore(
                       hCertStore,
                       pPrevCertContext);
        if(!pCertContext)
        {
            fTestFlag = FALSE;
            break;
        }
        else
        {
            // For clarity, this code searches for the first
            // occurrence of a signature key. This works here, 
            // as there is only one certificate in the store. Normally 
            // you would search for a name as well as the key type.

            // Call CertGetCertificateContextProperty to get the
            // returned structure size.
            fReturnFlag = CertGetCertificateContextProperty(
                          pCertContext,
                          CERT_KEY_PROV_INFO_PROP_ID,
                          NULL,
                          &dwSize);
            if(FALSE == fReturnFlag)
                AfxMessageBox("Error Getting Key Property");

            // Allocate memory for the returned structure.
            If(pKeyInfo)
                free(pKeyInfo);
            pKeyInfo = (CRYPT_KEY_PROV_INFO*)malloc(dwSize);
            if(!pKeyInfo)
                AfxMessageBox("Error Allocating Memory");

            // Get the key information structure.
            fReturnFlag = CertGetCertificateContextProperty(
                          pCertContext,
                          CERT_KEY_PROV_INFO_PROP_ID,
                          pKeyInfo,
                          &dwSize);

            // Does it contain an exchange key?
            if(pKeyInfo->dwKeySpec == AT_KEYEXCHANGE)
            {
                AfxMessageBox("KeyExchange Cert Found");
                fTestFlag = TRUE;
                break;
            }

        }
        pPrevCertContext = pCertContext;    
    }
    CertFreeCertificateContext(pPrevCertContext);
    if(pKeyInfo)
    free(pKeyInfo);

    if(FALSE == fTestFlag)
    {
        AfxMessageBox("KeyExchange Cert Not Found");
        return NULL;
    }else
        return (pCertContext);
}