Exemplo de programa C: recebendo uma mensagem assinada e criptografada
O exemplo a seguir funciona em conjunto com o programa no Exemplo de Programa C: Enviando e recebendo uma mensagem assinada e criptografada. Ele lê a mensagem assinada e criptografada, descriptografa e verifica a mensagem.
Para descriptografar e verificar a mensagem, a chave privada do receptor pretendido da mensagem deve estar disponível. O certificado do signatário está incluído na mensagem BLOB lida do arquivo.
Este exemplo ilustra as seguintes tarefas:
- Abrindo e fechando repositórios de certificados do sistema.
- Ler um CERT_NAME_BLOB de um arquivo.
- Inicializando estruturas de dados necessárias para descriptografar e verificar uma mensagem.
- Chamar uma função CryptoAPI para localizar o tamanho necessário de um buffer, alocar o buffer do tamanho necessário e chamar a função CryptoAPI novamente para preencher o buffer. Para obter mais informações, consulte Recuperando dados de comprimento desconhecido.
Este exemplo usa as seguintes funções CryptoAPI:
Este exemplo usa MyHandleError para sair normalmente do programa em caso de falha. O código MyHandleError está incluído no exemplo e também pode ser encontrado junto com outras funções auxiliares em Uso Geral Functions.
//-------------------------------------------------------------------
// Example C Program:
// Reads a signed and encrypted message, then decrypts and verifies
// the message.
#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
//-------------------------------------------------------------------
// 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(LPTSTR psz)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
} // End of MyHandleError
BYTE* DecryptAndVerify(DWORD cbBlob, BYTE *pbBlob)
{
//---------------------------------------------------------------
// Declare and initialize local variables.
HCERTSTORE hCertStore;
CRYPT_DECRYPT_MESSAGE_PARA DecryptPara;
CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
DWORD dwSignerIndex = 0;
BYTE *pbDecrypted;
DWORD cbDecrypted;
//---------------------------------------------------------------
// Open the certificate store.
if ( !(hCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"my")))
{
MyHandleError(TEXT("The MY store could not be opened."));
}
//---------------------------------------------------------------
// Initialize the needed data structures.
DecryptPara.cbSize = sizeof(CRYPT_DECRYPT_MESSAGE_PARA);
DecryptPara.dwMsgAndCertEncodingType = MY_ENCODING_TYPE;
DecryptPara.cCertStore = 1;
DecryptPara.rghCertStore = &hCertStore;
VerifyPara.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);
VerifyPara.dwMsgAndCertEncodingType = MY_ENCODING_TYPE;
VerifyPara.hCryptProv = 0;
VerifyPara.pfnGetSignerCertificate = NULL;
VerifyPara.pvGetArg = NULL;
pbDecrypted = NULL;
cbDecrypted = 0;
//---------------------------------------------------------------
// Call CryptDecryptAndVerifyMessageSignature a first time
// to determine the needed size of the buffer to hold the
// decrypted message.
// Note: The sixth parameter is NULL in this call to
// get the required size of the bytes string to contain the
// decrypted message.
if(!(CryptDecryptAndVerifyMessageSignature(
&DecryptPara,
&VerifyPara,
dwSignerIndex,
pbBlob,
cbBlob,
NULL,
&cbDecrypted,
NULL,
NULL)))
{
MyHandleError(TEXT("Failed getting size."));
}
//---------------------------------------------------------------
// Allocate memory for the buffer to hold the decrypted
// message.
if(!(pbDecrypted = (BYTE *)malloc(cbDecrypted)))
{
MyHandleError(TEXT("Memory allocation failed."));
}
if(!(CryptDecryptAndVerifyMessageSignature(
&DecryptPara,
&VerifyPara,
dwSignerIndex,
pbBlob,
cbBlob,
pbDecrypted,
&cbDecrypted,
NULL,
NULL)))
{
pbDecrypted = NULL;
}
//---------------------------------------------------------------
// Close the certificate store.
CertCloseStore(hCertStore, 0);
//---------------------------------------------------------------
// Return the decrypted string or NULL.
return pbDecrypted;
} // End of DecryptandVerify.
BYTE* ReadBlob(DWORD *pcbBlob)
{
FILE *hInputFile;
BYTE *pbBlob;
// Open the input file and read in the signed and encrypted BLOB.
// This file would be created by a program such as the example
// program "Example C Program: Sending and Receiving a Signed and
// Encrypted Message" in the Platform Software Development Kit (SDK).
// Change the path name for this file if it is not in the same
// directory as the executable.
if( !(hInputFile= _tfopen(TEXT("sandvout.txt"), TEXT("rb"))))
{
MyHandleError(TEXT("Input file was not opened.\n"));
}
fread(
pcbBlob,
sizeof(DWORD),
1,
hInputFile);
if(ferror(hInputFile))
{
MyHandleError(TEXT("The size of the BLOB was not read.\n"));
}
if(!(pbBlob = (BYTE *) malloc(*pcbBlob)))
{
MyHandleError(TEXT("Memory allocation failed."));
}
fread(
pbBlob,
*pcbBlob,
1,
hInputFile);
if(ferror(hInputFile))
{
MyHandleError(TEXT("The bytes of the BLOB were not read.\n"));
}
fclose(hInputFile);
return pbBlob;
} // End of ReadBlob.
//-------------------------------------------------------------------
// Main calls ReadBlob to read in the signed and encrypted message.
// It then calls DecryptAndVerify which, if successful, decrypts
// and verifies the message.
// The function main prints the returned, decrypted message
// if the verification and decryption are successful.
// Note: The file with the signed and encrypted file must be
// available, and the user running this program must have access to
// the private key of the intended message receiver.
// Also note that this program does not use CryptAcquireContext.
void main()
{
BYTE *pReturnMessage;
BYTE *pbBlob;
DWORD cbBlob;
if((pbBlob = ReadBlob(&cbBlob)) == NULL)
{
MyHandleError(TEXT("Read BLOB did not return the BLOB. "));
}
if(pReturnMessage = DecryptAndVerify(cbBlob, pbBlob))
{
_tprintf(TEXT
(" The returned, verified message is ->\n%s\n"),
pReturnMessage);
_tprintf(TEXT(" The program executed without error.\n"));
}
else
{
_tprintf(TEXT("Verification failed.\n"));
}
} // End of main.