vc++网络安全编程范例(16)-open ssl 哈希编码解码数据

OpenSSL一共提供了8种对称加密算法,其中7种是分组加密算法,仅有的一种流加密算法是RC4。这7种分组加密算法分别是AES、DES、Blowfish、CAST、IDEA、RC2、RC5,都支持电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)四种常用的分组密码加密模式。其中,AES使用的加密反馈模式(CFB)和输出反馈模式(OFB)分组长度是128位,其它算法使用的则是64位。事实上,DES算法里面不仅仅是常用的DES算法,还支持三个密钥和两个密钥3DES算法。

OpenSSL一共实现了4种非对称加密算法,包括DH算法、RSA算法、DSA算法和椭圆曲线算法(EC)。DH算法一般用户密钥交换。RSA算法既可以用于密钥交换,也可以用于数字签名,当然,如果你能够忍受其缓慢的速度,那么也可以用于数据加密。DSA算法则一般只用于数字签名。

我们来用VC++实现使用哈希编码解码数据,请见代码实现与注释讲解

 

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif 

#include 
#include 
#include 
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

//函数申明
HCRYPTPROV GetCryptProv();
void HandleError(char *s);

void main(void)
{

	//变量申明及初始化
	BYTE* pbContent = (BYTE*) "A razzle-dazzle hashed message \n"
		   "Hashing is better than trashing. \n";   // 与编码消息
	DWORD cbContent = strlen((char *)pbContent)+1;  // 消息长度
	HCRYPTPROV hCryptProv;                          // CSP句柄
	DWORD HashAlgSize;                              //算法数据结构大小
	CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;       //算法数据结构
	CMSG_HASHED_ENCODE_INFO HashedEncodeInfo;       //哈希编码数据结构
	DWORD cbEncodedBlob;                            //编码消息长度
	BYTE *pbEncodedBlob;                            //编码 消息
	HCRYPTMSG hMsg;                                 //消息句柄
	HCRYPTMSG hDupMsg;
	DWORD cbData = sizeof(DWORD);
	DWORD dwMsgType;
	DWORD cbDecoded;
	BYTE  *pbDecoded;


	printf("开始处理. \n");
	printf("要被哈希处理及编码的消息是: \n");
	printf("%s\n",pbContent);    // Display original message.
	printf("起初的消息长度是 %d\n",cbContent);

	//获取加密提供者句柄
	hCryptProv= GetCryptProv();

	//-------------------------------------------------------------------
	// 初始化算法数据结构.

	HashAlgSize = sizeof(HashAlgorithm);
	memset(&HashAlgorithm, 0, HashAlgSize);   // 初始化为0
	HashAlgorithm.pszObjId = szOID_RSA_MD5;   //指定算法为MD5哈希算法

	//-------------------------------------------------------------------
	// 初始化哈希编码数据结构
	memset(&HashedEncodeInfo, 0, sizeof(CMSG_HASHED_ENCODE_INFO));
	HashedEncodeInfo.cbSize = sizeof(CMSG_HASHED_ENCODE_INFO);
	HashedEncodeInfo.hCryptProv = hCryptProv;
	HashedEncodeInfo.HashAlgorithm = HashAlgorithm;
	HashedEncodeInfo.pvHashAuxInfo = NULL;

	//-------------------------------------------------------------------
	// 获取编码消息长度
	if(cbEncodedBlob = CryptMsgCalculateEncodedLength(
						 MY_ENCODING_TYPE,     // 编码类型
						 0,                    // 标志位
						 CMSG_HASHED,          // 编码消息类型
						 &HashedEncodeInfo,    // 执行消息类型指针
						 NULL,                 
						 cbContent))           // 预编码消息长度
	{
		printf("需要被分配的长度是 %d 字节.\n",
			cbEncodedBlob);
	}
	else
	{
		HandleError("获取编码消息长度失败");
	}
	//-------------------------------------------------------------------
	// 为编码消息分配空间
	if(pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob))
	{
		printf("已经分配了%d 字节的空间.\n",
			cbEncodedBlob);
	}
	else
	{
		HandleError("内存分配操作出错.");
	}

	//-------------------------------------------------------------------
	// 打开预编码消息
	if(hMsg = CryptMsgOpenToEncode(
				MY_ENCODING_TYPE,        // 编码类型
				0,                       // 标志位
				CMSG_HASHED,             // 编码消息类型
				&HashedEncodeInfo,       // 执行消息类型指针
				NULL,                    
				NULL))                   
	{
		printf("要编码的消息已经被打开. \n");
	}
	else
	{
		HandleError("打开预编码消息失败");
	}

	//-------------------------------------------------------------------
	// 编码消息,并加入消息句柄
	if(CryptMsgUpdate(
				hMsg,          // 消息句柄
				pbContent,     // 预编码消息
				cbContent,     // 消息长度
				TRUE))         // 是否为最后一块数据
	{
		printf("编码后的数据已经被添加到编码消息中. \n");
	}
	else
	{
		HandleError("编码消息失败.");
	}

	//-------------------------------------------------------------------
	// 复制消息
	if(hDupMsg = CryptMsgDuplicate(hMsg))
	{
		 printf("此消息已经被复制.\n");
	}
	else
	{
		 HandleError("此消息复制失败.");
	}

	//-------------------------------------------------------------------
	// 从复制消息中获取参数,这里是获取编码消息内容
	if(CryptMsgGetParam(
				   hDupMsg,                  // 消息句柄
				   CMSG_CONTENT_PARAM,       // 参数类型
				   0,                        // 序号
				   pbEncodedBlob,            // 数据指针
				   &cbEncodedBlob))          // 数据大小
	{
		 printf("消息编码成功. \n");
	}
	else    
	{
		HandleError("获取编码消息参数失败");
	}

	//-------------------------------------------------------------------
	// 关闭消息
	CryptMsgClose(hMsg);
	CryptMsgClose(hDupMsg);



	// 下面的代码是解码哈希消息。一般来说,这段代码应在另外的应用程序中。
	// 编码后的数据及数据大小从文件或网络中获取

	//-------------------------------------------------------------------
	// 打开解码消息

	if(hMsg = CryptMsgOpenToDecode(
				MY_ENCODING_TYPE,       // 编码类型
				0,                      // 标志位
				0,                      // 消息类型
				hCryptProv,             // CSP句柄
				NULL,                   
				NULL))                  
	{
		 printf("要解码的消息已经被打开. \n");
	}
	else
	{
		 HandleError("打开预解码消息失败");
	}

	//-------------------------------------------------------------------
	// 解码消息,把解码后的消息加入到消息句柄中
	if(CryptMsgUpdate(
				hMsg,             // 消息句柄
				pbEncodedBlob,    // 编码消息指针
				cbEncodedBlob,    // 编码消息长度
				TRUE))            // 是否为最后一块数据
	{
		 printf("解码后的数据被加入到解码消息中. \n");
	}
	else
	{
		HandleError("解码消息失败");
	}

	//-------------------------------------------------------------------
	// 获取数据类型
	if(CryptMsgGetParam(
		   hMsg,               // 消息句柄
		   CMSG_TYPE_PARAM,    // 参数类型
		   0,                  // 序号
		   &dwMsgType,         // 数据指针
		   &cbData))           // 数据大小
	{
		printf("消息类型已经被获取. \n");
	}
	else
	{
		HandleError("Decode CMSG_TYPE_PARAM failed");
	}

    //判断数据类型是否为哈希数据结构
	if(dwMsgType == CMSG_HASHED)
	{
		 printf("此消息是哈希结构的消息. 继续. \n");
	}
	else
	{
		HandleError("消息类型错误.");
	}
	//-------------------------------------------------------------------
	// 获取解码后消息长度

	if(CryptMsgGetParam(
				   hMsg,                   // 消息句柄
				   CMSG_CONTENT_PARAM,     // 参数类型
				   0,                      // 序号
				   NULL,                   // 数据指针
				   &cbDecoded))            // 数据长度
	{
		printf("消息的长度 %d 已获取. \n", cbDecoded);
	}
	else
	{
		HandleError("Decode CMSG_CONTENT_PARAM failed");
	}
	//-------------------------------------------------------------------
	// 分配内存空间

	if(pbDecoded = (BYTE *) malloc(cbDecoded))
	{
		 printf("已经为解码后的消息分配了内存空间.\n");
	}
	else
	{
		HandleError("内存分配失败");
	}
	//-------------------------------------------------------------------
	// 获取解码后消息

	if(CryptMsgGetParam(
				hMsg,                    // 消息句柄
				CMSG_CONTENT_PARAM,      // 参数类型
				0,                       // 序号
				pbDecoded,               // 数据指针
				&cbDecoded))             // 数据长度 
	{
		printf("消息解码成功 \n");
		printf("解码后的消息是 \n%s\n", (LPSTR)pbDecoded);
	}
	else
	{
		HandleError("Decoding CMSG_CONTENT_PARAM #2 failed");
	}
	//-------------------------------------------------------------------
	// 验证哈希值

	if(CryptMsgControl(
				  hMsg,                        // 消息句柄
				  0,                           // 标志位
				  CMSG_CTRL_VERIFY_HASH,       // 控制类型
				  NULL))                       
	{
		printf("哈希值验证成功. \n");
		printf("此数据未被篡改.\n");
	}
	else
	{
		 printf("哈希值验证失败.这个消息中某些内容发生改变 .\n");
	}

	printf("程序测试完成无错. \n");

	//-------------------------------------------------------------------
	// 释放内存
	if(pbEncodedBlob)
		free(pbEncodedBlob);
	if(pbDecoded)
		free(pbDecoded);

	CryptMsgClose(hMsg); 

	// 释放CSP句柄

	if(hCryptProv) 
	   CryptReleaseContext(hCryptProv,0);
} // End of main

//获取加密提供者句柄
HCRYPTPROV GetCryptProv()
{
	HCRYPTPROV hCryptProv;                      // 加密服务提供者句柄
	
	//获取加密提供者句柄
	if(CryptAcquireContext(
				&hCryptProv,         // 加密服务提供者句柄
				NULL,                // 密钥容器名,这里使用登陆用户名
				NULL,                // 加密服务提供者,这里取默认值   
				PROV_RSA_FULL,       // 加密服务提供者类型,可以提供加密和签名等功能
				0))                  // 标志
	{
		printf("加密服务提供者句柄获取成功!\n");
	}
	else
	{
		//删除掉密钥集
		if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET))
		{
			   HandleError("删除密钥集出错!");
		}
  
		//重新建立一个新的密钥集
	    if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
		{
		   HandleError("重新建立一个新的密钥集出错!");
		}
 
	}
	return hCryptProv;
}

//  HandleError:错误处理函数,打印错误信息,并退出程序
void HandleError(char *s)
{
    printf("程序执行发生错误!\n");
    printf("%s\n",s);
    printf("错误代码为: %x\n.",GetLastError());
    printf("程序终止执行!\n");
    exit(1);
}


 

你可能感兴趣的:(Visual,Studio2012,Windows8,信息安全,Visual,C++2010编程技术,VC++编程技术,VisualC++信息安全编程)