Openssl入门第二课--引用openssl lib搭建SHA256做计算

文章详细介绍了如何在VisualStudio2012环境下配置OpenSSL库,包括设置包含目录和附加依赖项,以及如何进行32位和64位平台的配置。接着,文章讲解了SHA256哈希函数的计算逻辑,并提供了两种计算方法:单次计算和多次计算。在多次计算中,重点阐述了SHA256_Init、SHA256_Update和SHA256_Final函数的作用。最后,通过代码示例展示了如何使用OpenSSL库进行SHA256哈希计算,并给出了计算结果。
摘要由CSDN通过智能技术生成

背景:在Visual Studio项目中使用OpenSSL库:

1. 环境准备

1.1 openssl编译或者安装后,获得的库文件(.lib)和头文件(.h)

1.2 VS2012

要点:编译出来的lib是32位的话,将VS的环境配置为x86;引用的lib是64位的话,将VS环境配置为X64.

创建X64平台方案,如图所示:

创建X86平台方案,如图所示:

2. 项目配置
2.1包含目录设置:
打开项目属性 -> VC++ 目录 -> 包含目录 -> 编辑 -> 添加你的OpenSSL头文件路径和库文件路径

2.2 附加依赖项和附加库目录设置:
打开项目属性 -> 链接器 -> 输入 -> 附加依赖项 -> 编辑 -> 添加libssl.lib和libcrypto.lib(以及其他需要的库)。

3. 实例

背景知识:在做SHA256计算之前,我们需要知道HASH计算的逻辑。

SHA256是一种密码散列函数,属于SHA-2(安全散列算法 2)家族,是SHA-1的后继者,SHA 256算法的主要过程包括预处理、主循环以及输出处理。

在预处理阶段,首先将原始数据以512位为一组进行分组,如果原始数据的位数不是512的倍数,则需要在原始数据的末尾填充若干个0,使其长度是512的倍数,并在其后附加一个64位的原始数据长度值。

接着进行64轮迭代运算,每轮迭代运算会对16个32位字进行一系列位运算,这些位运算主要包括循环右移、异或、与、或、非、加等。最后,将64轮迭代运算的结果进行拼接,得到一个256位的哈希值,即SHA256摘要。

使用openssl计算SHA256,主要有两种方案:

方案一,单次计算

使用API unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md) 做单次计算。

使用该方案计算SHA256,只允许输入一次数据const unsigned char *d,计算出来的SHA256的值存储到MD指针中。

方案二,多次计算

使用组合API SHA256_Init(SHA256_CTX *c) + SHA256_Update(SHA256_CTX *c,const void *data, size_t len) + SHA256_Final(unsigned char *md, SHA256_CTX *c) 做多次计算。

使用该方案计算SHA256,允许多次使用SHA256_Update传递被计算数据,理论来说被计算数据没有极限。

SHA256_Init(SHA256_CTX *c)

函数的作用主要是用于初始化一个SHA256_CTX结构体。在SHA-256算法的实现中,SHA256_CTX结构体用于保存SHA-256计算的状态。通过调用SHA256_Init函数,可以对这个结构体进行初始化,为后续的计算过程做准备。

SHA256_Update(SHA256_CTX *c, const void *data, size_t len)

函数在SHA-256哈希算法的计算过程中起到了关键的作用。该函数的主要功能是将输入的数据块添加到SHA256的计算上下文中,以更新当前的哈希值。

具体来说,参数 SHA256_CTX *c 是一个指向SHA256上下文的指针,这个上下文在SHA256_Init函数中已经被初始化,并包含了计算哈希值所需的所有状态信息。参数 const void *data 是一个指向要添加的数据的指针,这些数据可以是任意长度的字节序列。参数 size_t len 表示数据的长度。

SHA256_Update函数会按照SHA-256算法的规定,对输入的数据进行处理,并更新SHA256上下文中的状态。这样,随着数据的不断输入,SHA256的哈希值也会不断更新。

最后,当所有的数据都处理完毕后,可以通过调用SHA256_Final函数来获取最终的哈希值。这个函数会将SHA256上下文中的最终状态转换为固定长度的哈希值输出。

因此,SHA256_Update函数在SHA-256哈希计算中起到了“逐步更新”的作用,使得我们可以分块处理大量的数据,而不需要一次性将所有数据加载到内存中。这对于处理大文件或流式数据非常有用。

SHA256_Final(unsigned char *md, SHA256_CTX *c)

函数在SHA-256哈希计算中扮演着关键角色。这个函数的主要作用是完成SHA-256哈希计算,并将最终的哈希值存储在指定的缓冲区中

参数unsigned char *md是一个指向存储哈希结果的缓冲区的指针,该缓冲区的大小应足够大,以存储生成的256位(32字节)哈希值。参数SHA256_CTX *c是一个指向SHA256_CTX结构体的指针,该结构体包含了哈希计算过程中所需的所有状态信息,包括中间结果。

在调用SHA256_Final函数之前,通常需要先调用SHA256_Init函数来初始化SHA256_CTX结构体,然后通过SHA256_Update函数将待哈希的数据添加到计算中。SHA256_Update函数可以多次调用,以处理不同部分的数据。当所有数据都已处理完毕,就可以调用SHA256_Final函数来生成最终的哈希值。

SHA256_Final函数会将SHA256_CTX结构体中的状态信息转化为最终的哈希值,并将这个哈希值存储在md指向的缓冲区中。完成这个操作后,SHA256_CTX结构体中的状态信息将被清除或重置,因此无法再次使用它来生成哈希值。

3.1 方案一

SHA256((const unsigned char *)buf_Input, (size_t)32, md); 计算Buf_input内的32个字节的SHA256的值。

3.2  方案二

 SHA256_Init(&sha256);  
 SHA256_Update(&sha256, buf_Input, strlen((char *)buf_Input));   
  SHA256_Final(buf_HASH, &sha256);

注意SHA256_Update 需要输入实际传递进来的数据长度,需要使用strlen((char *)buf_Input)去计算,但是strlen计算的逻辑是遇到截止符"\0"才截止。所以在前面我们使用下面三种方案使buf_Input 计算出来的长度为32。

buf_Input = (unsigned char *)malloc(33);
 memset(buf_Input,0xff,32);
 buf_Input[32] = '\0';

反之,如果使用sizeof计算的是内存的大小。buf_Input 本质是一个指针,占用8字节的长度。

#include <string.h>
#include<stdio.h>
#include <openssl/sha.h> 
#include <openssl/crypto.h> 
#include <openssl/applink.c>

 
 
void printHash(unsigned char *md, int len)
{
 
	int i = 0;
    for (i = 0; i < len; i++)
	{
		printf("%02x", md[i]);
	}
 
	printf("\n");
}
 
int main()
{
	unsigned char *buf_HASH;   
	unsigned char *buf_Input,buf_Test[32];
	FILE *buf_Input_file;
	//对数据进行sha256算法摘要
	SHA256_CTX sha256;  
	unsigned char md[SHA256_DIGEST_LENGTH];
	buf_HASH = (unsigned char *)malloc(32);
    buf_Input = (unsigned char *)malloc(33);
	memset(buf_HASH,0xff,32);
	memset(buf_Input,0xff,32);
	buf_Input[32] = '\0';

	if((buf_Input_file = fopen("D:\\Coding\\C\\Openssl_test\\05_Sign_Verify_RSA\\05_Sign_Verify_RSA\\Wait_sign.bin","rb")) ==NULL)
	{
	printf("read Wait_sign.bin failure:\n");
	}
	else
	{
	fread(buf_Input,sizeof(unsigned char),32,buf_Input_file);
	fclose(buf_Input_file);
	}

	printf("read start:\n");
	printHash(buf_Input, SHA256_DIGEST_LENGTH);
	printf("read end:\n");
 
	SHA256((const unsigned char *)buf_Input, (size_t)32, md);
	printf("Hash start:\n");
	printHash(md, SHA256_DIGEST_LENGTH);
	printf("Hash end:\n");

	//不能用这种方式去计算开辟的空间长度,因为会出现内存开辟的内存空间正好有连续字节。注意strlen函数的原理是计算NULL
	/****strlen 函数用于计算 C 风格字符串(以 null 终止符 \0 结尾的字符数组)的长度。当你调用 strlen((char *)buf_Input) 时,
	你期望它返回的是从 buf_Input 指向的内存位置开始,直到遇到第一个 null 终止符的字符数。
	如果你发现 strlen((char *)buf_Input) 返回了 37,那么这意味着从 buf_Input 指向的内存开始,连续有 37 个非 null 字符,直到第 38 个位置才遇到 null 终止符。****/
	printf("strlen((char *)buf_Input) = %d %d:\n",strlen((char *)buf_Input),strlen((unsigned char *)buf_Input)); 
    SHA256_Init(&sha256);  
    SHA256_Update(&sha256, buf_Input, strlen((char *)buf_Input));   
    SHA256_Final(buf_HASH, &sha256);

	printf("SHA256_Init start:\n");
	printHash(buf_HASH, SHA256_DIGEST_LENGTH);
	printf("SHA256_Final end:\n");


	/****sizeof(buf_Input) = 8是因为sizeof是计算内存的大小,buf_Input本质是一个指针,X64架构下就是8字节***/
	memset(buf_HASH,0xff,32);
	printf("sizeof(buf_Input) = %d %d:\n",sizeof(buf_Input),sizeof(buf_Test)); 
    SHA256_Init(&sha256);  
    SHA256_Update(&sha256, buf_Input, sizeof(buf_Input));   
    SHA256_Final(buf_HASH, &sha256);

	printf("SHA256_Init start 2:\n");
	printHash(buf_HASH, SHA256_DIGEST_LENGTH);
	printf("SHA256_Final end 2:\n");


	free(buf_HASH);
	free(buf_Input);
	
    return 0;
}

附上测试结果:

read start:
4bdfd80bbed10d6d7a9bc0f8e199b35c08b3d79ad0e00210f5e6c7f32fbe08df
read end:
Hash start:
97f40ff3243630b2c9e37bf0c80349d1f74240ceaac61f0c1fa7ad0a93c1d7da
Hash end:
strlen((char *)buf_Input) = 32 32:
SHA256_Init start:
97f40ff3243630b2c9e37bf0c80349d1f74240ceaac61f0c1fa7ad0a93c1d7da
SHA256_Final end:
sizeof(buf_Input) = 8 8:
SHA256_Init start 2:
51dec461be3996751ab5ed7beb2731fc5dfcdbec6d04a0d598668970140e6e95
SHA256_Final end 2:
请按任意键继续. . .

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值