HASH256开源代码计算错误问题

计算量超500KB报错

OTA升级中可能会涉及到CRC、hash校验等算法,小编从网上抄到了HASH256的源码,拿来使用的时候却发现了一个问题,当源文件约大于500KB的时候会发现其计算出的hash值出现错误。

经过实际测试得知,当源文件大于约500kb时,用开源代码计算的hash值存在概率不正确的情况,而且发现其源文件大小/8byte为整数时计算出的结果是正确的(如下图计算出来的就是错误的)。

本着快速解决项目问题的想法,想到了将源文件大小补齐/8byte为整数的操作。(实际是小编暂时没能力找到问题所在哈哈哈)

若大家有更好的解决办法请指出~

代码片(.C)

c 复制代码
/*
 * @Description: 
 * @Author: shimianxiang
 * @Date: 2023-10-11 08:27:06
 * @LastEditTime: 2023-10-25 11:28:06
 * @LastEditors: shimianxiang
 */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "mcuhash2.h"
#include<time.h>
#include <math.h>

uint32_t    TW[16];
uint8_t     bitbuff[512/8];
uint32_t    bitbuff_num=0;

uint32_t    fill_data[64]={ 0x80000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000,
                0x00000000, 0x00000000, 0x00000000, 0x00000000 };

uint32_t    data[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
				0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
				0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
				0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
				0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
				0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
				0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
				0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
				0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
				0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
				0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
				0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
				0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
				0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
				0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
				0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
/*-----------------------------------------------------------------------SHA-256-------------------------------------------------------*/
uint32_t Ch(uint32_t x, uint32_t y, uint32_t z)
{
	return (x & y) ^ (~x & z);
}
uint32_t cycle_rshift(uint32_t x,uint32_t n)
{
	return 	((x & (((uint32_t)1 << n) - 1)) << (32 - n))|(x >> n);
}
uint32_t Sum0(uint32_t x)
{
	return cycle_rshift(x, 2) ^ cycle_rshift(x, 13) ^ cycle_rshift(x, 22);
}
uint32_t Sum1(uint32_t x)
{
	return cycle_rshift(x, 6) ^ cycle_rshift(x, 11) ^ cycle_rshift(x, 25);
}
uint32_t Sigma0(uint32_t x)
{
	return cycle_rshift(x, 7) ^ cycle_rshift(x, 18) ^ (x>>3);
}
uint32_t Sigma1(uint32_t x)
{
	return cycle_rshift(x, 17) ^ cycle_rshift(x, 19) ^ (x >> 10);
}
uint32_t Ma(uint32_t x, uint32_t y, uint32_t z)
{
	return (x & y) ^ (x & z)^ (y & z);
}
void sha_init(struct sha256 *s)
{
	s->hash[0] = H0;
	s->hash[1] = H1;
	s->hash[2] = H2;
	s->hash[3] = H3;
	s->hash[4] = H4;
	s->hash[5] = H5;
	s->hash[6] = H6;
	s->hash[7] = H7;
	s->hash_length = 0;
	s->index  = 0;
	s->offset = 0;
}

void sha_caculator(struct sha256* s)//先补齐 Wt,然后循环64次加密
{
	uint8_t i = 0;
	uint32_t m0, s0, s1,c1,t1;

	uint32_t temp[8];
	for(i=0;i<8;i++)
		temp[i]=s->hash[i];

	for (i = 0; i < 16; i++)
		Wt[i] = s->block[i];

	for (i = 16; i < 64; i++)
		Wt[i] = Sigma1(Wt[i-2])+ Wt[i-7]+Sigma0(Wt[i - 15])+ Wt[i - 16];
	
	for (i = 0; i < 64; i++)
	{
		s0 = Sum0(temp[0]);

		s1 = Sum1(temp[4]);

		m0 = Ma(temp[0], temp[1], temp[2]);

		c1 = Ch(temp[4], temp[5], temp[6]);

		t1 = s1+c1+temp[7]+Wt[i] + Kt[i];

		temp[7] = temp[6];
		temp[6] = temp[5];
		temp[5] = temp[4];
		temp[4] = temp[3]+ t1;
		temp[3] = temp[2];
		temp[2] = temp[1];
		temp[1] = temp[0];
		temp[0] = t1+m0+s0;
	
	}

	for (i = 0; i < 8; i++)
		s->hash[i]+=temp[i];
}

void sha_updata(struct sha256* s,unsigned char *str,uint64_t len)
{
	uint64_t i = 0;
	uint64_t count;
	s->hash_length += len;
	if (s->offset!=0)//说明没有4字节对齐
	{
		if (s->offset + len < 4)
		{
			for (i = s->offset; i < s->offset+len; i++)
			{
				s->block[s->index]  |= (((uint32_t)(*str)) << (8 * (3 - i)));
				str++;
			}
			s->offset += len;
			return;
		}
		else
		{
			len = len + s->offset - 4;
			for (i = s->offset; i < 4; i++)
			{
				s->block[s->index]  |= (((uint32_t)(*str)) << (8 * (3 - i)));
				str++;
			}
			s->index++;
			if (s->index == 16)
			{
				sha_caculator(s);//满足512bit 16Word加密一次
				s->index = 0;
			}
		}
	}
	count = (len >> 2);//计算这次加密有多少个Word
	s->offset = len % 4;//对齐Word剩余的byte


	for(i=0;i<count;i++)
	{

		s->block[s->index] = (((uint32_t)(*str))		<< 24) |
								((*(str	+	1))		<< 16) |
								((*(str + 2))	<< 8) |
								(*(str + 3));
		s->index++;

		str += 4;

		if (s->index == 16)
		{
			sha_caculator(s);//满足512bit 16Word加密一次
			s->index = 0;
		}
	}


	s->block[s->index] = 0;//对齐Word剩余的byte写在 s->index 位置上,供下一次update使用

	for (i = 0; i < s->offset; i++)
	{
		s->block[s->index] |= (((uint32_t)(*str)) << (8 * (3 - i)));
		str++;
	}
	
}

void sha_final(struct sha256* s)
{
	uint8_t temp=s->hash_length % 64;//计算需要填充多少byte
	uint8_t fill[4] = { 0x80,0x0,0x0,0x0 };
	uint32_t i;
	if (temp == 56)//则需要填充一个512bit
	{
		//补齐前一次的512bit
		if (s->offset != 0)
		{
			for (i = 0; i < 4-s->offset; i++)
			s->block[s->index]  |= (fill[i]<< (8 * (3 - i-s->offset)));

			s->index++;
		}
		else
		{
			s->block[s->index] = 0x80000000;
			s->index++;
		}
		for (i = s->index; i < 16; i++)
			s->block[i] = 0;

		sha_caculator(s);

	
		for(i=0;i<14;i++)
		s->block[i] = 0;

		s->block[14] = s->hash_length >> 29;
		s->block[15] = s->hash_length << 3 & 0xffffffff;
		sha_caculator(s);

	}
	else
	{
		if (s->offset != 0)
		{
			for (i = 0; i < 4-s->offset; i++)
				s->block[s->index]  |= (fill[i] << (8 * ( 3 - i - s->offset)));

			s->index++;
		}
		else
		{
			s->block[s->index] = 0x80000000;
			s->index++;
		}
		for (i = s->index; i < 14; i++)
			s->block[i] = 0;
		s->block[14] = s->hash_length>> 29;
		s->block[15] = s->hash_length<<3 & 0xffffffff;
		sha_caculator(s);
	}
}
/*-----------------------------------------------------------------------sort-------------------------------------------------------*/
uint32_t FlashASH_256(uint8_t *outdata,uint8_t *data,uint32_t length)
{
    uint32_t bitnum         = (length+bitbuff_num) % 64;
    uint32_t hash_times     = (length+bitbuff_num)/64;
    uint32_t offset_num     = 0;
    uint32_t bitbuff_num_or = 0;
    while (hash_times)
    {
        if(bitbuff_num == 0)
        {
            memcpy(&outdata[0],&data[0]+64*offset_num+bitbuff_num_or,64);
            hash_times--;
            offset_num++;
            // for(int i=0;i<4;i++)
            // {
            //     printf("%x   %x   %x   %x   ",TW[i*4+0],TW[i*4+1],TW[i*4+2],TW[i*4+3]);
            // }
            // printf("\n-----------------\n");
        }
        else
        {
            bitbuff_num_or = 64-bitbuff_num;
            memcpy(&outdata[0],&bitbuff[0],bitbuff_num);
            memcpy(&outdata[0]+bitbuff_num,&data[0]+64*offset_num,bitbuff_num_or);
            // memcpy(&outdata[0]+1,&data[0]+64*offset_num,bitbuff_num_or);
            hash_times--;
            bitbuff_num = 0;
            // for(int i=0;i<4;i++)
            // {
            //     printf("%x   %x   %x   %x   ",TW[i*4+0],TW[i*4+1],TW[i*4+2],TW[i*4+3]);
            // }
            // printf("\n+----------------\n");
        }

    }

    if(bitnum != 0)
    {
        memcpy(&bitbuff[0]+bitbuff_num,&data[0]+64*offset_num+bitbuff_num_or,bitnum);
        bitbuff_num = bitnum;
        // printf("\n get %d\n",bitnum);
        bitnum = 0;
    }
    else
    {
        bitbuff_num = 0;
    }
    return bitbuff_num;
}

int main(int argc, char const *argv[])
{
    printf("start \n");
    #if 0
    for(int i=1;i<16;i++)
    {
        TW[i]=0xffffffff+i;
    }
    uint8_t* inaddr_end=&fill_data[0];
    uint8_t* inaddr=&data[0];
    // memcpy(&TW[0],&Kt[0],65);
    FlashASH_256(&TW[0],&inaddr[0],120);
    FlashASH_256(&TW[0],&inaddr[120],1);
    FlashASH_256(&TW[0],&inaddr[121],4);
    FlashASH_256(&TW[0],&inaddr[125],35);
    uint32_t num=FlashASH_256(&TW[0],&inaddr[160],36);
    // FlashASH_256(&Kt[0]+129,63);
    FlashASH_256(&TW[0],&inaddr_end[0],(uint32_t)64-num);
    printf("last_num= %d\n",num);
    #elif 0
    FILE *fp = fopen("./tesths.c", "rb");
      if(fp == NULL)
    {
      printf("can not open file\n");
      return -1;
    }
    fseek(fp, 0, SEEK_END);
 
    uint32_t size = ftell(fp);
    char encrypt[1024*1024];

    fseek(fp, 0, SEEK_SET);
    printf("\n size: %d \n",size);
    int len = fread(encrypt, sizeof(char), size, fp);
    fclose(fp);

   	struct sha256 testsha;
    // uint8_t* inaddr=&data[0];
	sha_init(&testsha);
    sha_updata(&testsha, &encrypt[0], size);

	sha_final(&testsha);

	for (int i = 0; i < 8; i++)
		printf("%08x ", testsha.hash[i]);
	printf("\n");
    /* 验证通过 */
    #elif 1
    clock_t start,end;
FILE *fp2 = fopen("./dest_hash.bin", "w");
if(fp2 == NULL)
{
    printf("can not mkdir file\n");
    return -1;
}
fclose(fp2);
FILE *fp3 = fopen("./dest_hash.bin", "rb+");
    FILE *fp = fopen("./source.bin", "rb+");
      if(fp == NULL)
    {
      printf("can not open file\n");
      return -1;
    }
    fseek(fp, 0, SEEK_END);
 
    uint32_t size = ftell(fp);
    char encrypt[1024*1024];
	uint8_t* size_u8 = &size;
	/*如果源文件大小除8byte除不尽*/
	uint8_t buding=size%8;
	if(buding != 0)
	{
		buding = 8 - buding;
	}

    fseek(fp, 0, SEEK_SET);
    printf("size of bin: %d &add length=%d\n",size,size + 32);
    int len = fread(encrypt, sizeof(char), size, fp);

	size = buding + size;
    
   	struct sha256 testsha;
    // uint8_t* inaddr=&data[0];
	sha_init(&testsha);
    start=clock();
    sha_updata(&testsha, &encrypt[0], size);
    // sha_updata(&testsha, &encrypt[size/2], size/2);
    // sleep(2);
	sha_final(&testsha);
    end=clock();
    float time=(float)(end-start);
    printf("time=%lf ms\n",time);
	
fseek(fp3, 0, SEEK_END);

fwrite(encrypt, sizeof(char), size, fp3);
/* 文件结尾hash值输出开关 */
#if 1
/* 大小端切换开关 */
#if 0
    // fseek(fp3, size + 4, SEEK_SET);
    printf("write hash num byte=%d\nHASH:\n",fwrite(testsha.hash, sizeof(char), 32, fp3));
    fclose(fp);
	fclose(fp3);
#else
    uint8_t* hashfinal = &testsha.hash[0];
    // fseek(fp, size, SEEK_SET);
    int i,k;
    for(i=0;i<8;i++)
    for(k=0;k<4;k++)
    fwrite(&hashfinal[i*4+(3-k)], sizeof(char), 1, fp3);
    printf("write hash num byte=32\nHASH:\n");
    
#endif


fclose(fp3);
#else
fwrite(encrypt, sizeof(char), size, fp3);
    fclose(fp);
	fclose(fp3);
#endif

	for (int i = 0; i < 8; i++)
		printf("%08x ", testsha.hash[i]);
	printf("\nhash_finish!\n");

    // system("pause");
    /* 验证通过 */
    #elif 1
    
    struct sha256 testsha;
    
    uint8_t* inaddr_end=&fill_data[0];
    uint8_t* inaddr=&data[0];
    // memcpy(&TW[0],&Kt[0],65);
    sha_init(&testsha);
    // FlashASH_256(&testsha.block[0],&inaddr[0],14);
    uint32_t num=FlashASH_256(&testsha.block[0],&inaddr[0],14);
    // FlashASH_256(&Kt[0]+129,63);
    sha_caculator(&testsha);
    	for (int i = 0; i < 8; i++)
		printf("%08x ", testsha.hash[i]);
	printf("\n");

    // FlashASH_256(&TW[0],&inaddr_end[0],(uint32_t)64-num);
    // printf("last_num= %d\n",num);
    #endif

    return 0;
}

代码片(.H)

c 复制代码
/*
 * @Description: 
 * @Author: shimianxiang
 * @Date: 2023-10-11 09:27:35
 * @LastEditTime: 2023-10-12 13:33:24
 * @LastEditors: shimianxiang
 */

#ifndef HASHASH256_H_
#define HASHASH256_H_

#define H0  0x6a09e667
#define H1  0xbb67ae85
#define H2  0x3c6ef372
#define H3  0xa54ff53a
#define H4  0x510e527f
#define H5  0x9b05688c
#define H6  0x1f83d9ab
#define H7  0x5be0cd19
uint32_t Wt[64];
uint32_t Kt[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
				0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
				0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
				0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
				0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
				0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
				0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
				0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
				0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
				0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
				0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
				0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
				0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
				0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
				0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
				0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
struct sha256
{
	uint32_t block[16];	//加密的measage
	uint32_t hash[8];	//hash的结果
	uint64_t hash_length;//总共hash的byte数
	uint8_t  offset;		//一个update未对齐Word(4字节)的字节数
	uint8_t  index;		//当前已经写到block的位置
};
#endif
相关推荐
人才程序员4 小时前
QML z轴(z-order)前后层级
c语言·前端·c++·qt·软件工程·用户界面·界面
w(゚Д゚)w吓洗宝宝了4 小时前
C vs C++: 一场编程语言的演变与对比
c语言·开发语言·c++
爱吃西瓜的小菜鸡10 小时前
【C语言】抽空洗澡
c语言·开发语言·学习·算法
encoconut10 小时前
动态内存管理
c语言
人才程序员15 小时前
【无标题】
c语言·前端·c++·qt·软件工程·qml·界面
思麟呀17 小时前
在C语言基础上的C++第一章(基础的输入输出和动态内存开辟)
c语言·c++·学习
小林熬夜学编程19 小时前
【Linux网络编程】第十三弹---构建HTTP响应与请求处理系统:从HttpResponse到HttpServer的实战
linux·运维·服务器·c语言·网络·c++·http
misty youth19 小时前
学生信息管理系统
c语言·数据结构·算法·c#
人才程序员21 小时前
Qt Widgets、QML与Qt Quick
c语言·开发语言·c++·qt·ui·qml
LabVIEW开发21 小时前
LabVIEW中什么和C 语言指针类似?
c语言·开发语言·labview