範例 C 程式:接收已簽署和加密的訊息
下列範例會與範例 C 程式中的程式搭配運作 :傳送和接收已簽署和加密的訊息。 它會讀取已簽署和加密的訊息,然後解密並驗證訊息。
若要解密並驗證訊息,訊息預定接收者的 私密金鑰 必須可供使用。 簽署者的憑證會包含在從檔案讀取的 BLOB 訊息中。
此範例說明下列工作:
- 開啟和關閉系統憑證存放區。
- 從檔案讀取 CERT_NAME_BLOB 。
- 初始化解密和驗證訊息所需的資料結構。
- 呼叫 CryptoAPI 函式以尋找所需的緩衝區大小、配置所需大小的緩衝區,然後再次呼叫 CryptoAPI 函式以填滿緩衝區。 如需詳細資訊,請參閱 擷取未知長度的資料。
此範例使用下列 CryptoAPI 函式:
此範例會使用 MyHandleError 在發生任何失敗時正常結束程式。 MyHandleError程式碼隨附于範例中,也可以在常規用途 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.