CryptoAPI 学习

本文由网上各类汇总····

加密与解密第二版 222 页查看  学习:

CryptoAPI 学习_第1张图片

CryptoAPI 学习_第2张图片

CryptoAPI 学习_第3张图片

CryptoAPI 学习_第4张图片



下面的实验顺序颠倒,便于复习```````````````````````````````````````````


实验9````````````````````````````` 

CALG_AES_128 但是发现好像加密解密出来不对的感觉 

#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 
#pragma comment (lib, "crypt32.lib")

  using namespace std;

void cryptoAPI_encrypt(string text, unsigned char* pwd, unsigned char** encryptText, int &out_len)  
{  
	HCRYPTPROV hCryptProv = NULL;    
	HCRYPTKEY hKey = 0;    
	HCRYPTHASH hHash = 0;    
	int dwLength = 0;    


	OSVERSIONINFOW  VersionInformation = {sizeof(OSVERSIONINFOW)};

	GetVersionExW(&VersionInformation);
	LPCWSTR CSP_NAME = MS_ENH_RSA_AES_PROV_XP_W;
	if ( VersionInformation.dwMajorVersion != 5 )
		CSP_NAME = MS_ENH_RSA_AES_PROV_W;

	if(!CryptAcquireContext(&hCryptProv,    
		NULL,    
		CSP_NAME,//CSP_NAME     
		PROV_RSA_AES,    
		CRYPT_VERIFYCONTEXT))    
	{    
		DWORD dwLastErr = GetLastError();    

		if(NTE_BAD_KEYSET == dwLastErr)     
		{    
			return;    
		}    
		else{    
			if(!CryptAcquireContext(&hCryptProv,    
				NULL,    
				CSP_NAME,    
				PROV_RSA_AES,    
				CRYPT_NEWKEYSET))    
			{    
				return;    
			}    
		}    
	}    
	if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))    
	{    
		return;    
	}    

	BYTE *pPwd = pwd;   

	if(!CryptHashData(hHash, pPwd, 16, 0))    
	{    
		return;    
	}    
//CRYPT_EXPORTABLE
	if(!CryptDeriveKey(hCryptProv, CALG_AES_128, hHash,0x800000 , &hKey))//得到最后用来加密的密钥
	{    
		return;    
	}    

	int len = text.length();    
	BYTE *pData ;    
	pData = (BYTE*)malloc(len*4);    
	memcpy(pData,text.c_str(),len);  
	DWORD dwLen = len;    

	if(!CryptEncrypt(hKey, NULL, true, 0, pData, &dwLen, len*4))    
	{    
		return;    
	}    

	cout <<"\n--------------------------\n" << endl << "cryptoAPI encrypt"<


实验8````````````````````````````` 

DES加密解密

#include "stdafx.h"
#include 
#include 
#include 
#pragma comment (lib, "crypt32.lib")

void main()
{
	struct
	{
		BLOBHEADER hdr;
		DWORD cbKeySize;
		BYTE rgbKeyData[8];
	} keyBlob;

	keyBlob.hdr.bType = PLAINTEXTKEYBLOB;//The key is a session key.
	keyBlob.hdr.bVersion = CUR_BLOB_VERSION;
	keyBlob.hdr.reserved = 0;
	keyBlob.hdr.aiKeyAlg = CALG_DES;
	keyBlob.cbKeySize = 8;
	BYTE Key[8] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};
	BYTE Ciphertext[8];

	CopyMemory(keyBlob.rgbKeyData, Key, keyBlob.cbKeySize);

	BYTE pData[256] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38};
	DWORD dwDataLen = 8;

	HCRYPTPROV hProv;
	if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
	{
		HCRYPTKEY hKey;
		if (CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), 0, 0, &hKey))
		{
			DWORD dwMode = CRYPT_MODE_CBC;
			CryptSetKeyParam(hKey, KP_MODE, (BYTE*)(&dwMode), 0);
			CryptEncrypt(hKey, 0, TRUE, 0, pData, &dwDataLen, _countof(pData));
			for (int i = 0; i != 8 /*dwDataLen*/; ++i)
				{
					_tprintf(_T("%02x "), pData[i]);
					Ciphertext[i] = pData[i];
				}
			_tprintf(_T("\r\n"));
			CryptDestroyKey(hKey);
		}
		CryptReleaseContext(hProv, 0);
	}

	if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
	{
		HCRYPTKEY hKey2;
		if (CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), 0, 0, &hKey2))
		{
			DWORD dwMode = CRYPT_MODE_CBC;
			CryptSetKeyParam(hKey2, KP_MODE, (BYTE*)(&dwMode), 0);
			CryptDecrypt(hKey2, 0, TRUE, 0, pData, &dwDataLen);
			for (int i = 0; i != 8 /*dwDataLen*/; ++i)
			{
				_tprintf(_T("%02x "), pData[i]);
				Ciphertext[i] = pData[i];
			}
			_tprintf(_T("\r\n"));
			CryptDestroyKey(hKey2);
		}
		CryptReleaseContext(hProv, 0);
	}
	return ;
} // end main


实验7`````````````````````````````

/*
下面我们来看看如何哈希一个对话密钥,这个密钥可以用来对一个消息,文件进行加密。我们依旧从一个程序开始。
*/
#include "stdafx.h"
#include 
#include 
#include 
#pragma comment (lib, "crypt32.lib")
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)


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.

void main()
{

	//--------------------------------------------------------------------
	// Copyright (c) Microsoft Corporation.  All rights reserved.
	// Declare variables.

	HCRYPTPROV hCryptProv;
	HCRYPTHASH hHash;
	HCRYPTKEY hKey;

	//--------------------------------------------------------------------
	// Begin processing.

	printf("Process beginning. Creating a session key. \n");
	BYTE pData[11]="1234567890";

	if(CryptAcquireContext(                           // 首先依旧是获取一个缺省的CSP句柄
		&hCryptProv, 
		NULL, 
		NULL, 
		PROV_RSA_FULL, 
		0)) 
	{
		printf("CryptAcquireContext complete. \n");
	}
	else
	{
		MyHandleError(TEXT("Acquisition of context failed."));
	}

	if(CryptCreateHash(                            //     创建一个CALG_MD5算法的HASH对象,这个hash对象用的是MD5算法
		hCryptProv,                                 //        指定一个CSP句柄
		CALG_MD5,                                   //    指定算法
		0,               
		0, 
		&hHash)) 
	{
		printf("An empty hash object has been created. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptBeginHash!\n"));
	}

	if(CryptGenKey(                //  创建密钥
		hCryptProv,               //  传入一个CSP句柄
		CALG_RC2,                 //  指明密钥身成所用算法
		CRYPT_EXPORTABLE,        //  说明密钥是可以导出到CSP,用于这个应用程序外的
		&hKey)) 
	{
		printf("A random session key has been created. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptGenKey!\n"));
	}
	if(CryptHashSessionKey(                             //对生成的密钥进行hash
		hHash, 
		hKey, 
		0))
	{
		printf("The session key has been hashed. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptHashSessionKey!\n"));
	}
	DWORD dwRead;							
	//在这里就可以添加代码,用生成的密钥进行加密

	

		if(hHash)
		{
			if(!(CryptDestroyHash(hHash)))
				MyHandleError(TEXT("Error during CryptDestroyHash"));
		}


		if(hKey)
		{
			if(!(CryptDestroyKey(hKey)))
				MyHandleError(TEXT("Error during CryptDestroyKey"));
		}

		// Release the CSP.

		if(hCryptProv)
		{
			if(!(CryptReleaseContext(hCryptProv,0)))
				MyHandleError(TEXT("Error during CryptReleaseContext"));
		}

		printf("Create random session key completed without error. \n");
} // end main


实验6`````````````````````````````

/*
下面逐渐进入主题了,现在来讲讲是如何对数据进行Encoding and Decoding的。依旧是从一段程序中开始。
*/
#include "stdafx.h"
#include 
#include 
#include 
#pragma comment (lib, "crypt32.lib")
#define MY_ENCODING_TYPE  (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)

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.


void main(void)
{
	HCRYPTMSG hMsg;                         //指向一个消息句柄
		BYTE* pbContent;                    //一个BYTE指针指向消息
		DWORD cbContent;                    //消息长度
		DWORD cbEncodedBlob;                //ECODE的BLOB的大小
		BYTE *pbEncodedBlob;                //一个BYTE指针指向ENCODE BLOB

		DWORD cbData = sizeof(DWORD);        //数据大小
		DWORD cbDecoded;                     //Decode内容大小
		BYTE *pbDecoded;                     //指向Decode的指针

	pbContent = (BYTE*)"Security is our only business";
	cbContent = strlen((char *) pbContent)+1;

	printf("The original message => %s\n",pbContent);  

	if(cbEncodedBlob = CryptMsgCalculateEncodedLength(
		MY_ENCODING_TYPE,      //指定Encode类型,在程序的开头已经预定义了,MY_ENCODING_TYPE 就是 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING
		0,                      //Flags
		CMSG_DATA,              // 定义了数据的类型,这里指定为BYTE型的字符串
		NULL,                   
		NULL,                   
		cbContent))             //  内容的大小
								//这里的的函数的作用是计算指定消息Encode所需要的最大的长度,通过计算,为一个BLOB分配内存空间。
	{
		printf("The length of the data has been calculated. \n");
	}
	else
	{
		MyHandleError(TEXT("Getting cbEncodedBlob length failed"));
	}
	//为encode blob分配内存空间

		if(pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob))
		{
			printf("Memory has been allocated for the signed message. \n");
		}
		else
		{
			MyHandleError(TEXT("Memory allocation failed"));
		}

		if(hMsg = CryptMsgOpenToEncode(  //CryptMsgOpenToEncode为Encode,开一个消息
			MY_ENCODING_TYPE,           // Encode类型,文件开始有说明
			0,                          // Flags
			CMSG_DATA,                  // 指定Message的类型,CMSG_DATA说明类型没用到
			NULL,                       // 现在没有到,为NULL
			NULL,                       // 同上
			NULL))                      // 不是流加密,这个参数为NULL
		{
			printf("The message to be encoded has been opened. \n");
		}
		else
		{
			MyHandleError(TEXT("OpenToEncode failed"));
		}
		if(CryptMsgUpdate(                 // CryptMsgUpdate将数据加到消息中,可以通过循环,将数据一段段的加得到消息中
			hMsg,                           // 一个小心句柄
			pbContent,                      //    指向数据的指针
			cbContent,                      //   数据的大小
			TRUE))                         //   TRUE表明这个是最后一段数据,在开个消息的时候,如果CMSG_DETACHED_FLAG有使用到,这设为FALSE,否则为TRUE。
		{
			printf("Content has been added to the encoded message. \n");
		}
		else
		{
			MyHandleError(TEXT("MsgUpdate failed"));
		}

		if(CryptMsgGetParam(              // CryptMsgGetParam是获取一个消息中的参数
			hMsg,                         // 一个消息句柄
			CMSG_BARE_CONTENT_PARAM,      //指定要获取的参数的类型
			0,                        
			pbEncodedBlob,              //     一个接受数据的内存地址
			&cbEncodedBlob))            //     BLOB的大小,即是上面接受的数据的大小
		{
			printf("Message encoded successfully. \nencoded");
			printf("The message is %s.\n",(LPSTR)pbEncodedBlob);
		}
		else
		{
			MyHandleError(TEXT("MsgGetParam failed"));
		}
										//释放消息句柄
			if(hMsg)
				CryptMsgClose(hMsg);

	//

		if(hMsg = CryptMsgOpenToDecode(  //开个Decode的小心句柄,参数和上面的Encode一样
			MY_ENCODING_TYPE,      
			0,                                   
			CMSG_DATA,             
			NULL,                  
			NULL,                 
			NULL))                
		{
			printf("The message to decode is open. \n");
		}
		else
		{
			MyHandleError(TEXT("OpenToDecode failed"));
		}
											//下面的过程和Encode类似,调用的函数和上面相同,只不过是过程逆向

			printf("\nThe length of the encoded message is %d.\n\n",
			cbEncodedBlob);

		if(CryptMsgUpdate(
			hMsg,                 // Handle to the message
			pbEncodedBlob,        // Pointer to the encoded BLOB
			cbEncodedBlob,        // Size of the encoded BLOB
			TRUE))                // Last call
		{
			printf("The encoded BLOB has been added to the message. \n");
		}
		else
		{
			MyHandleError(TEXT("Decode MsgUpdate failed"));
		}
		if(CryptMsgGetParam(     // CryptMsgGetParam的调用和上面有所不同,这里一共是调用两次,第一次的作用主要是得到消息的大小,第二次是得到消息所在的内存地址
			hMsg,                 //消息句柄
			CMSG_CONTENT_PARAM,    // Parameter type
			0,                     
			NULL,                  // Address for returned 
			// information
			&cbDecoded))           // Size of the returned
			// information
		{
			printf("The decoded message size is %d. \n", cbDecoded);
		}
		else
		{
			MyHandleError(TEXT("Decode CMSG_CONTENT_PARAM failed"));
		}
		if(pbDecoded = (BYTE *) malloc(cbDecoded))
		{
			printf("Memory has been allocated for the decoded message.\n");
		}
		else
		{
			MyHandleError(TEXT("Decoding memory allocation failed."));
		}
		if(CryptMsgGetParam(
			hMsg,                  // Handle to the message
			CMSG_CONTENT_PARAM,    // Parameter type
			0,                     // Index
			pbDecoded,             // Address for returned 
			// information
			&cbDecoded))           // Size of the returned 
			// information
		{
			printf("The message is %s.\n",(LPSTR)pbDecoded);
		}
		else
		{
			MyHandleError(TEXT("Decode CMSG_CONTENT_PARAM #2 failed"));
		}
		if(pbEncodedBlob)
			free(pbEncodedBlob);
		if(pbDecoded)
			free(pbDecoded);
		if(hMsg)
			CryptMsgClose(hMsg);

		printf("This program ran to completion without error. \n");

} //  End of main


实验5`````````````````````````````

/*
当我们已经生成了一个密钥,我们下面要做的是如何保存,导出,导入一个对话密钥。将一个密钥保存起来,导出,保存到硬盘上。这样,这个密钥就可以在其它应用程序上使用,而不会随着生成密钥程序的关闭而丢失了。
	下面这段程序就是用来演示如何保存,导出一个对话密钥的。
*/
#include "stdafx.h"
#include 
#include 
#include 
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

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.
void main(void)
{
	//--------------------------------------------------------------------
	// Declare and initialize variables.

	HCRYPTPROV hProv;       // CSP handle
	HCRYPTKEY hSignKey;     // Signature key pair handle
	HCRYPTKEY hXchgKey;     // Exchange key pair handle
	HCRYPTKEY hKey;         // Session key handle
	BYTE *pbKeyBlob;        // Pointer to a simple key BLOB
	DWORD dwBlobLen;        // The length of the key BLOB

	//--------------------------------------------------------------------
	// Acquire a cryptographic provider context handle.

	if(CryptAcquireContext(                         //    获取一个缺省容器的CSP句柄
		&hProv, 
		NULL, 
		NULL, 
		PROV_RSA_FULL, 
		0)) 
	{
		printf("The CSP has been acquired. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptAcquireContext."));
	}

	if(CryptGetUserKey(         // CryptGetUserKey是获取一个密钥//句柄的函数,成功返回TRUE
		hProv,             //指定容器的CSP模块句柄
		AT_SIGNATURE,           //指定私钥的类型
		&hSignKey))                  //原来接收获取的密钥句柄
	{
		_tprintf(TEXT("A signature key is available.\n"));
	}
	else
	{
		_tprintf(TEXT("No signature key is available.\n"));
		if(GetLastError() == NTE_NO_KEY)      // NTE_NO_KEY意味着密钥不存在,下面就生成一个密钥
		{

			_tprintf(TEXT("The signature key does not exist.\n"));
			_tprintf(TEXT("Create a signature key pair.\n")); 
			if(CryptGenKey(    // CryptGenKey生成一个密钥
				hProv,    //指定CSP模块的句柄
				AT_SIGNATURE,  //对于公钥密码系统,生成一个私钥和一个公钥,这个参数指定了这个密钥是公钥,于是生成了一个密码对。如果不是公钥系统,则指定了密码算法,具体看MSDN。
				0,             //指定了生成密钥的类型,这个参数的说明挺多的,想获取更为详尽的资料请看MSDN。
				&hSignKey)) 
			{
				_tprintf(TEXT("Created a signature key pair.\n"));
			}
			else
			{
				MyHandleError(TEXT("Error occurred creating a ")
					TEXT("signature key.\n")); 
			}
		}
		else
		{
			MyHandleError(TEXT("An error other than NTE_NO_KEY ")
				TEXT("getting a signature key.\n"));
		}
	} // End if.


	//--------------------------------------------------------------------

	if(CryptGetUserKey(                              //        获取一个AT_KEYEXCHANGE,类型的密钥句柄,保存在hXchgKey中
		hProv, 
		AT_KEYEXCHANGE, 
		&hXchgKey)) 
	{
		printf("The key exchange key has been acquired. \n");
	}
	else
	{
		printf("Error during CryptGetUserKey exchange key.");
	}
	// Generate a session key.

	if (CryptGenKey(                                  //生成一个CRYPT_EXPORTABLE(可导出的),CALG_RC4(指定算法)的密钥,保存在hKey
		hProv,      
		CALG_RC4,      
		CRYPT_EXPORTABLE, 
		&hKey))
	{   
		printf("Original session key is created. \n");
	}
	else
	{
		MyHandleError(TEXT("ERROR -- CryptGenKey."));
	}
	if(CryptExportKey(                                 //  CryptExportKey导出一个密钥
		hKey,                                         // 将要导出的密钥的句柄
		hXchgKey,									//用户最终使用到的密钥的句柄
		SIMPLEBLOB,                               // 指定BLOB的类型,SIMPLEBLOB说明是 用来导出对话密钥的
		0,                                            // 指定密钥的附加属性
		NULL,                                         
		&dwBlobLen))                                 // 当时这个函数在这里的主要
													//目的是得到这个BLOB的长度
	{
		printf("Size of the BLOB for the session key determined. \n");
	}
	else
	{
		MyHandleError(TEXT("Error computing BLOB length."));
	}

	if(pbKeyBlob = (BYTE*)malloc(dwBlobLen)) 
	{
		printf("Memory has been allocated for the BLOB. \n");
	}
	else
	{
		MyHandleError(TEXT("Out of memory. \n"));
	}
	if(CryptExportKey(                            //这是这个函数才是真正的导出密钥
		hKey, 
		hXchgKey, 
		SIMPLEBLOB, 
		0, 
		pbKeyBlob, 
		&dwBlobLen))
	{
		printf("Contents have been written to the BLOB. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptExportKey."));
	}
	free(pbKeyBlob);                                  //释放内存

		// Destroy the session key.
		if(hKey)
			CryptDestroyKey(hKey);

	// Destroy the signature key handle.
	if(hSignKey)
		CryptDestroyKey(hSignKey);

	// Destroy the key exchange key handle.
	if(hXchgKey)
		CryptDestroyKey(hXchgKey);

	// Release the provider handle.
	if(hProv) 
		CryptReleaseContext(hProv, 0);
	printf("The program ran to completion without error. \n");

}


实验4`````````````````````````````

/*
讲如何复制一个对话密钥,照例是从一个程序讲起,完成以下任务。获取一个CSP句柄,
创建一个对话密钥,复制密钥。改变密钥生成过程,随机填充一个缓冲区,销毁密钥句柄,释放CSP句柄
*/
#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 
#include 
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

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.

void GetConsoleInput(char* strInput, 
	int   intMaxChars)
{
	char ch;
	char minChar = ' ';
	minChar++;

	ch = getch();
	while (ch != '\r')
	{
		if (ch == '\b' && strlen(strInput) > 0)
		{
			strInput[strlen(strInput)-1]   = '\0';
			printf("\b \b");
		}
		else if (ch >= minChar && strlen(strInput) < intMaxChars)
		{
			strInput[strlen(strInput)+1] = '\0';
			strInput[strlen(strInput)]   = ch;
			putch('*');
		}
		ch = getch();
	}
	putch('\n');
}

void main()
{
	//-------------------------------------------------------------------
	// Declare and initialize variables.

	HCRYPTPROV   hCryptProv;                        // CSP句柄
		HCRYPTKEY    hOriginalKey;              // 源密钥句柄
		HCRYPTKEY    hDuplicateKey;              // 复制后的密钥句柄
		DWORD        dwMode;                            
	BYTE          pbData[16];

	printf("This program creates a session key and duplicates \n");
	printf("that key. Next, parameters are added to the original \n");
	printf("key. Finally, both keys are destroyed. \n\n");

	if(CryptAcquireContext(                    //   获取CSP句柄,前面叙述过了,这里就不叙述了
		&hCryptProv,
		NULL,
		NULL,
		PROV_RSA_FULL,
		0)) 
	{    
		printf("CryptAcquireContext succeeded. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptAcquireContext!\n"));
	}
	//-------------------------------------------------------------------
	if (CryptGenKey(                     // 生成一个CALG_RC4算法生成的密钥,保存在hOriginalKey中
		hCryptProv, 
		CALG_RC4,                        // ALG_ID结构,指定生成这个密钥使用的算法
		0, 
		&hOriginalKey))
	{
		printf("Original session key is created. \n");
	}
	else
	{
		MyHandleError(TEXT("ERROR - CryptGenKey."));
	}

	if (CryptDuplicateKey(                          //  复制密钥
		hOriginalKey,                               //  源密钥
		NULL,                                       // 保留参数,必须为NULL
		0,                                          // 保留参数,必须为0
		&hDuplicateKey))                            //  副本密钥
	{
		printf("The session key has been duplicated. \n");
	}
	else
	{
		MyHandleError(TEXT("ERROR - CryptDuplicateKey"));
	}
											// 给源密钥设置附加参数
		dwMode = CRYPT_MODE_ECB;            //CRYPT_MODE_ECB是一个没有反馈的块加密模式  
		if(CryptSetKeyParam(
			hOriginalKey, 
			KP_MODE,						// KP_MODE指定密钥的某种属性被改变,
											// 意味着改变的是加密模式
			(BYTE*)&dwMode,              //     指向一个已经被初始化的缓冲区
			0))                                          
		{
			printf("Key Parameters set. \n");
		}
		else
		{
			MyHandleError(TEXT("Error during CryptSetKeyParam."));
		}
		if(CryptGenRandom(              //                随机填充一块缓冲区
			hCryptProv,                //                   CSP句柄
			8,                       //  缓冲区大小
			pbData))                 //      缓冲区地址
		{
			printf("Random sequence generated. \n");
		}
		else
		{
			MyHandleError(TEXT("Error during CryptGenRandom."));
		}
		if(CryptSetKeyParam(           //再次给密钥设置属性
			hOriginalKey, 
			KP_IV,               // KP_IV意味着,这个函数的第三个参数指向一个BYTE数组,数组大小为块大小/8。
			pbData, 
			0)) 
		{
			printf("Parameter set with random sequence as "
				"initialization vector. \n");
		}
		else
		{
			MyHandleError(TEXT("Error during CryptSetKeyParam."));
		}
		//-------------------------------------------------------------------

		if (hOriginalKey)                  //                  以下依次销毁,释放源密钥句柄,副本句柄,CSP句柄,
			if (!CryptDestroyKey(hOriginalKey))
				MyHandleError(TEXT("Failed CryptDestroyKey\n"));

		if (hDuplicateKey)
			if (!CryptDestroyKey(hDuplicateKey))
				MyHandleError(TEXT("Failed CryptDestroyKey\n"));

		if(hCryptProv)
			if (!CryptReleaseContext(hCryptProv, 0))
				MyHandleError(TEXT("Failed CryptReleaseContext\n"));

		printf("\nThe program ran to completion without error. \n");

} // End of main.



实验3`````````````````````````````

/*任务一:调用CryptAcquireContext,获取一个缺省CSP和缺省密钥容器的句柄
	任务二:用CryptCreateHash去创建一个空的哈希对象
	任务三:用CryptHashData.哈希密码
	任务四:调用CryptDeriveKey获取一个对话密钥
	任务五:销毁密码和哈希后的数据
	任务六:释放CSP
*/
#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 
#include 

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.

void GetConsoleInput(char* strInput, 
	int   intMaxChars)
{
	char ch;
	char minChar = ' ';
	minChar++;

	ch = getch();
	while (ch != '\r')
	{
		if (ch == '\b' && strlen(strInput) > 0)
		{
			strInput[strlen(strInput)-1]   = '\0';
			printf("\b \b");
		}
		else if (ch >= minChar && strlen(strInput) < intMaxChars)
		{
			strInput[strlen(strInput)+1] = '\0';
			strInput[strlen(strInput)]   = ch;
			putch('*');
		}
		ch = getch();
	}
	putch('\n');
}
void main()
{

	HCRYPTPROV hCryptProv;                       // 定义CSP句柄
		HCRYPTKEY hKey;                          // 定义密钥句柄
		HCRYPTHASH hHash;                        // 定义一个HASH对象的句柄
		CHAR szPassword[512] = "";               // 定义512大小的字符数组,用来保存密码
		DWORD dwLength;                          // 保存密码长度
		fprintf(stderr,"Enter a password to be used to create a key:");

	GetConsoleInput(szPassword, 512);             //  获取密码,这个是自己写的函数,目的是在屏幕上显示的是*。
		printf("The password has been stored.\n");
	dwLength = strlen(szPassword);


	if(CryptAcquireContext(                    //以下是获取一个缺省的PROV_RSA_FULL  CSP 句柄
		&hCryptProv, 
		NULL, 
		NULL, 
		PROV_RSA_FULL, 
		0)) 
	{
		printf("A context has been acquired. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptAcquireContext!"));
	}
	//--------------------------------------------------------------------
	if(CryptCreateHash(                             //  调用CryptCreateHash创建一个HASH对象
		hCryptProv,                                 //   一个CSP句柄
		CALG_MD5,                                   //  确定哈希算法   8003h
		0,    //对于非密钥算法,这个参数一定是0,如果是密钥算法,那么这个参数就是密钥
		0,     //                      保留参数,为0
		&hHash))                                       //  一个哈希对象的指针
	{
		printf("An empty hash object has been created. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptCreateHash!"));
	}
	//--------------------------------------------------------------------
	if(CryptHashData(                        //   调用CryptHashData哈希密码
		hHash,                               //   哈希对象
		(BYTE *)szPassword,                  // 指向缓冲区的地址
		dwLength,                            //           密码长度
		0)) 
	{
		printf("The password has been hashed. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptHashData!"));
	}
	//--------------------------------------------------------------------
	if(CryptDeriveKey(                //调用CryptDeriveKey获取对话密码
		hCryptProv,                   // CSP句柄
		CALG_RC2,                     // 6602h 一个ALG_ID结构,用来指定对称密钥生成的算法
		hHash,                        // 哈希对象
		CRYPT_EXPORTABLE,             //指定生成密钥的类型,CRYPT_EXPORTABLE意味着这个程序生成的密钥可以被其它程序调用,而不是仅仅限于这个程序当中。但是它不能用于非对称密码中。
		&hKey)) 
	{
		printf("The key has been derived. \n");
	}
	else
	{
		MyHandleError(TEXT("Error during CryptDeriveKey!"));
	}
	if(hHash)                                         //  销毁哈希对象
	{
		if(!(CryptDestroyHash(hHash)))
			MyHandleError(TEXT("Error during CryptDestroyHash"));
	}

	if(hKey)                                         //   销毁密钥句柄
	{
		if(!(CryptDestroyKey(hKey)))
			MyHandleError(TEXT("Error during CryptDestroyKey"));
	}

	if(hCryptProv)                                     //  销毁CSP句柄
	{
		if(!(CryptReleaseContext(hCryptProv, 0)))
			MyHandleError(TEXT("Error during CryptReleaseContext"));
	}
	printf("The program to derive a key completed without error. \n");
} // end main



实验2`````````````````````````````

/*这个程序演示了以下内容和几个函数。
	一.  用CryptAcquireContext获取一个缺省容器的缺省CSP的句柄。如果缺省容器不存在,用CryptAcquireContext创建一个。
	二.  用CryptGetProvParam获取CSP和容器的信息。
	三.  用CryptContextAddRef增加CSP的引用计数器的数值。
	四.  用CryptAcquireContext创建一个指定的容器
	五.  用CryptAcquireContext删除一个容器
	六.  用一个新创建的容器获取一个CSP的句柄。
*/
#include 
#include "stdafx.h"
#include 
#include 
#include 

	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.

void main(void)
{

	HCRYPTPROV hCryptProv;                            //定义CSP句柄

	if(CryptAcquireContext(
		&hCryptProv, 
		NULL,                                           //缺省容器
		NULL,                                           //缺省CSP
		PROV_RSA_FULL, 
		0)) 
	{
		_tprintf(TEXT("CryptAcquireContext succeeded.\n"));
	}
	else
	{
		if (GetLastError() == NTE_BAD_KEYSET)               //同样,如果当不存在这样的容器的时候,创建一个
		{
			if(CryptAcquireContext(
				&hCryptProv, 
				NULL, 
				NULL, 
				PROV_RSA_FULL, 
				CRYPT_NEWKEYSET))                     
			{
				_tprintf(TEXT("CryptAcquireContext succeeded.\n"));
			}
			else
			{
				MyHandleError(TEXT("Could not create the default ")
					TEXT("key container.\n"));
			}
		}
		else
		{
			MyHandleError(TEXT("A general error running ")
				TEXT("CryptAcquireContext."));
		}
	}

	CHAR pszName[1000];
	DWORD cbName;

	cbName = 1000;
	if(CryptGetProvParam(
		hCryptProv,                         //CSP模块句柄
		PP_NAME,                            //指定获取哪些信息,这里是指定获取CSP名字的信息
		(BYTE*)pszName,                     //缓冲区接受信息返回值
		&cbName, 
		0))
	{
		_tprintf(TEXT("CryptGetProvParam succeeded.\n"));
		printf("Provider name: %s\n", pszName);
	}
	else
	{
		MyHandleError(TEXT("Error reading CSP name.\n"));
	}

	//---------------------------------------------------------------
	// Read the name of the key container.
	cbName = 1000;
	if(CryptGetProvParam(
		hCryptProv, 
		PP_CONTAINER,                                       //获取容器名字
		(BYTE*)pszName, 
		&cbName, 
		0))
	{
		_tprintf(TEXT("CryptGetProvParam succeeded.\n"));
		printf("Key Container name: %s\n", pszName);
	}
	else
	{
		MyHandleError(TEXT("Error reading key container name.\n"));
	}

	//增加CSP的引用计数器的数值。
	if(CryptContextAddRef( // CryptContextAddRef是向一个CSP的引用计数器增加一个值的函数
		hCryptProv, 
		NULL,              //保留值,必须为NULL
		0))               //保留值,必须为0
	{
		_tprintf(TEXT("CryptcontextAddRef succeeded.\n"));
	}
	else
	{
		MyHandleError(TEXT("Error during CryptContextAddRef!\n"));
	}

	//---------------------------------------------------------------
	//  The reference count on hCryptProv is now greater than one. 
	//  The first call to CryptReleaseContext will not release the 
	//  provider handle. 

	//---------------------------------------------------------------
	//  Release the context once.
	if (CryptReleaseContext(hCryptProv, 0))  // CryptReleaseContext是用来释放CSP句柄的,当这个函数调用一次的时候,CSP里面的引用计数就减少一,当引用计数减少的0的时候。CSP将不能再被这个程序中的任何函数调用了。
	{
		_tprintf(TEXT("The first call to CryptReleaseContext ")
			TEXT("succeeded.\n"));
	}
	else
	{
		MyHandleError(TEXT("Error during ")
			TEXT("CryptReleaseContext #1!\n"));
	}

	if (CryptReleaseContext(hCryptProv, 0))                //再次释放CSP模块
	{
		_tprintf(TEXT("The second call to CryptReleaseContext ")
			TEXT("succeeded.\n"));
	}
	else
	{
		MyHandleError(TEXT("Error during ")
			TEXT("CryptReleaseContext #2!\n"));
	}

	//下面是从PROV_RSA_FULL的CSP模块中创建一个自己的容器
		LPCTSTR pszContainerName = TEXT("My Sample Key Container");

	hCryptProv = NULL;
	if(CryptAcquireContext(
		&hCryptProv, 
		pszContainerName,
		NULL, 
		PROV_RSA_FULL, 
		CRYPT_NEWKEYSET)) 
	{
		_tprintf(TEXT("CryptAcquireContext succeeded. \n"));
		_tprintf(TEXT("New key set created. \n")); 

		//-----------------------------------------------------------
		// Release the provider handle and the key container.
		if(hCryptProv)
		{
			if(CryptReleaseContext(hCryptProv, 0)) 
			{
				hCryptProv = NULL;
				_tprintf(TEXT("CryptReleaseContext succeeded. \n"));
			}
			else
			{
				MyHandleError(TEXT("Error during ")
					TEXT("CryptReleaseContext!\n"));
			}
		}
	}
	else
	{
		if(GetLastError() == NTE_EXISTS)
		{
			_tprintf(TEXT("The named key container could not be ")
				TEXT("created because it already exists.\n"));

		}
		else
		{
			MyHandleError(TEXT("Error during CryptAcquireContext ")
				TEXT("for a new key container."));
		}
	}


	if(CryptAcquireContext(
		&hCryptProv, 
		pszContainerName, 
		NULL, 
		PROV_RSA_FULL,
		0)) 
	{
		_tprintf(TEXT("Acquired the key set just created. \n"));
	}
	else
	{
		MyHandleError(TEXT("Error during CryptAcquireContext!\n"));
	}

	//---------------------------------------------------------------
	// Perform cryptographic operations.

	//---------------------------------------------------------------
	if(CryptReleaseContext(
		hCryptProv, 
		0)) 
	{
		_tprintf(TEXT("CryptReleaseContext succeeded. \n"));
	}
	else
	{
		MyHandleError(TEXT("Error during CryptReleaseContext!\n"));
	}


	if(CryptAcquireContext(
		&hCryptProv, 
		pszContainerName, 
		NULL, 
		PROV_RSA_FULL,
	CRYPT_DELETEKEYSET)) //CRYPT_DELETEKEYSET意味着CryptAcquireContex删除一个指定的容器
	{
		_tprintf(TEXT("Deleted the key container just created. \n"));
	}
	else
	{
		MyHandleError(TEXT("Error during CryptAcquireContext!\n"));
	}
}

实验1`````````````````````````````

#include "stdafx.h"
#include 
#include 
#include 
#include 

/*
任务一:获取一个指定的密钥容器,如果这个容器不存在,创建一个。
任务二:如果容器中不存在一个签名密钥对,创建一个
任务三:如果容器中不存在一个交换密钥对,创建一个
*/
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.

int _tmain(int argc, _TCHAR* argv[])
{
	HCRYPTPROV hCryptProv;   //定义一个CSP模块的句柄。“CSP模块,请查看《加密解密二》222页,那里有简单的说明,这里就不说了。     

	LPCTSTR pszContainerName = TEXT("My Sample Key Container");//用一个TEXT宏定义一个容器的名字,


	if(CryptAcquireContext(        //这个函数是获取有某个容器的CSP模块的指针,成功返回TRUE。
		&hCryptProv,            //指向一个CSP模块句柄指针,里面用指定的容器
		pszContainerName,       //指定容器的名称
		NULL,                //这个参数这里用的是缺省值,指得是缺省得CSP模块,你也可以传入一个LPCTSTR类型的字符串,指定CSP模块
		PROV_RSA_FULL,      //确定密钥的类型
		0))                    //常设为0,还有些其他的类型,请看MSDN
	{
		_tprintf(
			TEXT("A crypto context with the %s key container ")
			TEXT("has been acquired.\n"), 
			pszContainerName);
	}
	else
	{ 
		//不成功的处理段
		if(GetLastError() == NTE_BAD_KEYSET)// NTE_BAD_KEYSET意味着密钥容器不存在,
											//下面就去创建一个
											//新的密钥容器
		{
			if(CryptAcquireContext(
				&hCryptProv, 
				pszContainerName, 
				NULL, 
				PROV_RSA_FULL, 
				CRYPT_NEWKEYSET))           // CRYPT_NEWKEYSET意味着当指定容器不存在的时候,去创建一个容器。
			{
				_tprintf(TEXT("A new key container has been ")
					TEXT("created.\n"));
			}
			else
			{
				MyHandleError(TEXT("Could not create a new key ")
					TEXT("container.\n"));
			}
		}
		else
		{
			MyHandleError(TEXT("CryptAcquireContext failed.\n"));
		}
	}


	HCRYPTKEY hKey;            //创建一个密钥句柄

	if(CryptGetUserKey(         // CryptGetUserKey是获取一个密钥//句柄的函数,成功返回TRUE
		hCryptProv,             //指定容器的CSP模块句柄
		AT_SIGNATURE,           //指定私钥的类型
		&hKey))                  //原来接收获取的密钥句柄
	{
		_tprintf(TEXT("A signature key is available.\n"));
	}
	else
	{
		_tprintf(TEXT("No signature key is available.\n"));
		if(GetLastError() == NTE_NO_KEY)      // NTE_NO_KEY意味着密钥不存在,下面就生成一个密钥
		{

			_tprintf(TEXT("The signature key does not exist.\n"));
			_tprintf(TEXT("Create a signature key pair.\n")); 
			if(CryptGenKey(    // CryptGenKey生成一个密钥
				hCryptProv,    //指定CSP模块的句柄
				AT_SIGNATURE,  //对于公钥密码系统,生成一个私钥和一个公钥,这个参数指定了这个密钥是公钥,于是生成了一个密码对。如果不是公钥系统,则指定了密码算法,具体看MSDN。
				0,             //指定了生成密钥的类型,这个参数的说明挺多的,想获取更为详尽的资料请看MSDN。
				&hKey)) 
			{
				_tprintf(TEXT("Created a signature key pair.\n"));
			}
			else
			{
				MyHandleError(TEXT("Error occurred creating a ")
					TEXT("signature key.\n")); 
			}
		}
		else
		{
			MyHandleError(TEXT("An error other than NTE_NO_KEY ")
				TEXT("getting a signature key.\n"));
		}
	} // End if.

	_tprintf(TEXT("A signature key pair existed, or one was ")
		TEXT("created.\n\n"));

	if(hKey)                              //将密钥句柄销毁
	{
		if(!(CryptDestroyKey(hKey)))
		{
			MyHandleError(TEXT("Error during CryptDestroyKey."));
		}

		hKey = NULL;
	} 

	//下面这部分和上面是类似的,只不过密钥类型不相同而已。
		if(CryptGetUserKey(
			hCryptProv,
			AT_KEYEXCHANGE,
			&hKey)) 
		{
			_tprintf(TEXT("An exchange key exists.\n"));
		}
		else
		{
			_tprintf(TEXT("No exchange key is available.\n"));

			// Check to determine whether an exchange key 
			// needs to be created.
			if(GetLastError() == NTE_NO_KEY) 
			{ 
				// Create a key exchange key pair.
				_tprintf(TEXT("The exchange key does not exist.\n"));
				_tprintf(TEXT("Attempting to create an exchange key ")
					TEXT("pair.\n"));
				if(CryptGenKey(
					hCryptProv,
					AT_KEYEXCHANGE,
					0,
					&hKey)) 
				{
					_tprintf(TEXT("Exchange key pair created.\n"));
				}
				else
				{
					MyHandleError(TEXT("Error occurred attempting to ")
						TEXT("create an exchange key.\n"));
				}
			}
			else
			{
				MyHandleError(TEXT("An error other than NTE_NO_KEY ")
					TEXT("occurred.\n"));
			}
		}

		// Destroy the exchange key.
		if(hKey)
		{
			if(!(CryptDestroyKey(hKey)))
			{
				MyHandleError(TEXT("Error during CryptDestroyKey."));
			}

			hKey = NULL;
		}

		// Release the CSP.
		if(hCryptProv)
		{
			if(!(CryptReleaseContext(hCryptProv, 0)))
			{
				MyHandleError(TEXT("Error during CryptReleaseContext."));
			}
		} 

		_tprintf(TEXT("Everything is okay. A signature key "));
		_tprintf(TEXT("pair and an exchange key exist in "));
		_tprintf(TEXT("the %s key container.\n"), pszContainerName);  

	return 0;
}









转载至:  http://bbs.pediy.com/showthread.php?t=31357&highlight=Crypto+API



转载于:https://www.cnblogs.com/zcc1414/p/3982359.html

你可能感兴趣的:(CryptoAPI 学习)