Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In het volgende voorbeeld ziet u hoe u de CryptMsgOpenToEncode, CryptMsgOpenToDecodeen CryptMsgUpdate--functies gebruikt met de CMSG_STREAM_INFO structuur om een bericht te coderen en decoderen met behulp van de streamingfuncties van deze functies.
Het ondertekenen en coderen van een bericht garandeert geen privacy voor dat bericht. In plaats daarvan zorgt het voor de echtheid van het bericht. Omdat het bericht is ondertekend met de persoonlijke sleutel van de afzender en de ontvanger van het bericht de handtekening ontsleutelt met de openbare sleutel van de afzender (beschikbaar via het certificaat dat samen met het bericht wordt verzonden), kan de ontvanger ervoor zorgen dat het bericht is verzonden door de persoon of entiteit die is gekoppeld aan het certificaat en dat het bericht niet is gewijzigd nadat het is ondertekend.
Dit coderingsgedeelte van dit voorbeeld illustreert de volgende taken en CryptoAPI-functies:
- Een certificaatarchief openen met behulp van CertOpenStore-.
- Een certificaat ophalen met een specifieke onderwerpnaam met behulp van CertFindCertificateInStore.
- De onderwerpnaam van een certificaat ophalen en afdrukken met behulp van CertGetNameString-.
- De ingang ophalen bij een cryptografische provider die een persoonlijke sleutel kan bieden met de CryptAcquireCertificatePrivateKey functie.
- Initialiseren van de CMSG_SIGNED_ENCODE_INFO- en CMSG_STREAM_INFO structuren die moeten worden gebruikt in een aanroep van CryptMsgOpenToEncode.
- Een bericht ondertekenen en coderen met behulp van CryptMsgOpenToEncode- en CryptMsgUpdate.
- Het implementeren van een stream callback-functie waarmee een gecodeerd en ondertekend bericht in een permanente indeling kan worden opgeslagen, zoals het schrijven naar een bestand.
Het decoderingsgedeelte van dit voorbeeld illustreert de volgende taken en CryptoAPI-functies:
- Initialiseren van een CMSG_STREAM_INFO structuur die moet worden gebruikt in een aanroep van CryptMsgOpenToDecode.
- Het implementeren van een stream callback-functie waarmee een gedecodeerd bericht in een permanente indeling kan worden opgeslagen, zoals het afdrukken naar het scherm.
- Het lezen van een gecodeerd bericht uit een bestand en het decoderen van het bericht met behulp van CryptMsgUpdate-.
Zie Voorbeeld van C-programma: ondertekening, codering, decoderen en verifiëren van een berichtvoor een voorbeeld van hoe u dezelfde bewerkingen kunt uitvoeren zonder een stream-callback te gebruiken.
In dit voorbeeld wordt de functie MyHandleErrorgebruikt. Code voor deze functie is opgenomen in het voorbeeld. Code voor deze en andere hulpfuncties wordt ook vermeld onder General_Purpose_Functions.
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")
// Link with the Crypt32.lib file.
#pragma comment (lib, "Crypt32")
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define MAX_NAME 256
#define ENCODED_FILE_NAME L"testStream.p7s"
//-------------------------------------------------------------------
// Define function MyHandleError.
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.
//+----------------------------------------------
// Callback function used for streamed Signing.
//-----------------------------------------------
BOOL
WINAPI
EncodeCallback(
const void *pvArg,
BYTE *pbData,
DWORD cbData,
BOOL fFinal)
{
DWORD dwWrittenBytes = 0;
HANDLE hFileToWrite = INVALID_HANDLE_VALUE;
hFileToWrite = *((HANDLE *)pvArg);
if ( !WriteFile(
hFileToWrite,
pbData,
cbData,
&dwWrittenBytes,
NULL) ||
(dwWrittenBytes != cbData))
{
return FALSE;
}
return TRUE;
}
//+----------------------------------------------
// Callback function used for decoding streamed Signing.
//-----------------------------------------------
BOOL
WINAPI
DecodeCallback(
const void *pvArg,
BYTE *pbData,
DWORD cbData,
BOOL fFinal)
{
if (pbData != NULL && cbData > 0)
{
*(pbData+cbData) = 0;
printf("%s", (char*)pbData);
}
return TRUE;
}
void EncodeMessageWithStream(LPWSTR pwszSignerName)
{
//---------------------------------------------------------------
// Declare and initialize variables. This includes declaring and
// initializing a pointer to message content to be countersigned
// and encoded. Usually, the message content will exist somewhere
// and a pointer to it is passed to the application.
BYTE* pbContent1 = (BYTE*)"First sentence. ";
DWORD cbContent1 = lstrlenA((char *)pbContent1);
BYTE* pbContent2 = (BYTE*)"Second sentence. ";
DWORD cbContent2 = lstrlenA((char *)pbContent2);
HCRYPTPROV hCryptProv; // CSP handle
HCERTSTORE hStoreHandle; // store handle
PCCERT_CONTEXT pSignerCert; // signer certificate
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[1];
CERT_BLOB SignerCertBlob;
CERT_BLOB SignerCertBlobArray[1];
CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
HCRYPTMSG hMsg;
LPWSTR pszNameString;
DWORD dwKeySpec;
//---------------------------------------------------------------
// Open the My system certificate store.
if(!(hStoreHandle = CertOpenStore(
// The system store will be a virtual store.
CERT_STORE_PROV_SYSTEM,
// Encoding type not needed with this PROV.
0,
// Accept the default HCRYPTPROV.
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
// Set the system store location in the registry. Other
// predefined system stores could have been used, including
// trust, Ca, or root.
L"MY")))
{
MyHandleError(L"Could not open the MY system store.");
}
//---------------------------------------------------------------
// Get a pointer to a signer's signature certificate.
if(pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_ENCODING_TYPE,
0,
CERT_FIND_SUBJECT_STR,
pwszSignerName,
NULL))
{
//-----------------------------------------------------------
// A certificate was found. Get and print the name of the
// subject of the certificate.
if(CertGetNameString(
pSignerCert,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszNameString,
MAX_NAME) > 1)
{
printf("The message signer is %s \n",pszNameString);
}
else
{
MyHandleError(L"CertGetNameString failed.\n");
}
}
else
{
MyHandleError(L"Cert not found.\n");
}
//---------------------------------------------------------------
// Initialize the CMSG_SIGNER_ENCODE_INFO structure.
//---------------------------------------------------------------
// Get a handle to a cryptographic provider.
if(!(CryptAcquireCertificatePrivateKey(
pSignerCert,
0,
NULL,
&hCryptProv,
&dwKeySpec,
NULL)))
{
DWORD dwError = GetLastError();
if(NTE_BAD_PUBLIC_KEY == dwError)
{
printf("NTE_BAD_PUBLIC_KEY\n");
}
MyHandleError(L"CryptAcquireContext failed");
}
memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
SignerEncodeInfo.pCertInfo = pSignerCert->pCertInfo;
SignerEncodeInfo.hCryptProv = hCryptProv;
SignerEncodeInfo.dwKeySpec = dwKeySpec;
SignerEncodeInfo.HashAlgorithm.pszObjId = szOID_RSA_MD5;
SignerEncodeInfo.pvHashAuxInfo = NULL;
//---------------------------------------------------------------
// Initialize the first element of an array of signers.
// Note: Currently, there is only one signer.
SignerEncodeInfoArray[0] = SignerEncodeInfo;
//---------------------------------------------------------------
// Initialize the CMSG_SIGNED_ENCODE_INFO structure.
SignerCertBlob.cbData = pSignerCert->cbCertEncoded;
SignerCertBlob.pbData = pSignerCert->pbCertEncoded;
//---------------------------------------------------------------
// Initialize the first element of an array of signer BLOBs.
// Note: In this program, there is only one signer BLOB used.
SignerCertBlobArray[0] = SignerCertBlob;
memset(&SignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
SignedMsgEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
SignedMsgEncodeInfo.cSigners = 1;
SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray;
SignedMsgEncodeInfo.cCertEncoded = 1;
SignedMsgEncodeInfo.rgCertEncoded = SignerCertBlobArray;
// Fill the CMSG_STREAM_INFO structure.
CMSG_STREAM_INFO stStreamInfo;
// BER_ENCODING
stStreamInfo.cbContent = 0xffffffff;
// DER_ENCODING
// stStreamInfo.cbContent = cbContent;
stStreamInfo.pfnStreamOutput = EncodeCallback;
HANDLE hOutMsgFile = INVALID_HANDLE_VALUE;
hOutMsgFile = CreateFile(
ENCODED_FILE_NAME,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hOutMsgFile)
{
MyHandleError(L"CreateFile (OUT MSG)");
}
stStreamInfo.pvArg = &hOutMsgFile;
//---------------------------------------------------------------
// Open a message to encode.
if(!(hMsg = CryptMsgOpenToEncode(
MY_ENCODING_TYPE, // encoding type
0, // flags
CMSG_SIGNED, // message type
&SignedMsgEncodeInfo, // pointer to structure
NULL, // inner content OID
&stStreamInfo))) // stream information
{
MyHandleError(L"OpenToEncode failed");
}
//---------------------------------------------------------------
// Update the message with the data.
if(!(CryptMsgUpdate(
hMsg, // handle to the message
pbContent1, // pointer to the content
cbContent1, // size of the content
FALSE))) // first call
{
MyHandleError(L"MsgUpdate failed");
}
if(!(CryptMsgUpdate(
hMsg, // handle to the message
pbContent2, // pointer to the content
cbContent2, // size of the content
TRUE))) // last call
{
MyHandleError(L"MsgUpdate failed");
}
//---------------------------------------------------------------
// The message is signed and encoded.
// Close the message handle and the certificate store.
CryptMsgClose(hMsg);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
CryptReleaseContext(hCryptProv,0);
CloseHandle(hOutMsgFile);
}
void DecodeMessageWithStream()
{
//---------------------------------------------------------------
// Open the message for decoding.
HCRYPTMSG hMsg;
// Fill the CMSG_STREAM_INFO structure.
CMSG_STREAM_INFO stStreamInfo2;
// BER_ENCODING
stStreamInfo2.cbContent = 0xffffffff;
stStreamInfo2.pfnStreamOutput = DecodeCallback;
if(!(hMsg = CryptMsgOpenToDecode(
MY_ENCODING_TYPE, // encoding type
0, // flags
0, // message type (get from message)
NULL, // cryptographic provider
// use NULL for the default provider
NULL, // recipient information
&stStreamInfo2))) // stream information
{
MyHandleError(L"OpenToDecode failed.");
}
HANDLE hInMsgFile = INVALID_HANDLE_VALUE;
hInMsgFile = CreateFile(
ENCODED_FILE_NAME,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hInMsgFile)
{
MyHandleError(L"CreateFile (IN MSG)");
}
const DWORD cbBytesToRead = 256;
byte pbEncodedBlob[cbBytesToRead];
DWORD cbBytesRead;
BOOL lastCall = FALSE;
while (ReadFile(
hInMsgFile,
pbEncodedBlob,
cbBytesToRead,
&cbBytesRead,
NULL))
{
if (cbBytesRead < cbBytesToRead)
{
lastCall = TRUE;
}
if(!(CryptMsgUpdate(
hMsg, // handle to the message
pbEncodedBlob, // pointer to the encoded BLOB
cbBytesRead, // size of the encoded BLOB
lastCall))) // last call
{
MyHandleError(L"Decode MsgUpdate failed.");
}
if (lastCall)
{
break;
}
}
CryptMsgClose(hMsg);
CloseHandle(hInMsgFile);
}