예제 C 프로그램: CryptEncryptMessage 및 CryptDecryptMessage 사용

CryptEncryptMessage메시지 암호화에 나열된 모든 작업을 수행하는 데 필요한 유일한 함수 호출입니다. 데이터 구조를 초기화해야 합니다. 다음 그림에서는 구조 또는 배열을 가리키는 함수 매개 변수와 초기화된 데이터 간의 관계를 보여 줍니다. 또한 이 예제에서는 CryptDecryptMessage를 사용하여 메시지의 암호를 해독합니다.

initialization map for a call to cryptencryptmessage

데이터를 암호화하려면

  1. 암호화할 콘텐츠에 대한 포인터를 가져옵니다.
  2. 암호화할 콘텐츠의 크기를 결정합니다.
  3. 암호화 공급자에 대한 핸들을 획득합니다.
  4. 인증서 저장소를 엽니다.
  5. 받는 사람 인증서를 가져옵니다.
  6. 받는 사람 인증서 배열을 만듭니다.
  7. CRYPT_ALGORITHM_IDENTIFIER 구조를 초기화합니다.
  8. CRYPT_ENCRYPT_MESSAGE_PARA 구조를 초기화합니다.
  9. CryptEncryptMessage를 호출하여 콘텐츠를 암호화하고 디지털 봉투 메시지를 만듭니다.

다음 예제에서는 이 절차를 구현합니다.

주석은 코드 조각을 프로시저의 각 단계와 관련합니다. 함수에 대한 자세한 내용은 CryptEncryptMessage를 참조하세요. 데이터 구조에 대한 자세한 내용은 CRYPT_ALGORITHM_IDENTIFIERCRYPT_ENCRYPT_MESSAGE_PARA 참조하세요.

이 예제에서는 MyHandleErrorByteToStr 함수를 사용합니다. 이 함수에 대한 코드는 샘플에 포함되어 있습니다. 이 함수 및 기타 보조 함수에 대한 코드도 범용 함수 아래에 나열됩니다.

//-------------------------------------------------------------------
// Copyright (C) Microsoft.  All rights reserved.
// Example of encrypting data and creating an enveloped 
// message using CryptEncryptMessage.
#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);
//-------------------------------------------------------------------
// This program uses the function GetRecipientCert, declared here and
// defined after main.

PCCERT_CONTEXT GetRecipientCert(
     HCERTSTORE hCertStore);

//-------------------------------------------------------------------
// This program uses the function ByteToStr, declared here and
// defined after main. Code for ByteToStr can also be found as one
// of the general purpose functions.

void ByteToStr(
     DWORD cb, 
     void* pv, 
     LPSTR sz);

//-------------------------------------------------------------------
// This program uses the function DecryptMessage, declared here and
// defined after main.

BOOL DecryptMessage( 
       BYTE *pbEncryptedBlob, 
       DWORD cbEncryptedBlob,
       HCRYPTPROV hCryptProv,
       HCERTSTORE hStoreHandle);

void main()
{
//-------------------------------------------------------------------
// Declare and initialize variables. This includes getting a pointer 
// to the message to be encrypted. This code creates a message
// and gets a pointer to it. In reality, the message content 
// usually exists somewhere and a pointer to the message is 
// passed to the application. 

BYTE* pbContent = (BYTE*) "Security is our business.";
                                            // The message
DWORD cbContent = strlen((char *)pbContent)+1;
                                            // Size of message
HCRYPTPROV hCryptProv;                      // CSP handle
HCERTSTORE hStoreHandle;
PCCERT_CONTEXT pRecipientCert;
PCCERT_CONTEXT RecipientCertArray[1];
DWORD EncryptAlgSize;
CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm;
CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams;
DWORD EncryptParamsSize;
BYTE*    pbEncryptedBlob;
DWORD    cbEncryptedBlob;

//-------------------------------------------------------------------
//  Begin processing.

printf("About to begin with the message %s.\n",pbContent);
printf("The message length is %d bytes. \n", cbContent);

//-------------------------------------------------------------------
// Get a handle to a cryptographic provider.

if(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 both encrypt and sign.
            NULL))              // No flags needed.
{
    printf("A CSP has been acquired. \n");
}
else
{
    MyHandleError("Cryptographic context could not be acquired.");
}
//-------------------------------------------------------------------
// Open a system certificate store.

if(hStoreHandle = CertOpenSystemStore(
     hCryptProv, 
     "MY"))
{
    printf("The MY store is open. \n");
}
else
{
    MyHandleError( "Error getting store handle.");
}
//-------------------------------------------------------------------
// Get a pointer to the recipient's certificate.
// by calling GetRecipientCert. 

if(pRecipientCert = GetRecipientCert(
     hStoreHandle))
{
    printf("A recipient's certificate has been acquired. \n");
}
else
{
    printf("No certificate with a CERT_KEY_CONTEXT_PROP_ID \n");
    printf("property and an AT_KEYEXCHANGE private key "
        "available. \n");
    printf("While the message could be encrypted, in this case, \n");
    printf("it could not be decrypted in this program. \n");
    printf("For more information, see the documentation for \n");
    printf("CryptEncryptMessage and CryptDecryptMessage.\n\n");
    MyHandleError( "No Certificate with AT_KEYEXCHANGE "
        "key in store.");
}
//-------------------------------------------------------------------
// Create a RecipientCertArray.

RecipientCertArray[0] = pRecipientCert;

//-------------------------------------------------------------------
// Initialize the algorithm identifier structure.

EncryptAlgSize = sizeof(EncryptAlgorithm);

//-------------------------------------------------------------------
// Initialize the structure to zero.

memset(&EncryptAlgorithm, 0, EncryptAlgSize);

//-------------------------------------------------------------------
// Set the necessary member.

EncryptAlgorithm.pszObjId = szOID_RSA_RC4;  

//-------------------------------------------------------------------
// Initialize the CRYPT_ENCRYPT_MESSAGE_PARA structure. 

EncryptParamsSize = sizeof(EncryptParams);
memset(&EncryptParams, 0, EncryptParamsSize);
EncryptParams.cbSize =  EncryptParamsSize;
EncryptParams.dwMsgEncodingType = MY_ENCODING_TYPE;
EncryptParams.hCryptProv = hCryptProv;
EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm;

//-------------------------------------------------------------------
// Call CryptEncryptMessage.

if(CryptEncryptMessage(
          &EncryptParams,
          1,
          RecipientCertArray,
          pbContent,
          cbContent,
          NULL,
          &cbEncryptedBlob))
{
    printf("The encrypted message is %d bytes. \n",cbEncryptedBlob);
}
else
{
    MyHandleError( "Getting EncryptedBlob size failed.");
}
//-------------------------------------------------------------------
// Allocate memory for the returned BLOB.

if(pbEncryptedBlob = (BYTE*)malloc(cbEncryptedBlob))
{
    printf("Memory has been allocated for the encrypted BLOB. \n");
}
else
{
    MyHandleError("Memory allocation error while encrypting.");
}
//-------------------------------------------------------------------
// Call CryptEncryptMessage again to encrypt the content.

if(CryptEncryptMessage(
          &EncryptParams,
          1,
          RecipientCertArray,
          pbContent,
          cbContent,
          pbEncryptedBlob,
          &cbEncryptedBlob))
{
    printf( "Encryption succeeded. \n");
}
else
{
    MyHandleError("Encryption failed.");
}

//-------------------------------------------------------------------
// Call the function DecryptMessage, whose code follows main,
// to decrypt the message.

if(DecryptMessage( 
     pbEncryptedBlob, 
     cbEncryptedBlob,
     hCryptProv,
     hStoreHandle))
{
   printf("Decryption succeeded. \n");
}
else
{
   printf("Decryption failed. \n");
}
//-------------------------------------------------------------------
// Clean up memory.

CertFreeCertificateContext(pRecipientCert);
if(CertCloseStore(
          hStoreHandle, 
          CERT_CLOSE_STORE_CHECK_FLAG))
{
    printf("The MY store was closed without incident. \n");
}
else
{
   printf("Store closed after encryption -- \n"
      "but not all certificates or CRLs were freed. \n");
}
if(hCryptProv)
{
    CryptReleaseContext(hCryptProv,0);
    printf("The CSP has been released. \n");
}
else
{
    printf("CSP was NULL. \n");
}
} // End of main

//-------------------------------------------------------------------
//  Define the function DecryptMessage.

BOOL DecryptMessage( 
     BYTE *pbEncryptedBlob, 
     DWORD cbEncryptedBlob,
     HCRYPTPROV hCryptProv,
     HCERTSTORE hStoreHandle)

//-------------------------------------------------------------------
// Example function for decrypting an encrypted message using
// CryptDecryptMessage. Its parameters are pbEncryptedBlob,
// an encrypted message; cbEncryptedBlob, the length of that
// message; hCryptProv, a CSP; and hStoreHandle, the handle
// of an open certificate store.

{
//-------------------------------------------------------------------
// Declare and initialize local variables.

DWORD cbDecryptedMessage;
char* EncryptedString = new char[(cbEncryptedBlob * 2) +1];
HCERTSTORE CertStoreArray[] = {hStoreHandle};
CRYPT_DECRYPT_MESSAGE_PARA  DecryptParams;
DWORD  DecryptParamsSize = sizeof(DecryptParams);
BYTE*  pbDecryptedMessage;
LPSTR  DecryptedString;
BOOL   fReturn = TRUE;

//-------------------------------------------------------------------
// Get a pointer to the encrypted message, pbEncryptedBlob,
// and its length, cbEncryptedBlob. In this example, these are
// passed as parameters along with a CSP and an open store handle.

//-------------------------------------------------------------------
// View the encrypted BLOB.
// Call a function, ByteToStr, to convert the byte BLOB to ASCII
// hexadecimal format. 

ByteToStr(
    cbEncryptedBlob, 
    pbEncryptedBlob, 
    EncryptedString);

//-------------------------------------------------------------------
// Print the converted string.

printf("The encrypted string is: \n%s\n",EncryptedString);

//-------------------------------------------------------------------
//   In this example, the handle to the MY store was passed in as a 
//   parameter. 

//-------------------------------------------------------------------
//   Create a "CertStoreArray."
//   In this example, this step was done in the declaration
//   and initialization of local variables because the store handle 
//   was passed into the function as a parameter.

//-------------------------------------------------------------------
//   Initialize the CRYPT_DECRYPT_MESSAGE_PARA structure.

memset(&DecryptParams, 0, DecryptParamsSize);
DecryptParams.cbSize = DecryptParamsSize;
DecryptParams.dwMsgAndCertEncodingType = MY_ENCODING_TYPE;
DecryptParams.cCertStore = 1;
DecryptParams.rghCertStore = CertStoreArray;

//-------------------------------------------------------------------
//  Decrypt the message data.
//  Call CryptDecryptMessage to get the returned data size.

if(CryptDecryptMessage(
          &DecryptParams,
          pbEncryptedBlob,
          cbEncryptedBlob,
          NULL,
          &cbDecryptedMessage,
          NULL))
{
    printf("The size for the decrypted message is: %d.\n",
        cbDecryptedMessage);
}
else
{
    MyHandleError( "Error getting decrypted message size");
}
//-------------------------------------------------------------------
// Allocate memory for the returned decrypted data.

if(pbDecryptedMessage = (BYTE*)malloc(
       cbDecryptedMessage))
{
    printf("Memory has been allocated for the decrypted message. "
        "\n");
}
else
{
    MyHandleError("Memory allocation error while decrypting");
}
//-------------------------------------------------------------------
// Call CryptDecryptMessage to decrypt the data.

if(CryptDecryptMessage(
          &DecryptParams,
          pbEncryptedBlob,
          cbEncryptedBlob,
          pbDecryptedMessage,
          &cbDecryptedMessage,
          NULL))
{
    DecryptedString = (LPSTR) pbDecryptedMessage;
    printf("Message Decrypted Successfully. \n");
    printf("The decrypted string is: %s\n",DecryptedString);
}
else
{
    printf("Error decrypting the message \n");
    printf("Error code %x \n",GetLastError());
    fReturn = FALSE;
}

//-------------------------------------------------------------------
// Clean up memory.

free(pbEncryptedBlob);
free(pbDecryptedMessage);
return fReturn;
}  // End of DecryptMessage

//-------------------------------------------------------------------
// Define the function ByteToStr.

void ByteToStr(
     DWORD cb, 
     void* pv, 
     LPSTR sz)
//-------------------------------------------------------------------
// Parameters passed are:
//    pv is the array of BYTEs to be converted.
//    cb is the number of BYTEs in the array.
//    sz is a pointer to the string to be returned.

{
//-------------------------------------------------------------------
//  Declare and initialize local variables.

BYTE* pb = (BYTE*) pv; // Local pointer to a BYTE in the BYTE array
DWORD i;               // Local loop counter
int b;                 // Local variable

//-------------------------------------------------------------------
//  Begin processing loop.

for (i = 0; i<cb; i++)
{
   b = (*pb & 0xF0) >> 4;
   *sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A';
   b = *pb & 0x0F;
   *sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A';
   pb++;
}
*sz++ = 0;
} // End of ByteToStr

//-------------------------------------------------------------------
//  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

//-------------------------------------------------------------------
// GetRecipientCert enumerates the certificates in a store and finds
// the first certificate that has an AT_EXCHANGE key. If a  
// certificate is found, a pointer to that certificate is returned.  

PCCERT_CONTEXT GetRecipientCert( 
    HCERTSTORE hCertStore) 
//------------------------------------------------------------------- 
// Parameter passed in: 
// hCertStore, the handle of the store to be searched. 
{ 
//------------------------------------------------------------------- 
// Declare and initialize local variables. 

PCCERT_CONTEXT pCertContext = NULL; 
BOOL fMore = TRUE; 
DWORD dwSize = NULL; 
CRYPT_KEY_PROV_INFO* pKeyInfo = NULL; 
DWORD PropId = CERT_KEY_PROV_INFO_PROP_ID; 

//--------------------------------------------------------------------
// Find certificates in the store until the end of the store 
// is reached or a certificate with an AT_KEYEXCHANGE key is found. 

while(fMore && (pCertContext= CertFindCertificateInStore( 
   hCertStore, // Handle of the store to be searched. 
   0,          // Encoding type. Not used for this search. 
   0,          // dwFindFlags. Special find criteria. 
               // Not used in this search. 
   CERT_FIND_PROPERTY, 
               // Find type. Determines the kind of search 
               // to be done. In this case, search for 
               // certificates that have a specific 
               // extended property. 
   &PropId,    // pvFindPara. Gives the specific 
               // value searched for, here the identifier 
               // of an extended property. 
   pCertContext))) 
               // pCertContext is NULL for the  
               // first call to the function. 
               // If the function were being called 
               // in a loop, after the first call 
               // pCertContext would be the pointer 
               // returned by the previous call. 
{ 
//------------------------------------------------------------------- 
// For simplicity, this code only searches 
// for the first occurrence of an AT_KEYEXCHANGE key. 
// In many situations, a search would also look for a 
// specific subject name as well as the key type. 

//-------------------------------------------------------------------
// Call CertGetCertificateContextProperty once to get the 
// returned structure size. 

if(!(CertGetCertificateContextProperty( 
     pCertContext, 
     CERT_KEY_PROV_INFO_PROP_ID, 
     NULL, &dwSize))) 
{ 
     MyHandleError("Error getting key property."); 
} 

//------------------------------------------------------------------- 
// Allocate memory for the returned structure. 

if(pKeyInfo) 
    free(pKeyInfo); 
if(!(pKeyInfo = (CRYPT_KEY_PROV_INFO*)malloc(dwSize))) 
{ 
     MyHandleError("Error allocating memory for pKeyInfo."); 
} 

//------------------------------------------------------------------- 
// Get the key information structure. 

if(!(CertGetCertificateContextProperty( 
   pCertContext, 
   CERT_KEY_PROV_INFO_PROP_ID, 
   pKeyInfo, 
   &dwSize))) 
{ 
    MyHandleError("The second call to the function failed."); 
} 

//------------------------------------------------------------------- 
// Check the dwKeySpec member for an exchange key. 

if(pKeyInfo->dwKeySpec == AT_KEYEXCHANGE) 
{ 
    fMore = FALSE; } 
}    // End of while loop 

if(pKeyInfo) 
      free(pKeyInfo); 
return (pCertContext); 
} // End of GetRecipientCert