Статус: Сотрудник
Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC) Сообщений: 6,405  Откуда: КРИПТО-ПРО Сказал «Спасибо»: 37 раз Поблагодарили: 720 раз в 624 постах
|
Пример из MS SDK Код:// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
/****************************************************************
Title: Encrypting Data and creating an enveloped message
This example shows how to encrypt and decrypt a PKCS7 / CMS message.
It illustrates use of the CryptEncryptMessage and CryptDecryptMessage API.
This example creates a ECDH certificate with a private key
associated with it.
****************************************************************/
#include "stdio.h"
#include "malloc.h"
#include "process.h"
#include "windows.h"
#include "wincrypt.h"
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(char *s);
BOOL MyDecryptMessage(
BYTE *pbEncryptedBlob,
DWORD cbEncryptedBlob,
HCERTSTORE hStoreHandle);
NCRYPT_KEY_HANDLE MyCreateKey(
IN LPWSTR wszContainerName,
IN LPCWSTR pwszAlgid,
IN LPCWSTR pwszProvName);
PCCERT_CONTEXT MyCreateECDHCertAndAddToStore(
IN HCERTSTORE hStoreHandle);
void __cdecl 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*) "Enter message to be encrypted here"; // Message
DWORD cbContent = strlen((char *)pbContent)+1; // Size of message
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pRecipientCert = NULL;
PCCERT_CONTEXT RecipientCertArray[1];
DWORD cbEncryptAlgSize = 0;
CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm = {0};
CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams = {0};
DWORD cbEncryptParamsSize = 0;
BYTE* pbEncryptedBlob = NULL;
DWORD cbEncryptedBlob = 0;
CHAR szStoreName [MAX_PATH] = "CMS_ENCRYPT_SAMPLE_STORE";
//-------------------------------------------------------------------
// Begin processing.
printf_s("The message to be encrypted is: %s.\n",pbContent);
//-------------------------------------------------------------------
// Create a temporary store in the memory
// Temporary store is required to store the certificate as we need to pass
// the store handle as a parameter to the CryptDecryptMessage API for
// decrypting the message
if(hStoreHandle = CertOpenStore(
CERT_STORE_PROV_MEMORY,
0,
NULL,
NULL,
szStoreName) )
{
printf_s("The store is open. \n");
}
else
{
MyHandleError( "Error getting store handle.");
goto done;
}
if ( pRecipientCert = MyCreateECDHCertAndAddToStore(hStoreHandle) )
{
printf_s("ECDH certificate is created! \n");
}
else
{
MyHandleError("Error Creating certificate." );
goto done;
}
//-------------------------------------------------------------------
// Create a RecipientCertArray.
RecipientCertArray[0] = pRecipientCert;
//-------------------------------------------------------------------
// Initialize the algorithm identifier structure.
cbEncryptAlgSize = sizeof(EncryptAlgorithm);
//-------------------------------------------------------------------
// Initialize the structure to zero.
memset(&EncryptAlgorithm, 0, cbEncryptAlgSize);
//-------------------------------------------------------------------
// Set the necessary member.
EncryptAlgorithm.pszObjId = szOID_NIST_AES128_CBC ;
//-------------------------------------------------------------------
// Initialize the CRYPT_ENCRYPT_MESSAGE_PARA structure.
cbEncryptParamsSize = sizeof(EncryptParams);
memset(&EncryptParams, 0, cbEncryptParamsSize);
EncryptParams.cbSize = cbEncryptParamsSize;
EncryptParams.dwMsgEncodingType = MY_ENCODING_TYPE;
EncryptParams.hCryptProv = NULL;
EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm;
//-------------------------------------------------------------------
// Call CryptEncryptMessage.
if(CryptEncryptMessage(
&EncryptParams, // Pointer to encryption parameters
1, // Number of elements in the CertArray
RecipientCertArray, // Array of pointers to recipient certificates
pbContent, // Pointer to message to be encrypted
cbContent, // Size of message to be encrypted
NULL, // Pointer to encrypted content
&cbEncryptedBlob)) // Size of encrypted content
{
printf_s("The encrypted message is %d bytes. \n",cbEncryptedBlob);
}
else
{
MyHandleError( "Getting EncryptedBlob size failed.");
goto done;
}
//-------------------------------------------------------------------
// Allocate memory for the returned BLOB.
if(pbEncryptedBlob = (BYTE*)malloc(cbEncryptedBlob))
{
printf_s("Memory has been allocated for the encrypted blob. \n");
}
else
{
MyHandleError("Memory allocation error while encrypting.");
goto done;
}
//-------------------------------------------------------------------
// Call CryptEncryptMessage again to encrypt the content.
if(CryptEncryptMessage(
&EncryptParams, // Pointer to encryption parameters
1, // Number of elements in the CertArray
RecipientCertArray, // Array of pointers to recipient certificates
pbContent, // Pointer to message to be encrypted
cbContent, // Size of message to be encrypted
pbEncryptedBlob, // Pointer to encrypted content
&cbEncryptedBlob)) // Size of encrypted content
{
printf_s( "Encryption succeeded. \n");
}
else
{
MyHandleError("Encryption failed.");
goto done;
}
//-------------------------------------------------------------------
// Call the function MyDecryptMessage, whose code follows main,
// to decrypt the message.
if(MyDecryptMessage(
pbEncryptedBlob,
cbEncryptedBlob,
hStoreHandle))
{
printf_s("Decryption succeeded. \n");
}
else
{
MyHandleError("Decryption failed. \n");
goto done;
}
//-------------------------------------------------------------------
// Clean up memory.
done:
if(pbEncryptedBlob)
free(pbEncryptedBlob);
if(pRecipientCert)
CertFreeCertificateContext(pRecipientCert);
if(hStoreHandle){
if(CertCloseStore(
hStoreHandle,
CERT_CLOSE_STORE_CHECK_FLAG))
{
printf_s("The store was closed successfully.\n");
}
else
{
printf_s("Store closed after encryption -- \n"
"but not all certificates or CRLs were freed. \n");
}
}
} // End of main
//-------------------------------------------------------------------
// Define the function MyDecryptMessage.
BOOL MyDecryptMessage(
BYTE *pbEncryptedBlob,
DWORD cbEncryptedBlob,
HCERTSTORE hStoreHandle)
//-------------------------------------------------------------------
// Example function for decrypting an encrypted message using
// CryptDecryptMessage. Its parameters are pbEncryptedBlob,
// an encrypted message; cbEncryptedBlob, the length of that
// message; and hStoreHandle, the handle of an open certificate store.
{
//-------------------------------------------------------------------
// Declare and initialize local variables.
DWORD cbDecryptedMessage = 0;
HCERTSTORE CertStoreArray[] = {hStoreHandle};
CRYPT_DECRYPT_MESSAGE_PARA DecryptParams = {0};
DWORD DecryptParamsSize = sizeof(DecryptParams);
BYTE* pbDecryptedMessage = NULL;
LPSTR DecryptedString = NULL;
BOOL fReturn = TRUE;
//-------------------------------------------------------------------
// Get a pointer to the encrypted message, pbEncryptedBlob,
// and its length, cbEncryptedBlob. In this sample program, these are
// passed as parameters along with a CSP and an open store handle.
//-------------------------------------------------------------------
// In this example, the handle to the store was passed in as a
// parameter.
//-------------------------------------------------------------------
// Create a "CertStoreArray."
// In this sample program, 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, // Pointer to decryption parameters
pbEncryptedBlob, // Pointer to encrypted content
cbEncryptedBlob, // Size of encrypted content
NULL, // Pointer to decrypted message
&cbDecryptedMessage, // Size of decrypted message
NULL)) // Pointer to certificate that corresponds
// to private exchange key for decryption
{
printf_s("The size for the decrypted message is: %d.\n",
cbDecryptedMessage);
}
else
{
printf_s( "Error getting decrypted message size");
goto ErrorReturn;
}
//-------------------------------------------------------------------
// Allocate memory for the returned decrypted data.
if(pbDecryptedMessage = (BYTE*)malloc(
cbDecryptedMessage))
{
printf_s("Memory has been allocated for the decrypted message. "
"\n");
}
else
{
printf_s("Memory allocation error while decrypting");
goto ErrorReturn;
}
//-------------------------------------------------------------------
// Call CryptDecryptMessage to decrypt the data.
if(CryptDecryptMessage(
&DecryptParams, // Pointer to decryption parameters
pbEncryptedBlob, // Pointer to encrypted content
cbEncryptedBlob, // Size of encrypted content
pbDecryptedMessage, // Pointer to decrypted message
&cbDecryptedMessage, // Size of decrypted message
NULL)) // Pointer to certificate that corresponds
// to private exchange key for decryption
{
DecryptedString = (LPSTR) pbDecryptedMessage;
printf_s("The decrypted string is: %s\n",DecryptedString);
}
else
{
printf_s("Error decrypting the message \n");
goto ErrorReturn;
}
CommonReturn:
if (pbDecryptedMessage)
free (pbDecryptedMessage);
return fReturn;
ErrorReturn:
fReturn = FALSE;
goto CommonReturn;
} // End of MyDecryptMessage
//-------------------------------------------------------------------
// This example uses the function MyHandleError, a simple error
// reporting function, to print an error message corresponding
// to the error that occured.
// For most applications, replace this function with one
// that does more extensive error reporting.
void MyHandleError(char *s)
{
DWORD dwErr = GetLastError();
LPVOID lpMsgBuf;
printf_s("An error occurred in running the program. \n");
printf_s("%s\n",s);
printf_s("Error number %x : ", dwErr);
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, // Location of message
// definition ignored
dwErr, // Message identifier for
// the requested message
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Language identifier for
// the requested message
(LPTSTR) &lpMsgBuf, // Buffer that receives
// the formatted message
0, // Size of output buffer
// not needed as allocate
// buffer flag is set
NULL ); // Array of insert values
printf_s( "%S\n",lpMsgBuf);
printf_s( "Program terminating. \n");
LocalFree(lpMsgBuf);
} // end MyHandleError
//+--------------------------------------------
// Create an ECDH certificate context and add it to
// the memory store to be used in message creation.
// The structure of a X.509 v3 digital certificate is as follows:
// Version
// Serial Number
// Algorithm ID
// Issuer Name
// Validity
// Not Before
// Not After
// Subject Name
// Subject Public Key Info
// Public Key Algorithm
// Subject Public Key
// Issuer Unique Identifier (Optional)
// Subject Unique Identifier (Optional)
// Extensions (Optional)
// Certificate Signature Algorithm
// Certificate Signature
//---------------------------------------------
PCCERT_CONTEXT
MyCreateECDHCertAndAddToStore(
IN HCERTSTORE hStoreHandle
)
{
LPWSTR wszContainerName= L"CMS_ENCRYPT_SAMPLE_ECDH256";
LPCSTR szSubject= "CN=CMS_ENCRYPT_SAMPLE_CERT";
LPCWSTR pwszCNGAlg = NULL;
NCRYPT_KEY_HANDLE hCNGKey = NULL;
// Certificate
PCCERT_CONTEXT pCertContext = NULL;
// Private key info
CRYPT_KEY_PROV_INFO KeyProvInfo = {0};
// Subject Name
// For a self-signed certificate, subject and issuer are the same
CERT_NAME_BLOB SubjectName = { 0 };
CRYPT_ALGORITHM_IDENTIFIER signatureAlgorithm = { 0 };
if (!CertStrToName(
CRYPT_ASN_ENCODING, // Use X509_ASN_ENCODING
szSubject, // String to be encoded
0, // Type of the string
NULL, // Reserved for future use
NULL, // Pointer to a buffer that receives the
// encoded structure; NULL to obtain the
// required size of the buffer
// for memory allocation purposes
&SubjectName.cbData, // Size, in bytes, required for the buffer
NULL) ) // Additional error information about
// an invalid input string
{
printf_s("CertStrToName failed");
goto ErrorReturn;
}
SubjectName.pbData = (PBYTE)LocalAlloc(LPTR, SubjectName.cbData);
if (NULL == SubjectName.pbData) {
printf_s("SubjectName out of memory");
goto ErrorReturn;
}
if (!CertStrToName(
CRYPT_ASN_ENCODING, // Use X509_ASN_ENCODING
szSubject, // String to be encoded
0, // Type of the string
NULL, // Reserved for future use
SubjectName.pbData, // Pointer to a buffer that receives the
// encoded structure
&SubjectName.cbData, // Size, in bytes, required for the buffer
NULL) ) // Additional error information about
// an invalid input string
{
printf_s( "CertStrToName failed");
goto ErrorReturn;
}
pwszCNGAlg =L"ECDH_P256";
// Get a CERT_PUBLIC_KEY_INFO
hCNGKey = MyCreateKey(
wszContainerName,
pwszCNGAlg,
NULL);
if (hCNGKey == NULL)
{
printf_s ("MyCreateKey failed.\n");
goto ErrorReturn;
}
memset( &signatureAlgorithm, 0, sizeof( CRYPT_ALGORITHM_IDENTIFIER ));
signatureAlgorithm.pszObjId = szOID_ECDSA_SHA256;
// Tie this certificate to the Private key by setting a property
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo));
KeyProvInfo.pwszContainerName = wszContainerName;
KeyProvInfo.pwszProvName = MS_KEY_STORAGE_PROVIDER;
KeyProvInfo.dwProvType = 0;
KeyProvInfo.dwKeySpec = 0;
pCertContext = CertCreateSelfSignCertificate(
NULL, // Use information from pKeyProvInfo
// parameter to acquire the handle
// to cryptographic provider
&SubjectName, // Pointer to a BLOB containing the
// distinguished name (DN) for
// the certificate subject
0, // No flags: use default behavior
&KeyProvInfo, // Key provider information
&signatureAlgorithm, // Use default signature algorithm
NULL, // Start time : Use the system
// current time by default
NULL, // End time : Use start time plus
// one year by default
NULL // Array of extensions
);
if (NULL == pCertContext) {
printf_s( "CertCreateSelfSignCertificate failed");
goto ErrorReturn;
}
else {
printf_s("Successfully Created Certificate.\n");
}
// Add it to the Store
if (!CertAddCertificateContextToStore (
hStoreHandle,
pCertContext,
CERT_STORE_ADD_ALWAYS,
NULL)) {
printf_s("CertAddCertificateContextToStore for ECC ");
goto ErrorReturn;
}
CommonReturn:
if (SubjectName.pbData)
LocalFree(SubjectName.pbData);
if (NULL != hCNGKey)
NCryptFreeObject(hCNGKey);
return pCertContext;
ErrorReturn:
if (pCertContext)
pCertContext = NULL;
goto CommonReturn;
}
// Function to create an ECC key
// This function uses the NCrypt API to open the storage provider
// and create the key
// It handles the errors which this API might throw
NCRYPT_KEY_HANDLE MyCreateKey(
IN LPWSTR wszContainerName,
IN LPCWSTR pwszAlgid,
IN LPCWSTR pwszProvName
)
{
NCRYPT_PROV_HANDLE hProvider = NULL;
NCRYPT_KEY_HANDLE hKey = NULL;
SECURITY_STATUS Status;
char szErr[100];
Status = NCryptOpenStorageProvider(
&hProvider,
NULL != pwszProvName ? pwszProvName : MS_KEY_STORAGE_PROVIDER,
0 // dwFlags
);
if (0 != Status) {
sprintf_s(szErr, 100, "NCryptOpenStorageProvider failed"
" 0x%x (%d) \n", Status, Status);
goto ErrorReturn;
}
Status = NCryptOpenKey(
hProvider,
&hKey,
wszContainerName,
0, // dwLegacyKeySpec
0 // dwFlags
);
if (0 == Status) {
Status = NCryptDeleteKey(
hKey,
0 // dwFlags
);
hKey = NULL;
if (0 != Status) {
sprintf_s(szErr, 100, "NCryptDeleteKey failed"
" 0x%x (%d) \n", Status, Status);
goto ErrorReturn;
}
}
Status = NCryptCreatePersistedKey(
hProvider,
&hKey,
pwszAlgid,
wszContainerName,
0, // dwLegacyKeySpec
0 // dwFlags
);
if (0 != Status) {
sprintf_s(szErr, 100, "NCryptCreatePersistedKey failed"
" 0x%x (%d) \n", Status, Status);
goto ErrorReturn;
}
Status = NCryptFinalizeKey(
hKey,
0 // dwFlags
);
if (0 != Status) {
sprintf_s(szErr, 100, "NCryptFinalizeKey failed"
" 0x%x (%d) \n", Status, Status);
goto ErrorReturn;
}
CommonReturn:
if (NULL != hProvider) {
Status = NCryptFreeObject(hProvider);
if (0 != Status){
sprintf_s(szErr, 100, "NCryptFreeObject(hProvider) failed"
" 0x%x (%d) \n", Status, Status);
}
}
return hKey;
ErrorReturn:
if (NULL != hKey) {
Status = NCryptFreeObject(hKey);
if (0 != Status){
sprintf_s(szErr, 100, "NCryptFreeObject(hKey) failed"
" 0x%x (%d) \n", Status, Status);
}
hKey = NULL;
}
printf_s("MyCreateKey: %s", szErr ) ;
goto CommonReturn;
}
|