首页 > 程序开发 > 综合编程 > 安全编程 >

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

2011-12-23

OpenSSL一共提供了8种对称加密算法,其中7种是分组加密算法,仅有的一种流加密算法是RC4。这7种分组加密算法分别是AES、DES、Blowfish、CAST、IDEA、RC2、RC5,都支持电子密码本模式(ECB)、加密分组链接模式(...

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 <stdio.h>

#include <windows.h>

#include <wincrypt.h>

#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

//函数申明 www.2cto.com

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);

}

#ifndef _WIN32_WINNT

#define _WIN32_WINNT 0x0400

#endif

#include <stdio.h>

#include <windows.h>

#include <wincrypt.h>

#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);

}


作者 yincheng01
相关文章
最新文章
热点推荐