例 C プログラム: 署名済みおよび暗号化されたメッセージの受信
次の例は、「 例 C プログラム: 署名済みおよび暗号化されたメッセージの送受信」のプログラムと組み合わせて動作します。 署名された暗号化されたメッセージを読み取り、メッセージの暗号化を解除して検証します。
メッセージの暗号化を解除して検証するには、メッセージの目的の受信者の 秘密キー を使用できる必要があります。 署名者の証明書は、ファイルから読み込まれたメッセージ BLOB に含まれています。
この例では、次のタスクを示します。
- システム証明書ストアを開いたり閉じたりします。
- ファイルからの CERT_NAME_BLOB の読み取り。
- メッセージの暗号化解除と検証に必要なデータ構造の初期化。
- CryptoAPI 関数を呼び出してバッファーの必要なサイズを検索し、必要なサイズのバッファーを割り当て、CryptoAPI 関数をもう一度呼び出してバッファーを埋めます。 詳細については、「不明な 長さのデータの取得」を参照してください。
この例では、次の CryptoAPI 関数を使用します。
この例では、 MyHandleError を使用して、エラーが発生した場合にプログラムを正常に終了します。 MyHandleError コードはサンプルに含まれており、General Purpose 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.