单片机MD5校验

MD5简介

MD5消息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,通过其不可逆的字符串变换计算,产生文件或字符串的MD5散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。

理论上,任意两个文件、字符串不会有相同的散列值。

MD5文件校验用途非常多,例如:游戏补丁包的校验,病毒文件确认,APP提审校验等;如果要确认某一个文件的完整性和正确性,都会使用MD5进行校验。

因此md5文件可以简单的理解为可以用于验证数据完整性的文件

在单片机当中,有些程序需要用到OTA远程升级,此时可以使用MD5校验算法来判断升级文件是否完整,避免造成死机。

文件介绍

my_md5.h

首先是对头文件的介绍,主要是几个关键宏定义,以及几个关键函数


#ifndef __MY_MD5__
#define __MY_MD5__
#include "string.h"
#include "stdio.h"
#include "stdint.h"


#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

#define RL(x, y) (((x) << (y)) | ((x) >> (32 - (y))))  

#define PP(x) (x<<24)|((x<<8)&0xff0000)|((x>>8)&0xff00)|(x>>24)  

#define FF(a, b, c, d, x, s, ac) a = b + (RL((a + F(b,c,d) + x + ac),s))
#define GG(a, b, c, d, x, s, ac) a = b + (RL((a + G(b,c,d) + x + ac),s))
#define HH(a, b, c, d, x, s, ac) a = b + (RL((a + H(b,c,d) + x + ac),s))
#define II(a, b, c, d, x, s, ac) a = b + (RL((a + I(b,c,d) + x + ac),s))


void md5_cal(void);
void md5_data_reset(void);
void md5_data_deal(unsigned long fileSize);
int get_flash_md5(unsigned int tart_addr, unsigned long size,char *result);


#endif

my_md5.C

#include "my_md5.h"
#include "register.h"
//#define APP2_ADDRESS_BEGIN	0x8020000
static unsigned int A=0x67452301,B=0xEFCDAB89,C=0x98BADCFE,D=0x10325476,a,b,c,d,flen[2],x[16]; 

unsigned char readDataBuf[1024];//定义暂时存储1K外部flash内bin文件

static unsigned int readTimes = 0;
static unsigned int dataIndex = 0;   //bin文件字符索引,固件bin文件大小不要超过65K


void md5_cal(void){                 //MD5主要计算

  a=A,b=B,c=C,d=D;

  FF (a, b, c, d, x[ 0],  7, 0xd76aa478); 
  FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); 
  FF (c, d, a, b, x[ 2], 17, 0x242070db); 
  FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); 
  FF (a, b, c, d, x[ 4],  7, 0xf57c0faf); 
  FF (d, a, b, c, x[ 5], 12, 0x4787c62a); 
  FF (c, d, a, b, x[ 6], 17, 0xa8304613); 
  FF (b, c, d, a, x[ 7], 22, 0xfd469501); 
  FF (a, b, c, d, x[ 8],  7, 0x698098d8); 
  FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); 
  FF (c, d, a, b, x[10], 17, 0xffff5bb1); 
  FF (b, c, d, a, x[11], 22, 0x895cd7be); 
  FF (a, b, c, d, x[12],  7, 0x6b901122); 
  FF (d, a, b, c, x[13], 12, 0xfd987193); 
  FF (c, d, a, b, x[14], 17, 0xa679438e); 
  FF (b, c, d, a, x[15], 22, 0x49b40821); 


  GG (a, b, c, d, x[ 1],  5, 0xf61e2562); 
  GG (d, a, b, c, x[ 6],  9, 0xc040b340); 
  GG (c, d, a, b, x[11], 14, 0x265e5a51); 
  GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); 
  GG (a, b, c, d, x[ 5],  5, 0xd62f105d); 
  GG (d, a, b, c, x[10],  9, 0x02441453); 
  GG (c, d, a, b, x[15], 14, 0xd8a1e681); 
  GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); 
  GG (a, b, c, d, x[ 9],  5, 0x21e1cde6); 
  GG (d, a, b, c, x[14],  9, 0xc33707d6); 
  GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); 
  GG (b, c, d, a, x[ 8], 20, 0x455a14ed); 
  GG (a, b, c, d, x[13],  5, 0xa9e3e905); 
  GG (d, a, b, c, x[ 2],  9, 0xfcefa3f8); 
  GG (c, d, a, b, x[ 7], 14, 0x676f02d9); 
  GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); 


  HH (a, b, c, d, x[ 5],  4, 0xfffa3942); 
  HH (d, a, b, c, x[ 8], 11, 0x8771f681); 
  HH (c, d, a, b, x[11], 16, 0x6d9d6122); 
  HH (b, c, d, a, x[14], 23, 0xfde5380c); 
  HH (a, b, c, d, x[ 1],  4, 0xa4beea44); 
  HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); 
  HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); 
  HH (b, c, d, a, x[10], 23, 0xbebfbc70); 
  HH (a, b, c, d, x[13],  4, 0x289b7ec6); 
  HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); 
  HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); 
  HH (b, c, d, a, x[ 6], 23, 0x04881d05); 
  HH (a, b, c, d, x[ 9],  4, 0xd9d4d039); 
  HH (d, a, b, c, x[12], 11, 0xe6db99e5); 
  HH (c, d, a, b, x[15], 16, 0x1fa27cf8); 
  HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); 


  II (a, b, c, d, x[ 0],  6, 0xf4292244); 
  II (d, a, b, c, x[ 7], 10, 0x432aff97); 
  II (c, d, a, b, x[14], 15, 0xab9423a7); 
  II (b, c, d, a, x[ 5], 21, 0xfc93a039); 
  II (a, b, c, d, x[12],  6, 0x655b59c3); 
  II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); 
  II (c, d, a, b, x[10], 15, 0xffeff47d); 
  II (b, c, d, a, x[ 1], 21, 0x85845dd1); 
  II (a, b, c, d, x[ 8],  6, 0x6fa87e4f); 
  II (d, a, b, c, x[15], 10, 0xfe2ce6e0); 
  II (c, d, a, b, x[ 6], 15, 0xa3014314); 
  II (b, c, d, a, x[13], 21, 0x4e0811a1); 
  II (a, b, c, d, x[ 4],  6, 0xf7537e82); 
  II (d, a, b, c, x[11], 10, 0xbd3af235); 
  II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); 
  II (b, c, d, a, x[ 9], 21, 0xeb86d391); 

  A += a;
  B += b;
  C += c;
  D += d;

}

void md5_data_reset()
{
	readTimes = 0;
	dataIndex = 0;

	A=0x67452301;
	B=0xefcdab89;
	C=0x98badcfe;
	D=0x10325476;
	a=0;
	b=0;
	c=0;
	d=0;
	memset(flen,0x00,sizeof(flen));
	memset(x,0x00,sizeof(x));
}

void md5_data_deal(unsigned long fileSize)
{
	unsigned short j = 0;
	unsigned short k = 0;	
	unsigned int sampleIndex = 0; //从TEST_data采集64位个字节

	
	memset(x,0,64);	
	sampleIndex = 0;
	for(j = 0;j < 16;j++)//fread(&x,4,16,fp) 以4字节为一组,共16组往x写入数据
	{
		for(k = 0;k < 4;k++)
		{
			if((readTimes >= fileSize/1024)&&(dataIndex >= fileSize%1024)) break;//当对最后一部分小于1K的bin文件处理
			
			((char*)x)[sampleIndex] = readDataBuf[dataIndex];
			dataIndex++;
			sampleIndex++;
		}
	}
}

int get_flash_md5(unsigned int start_addr, unsigned long size,char *result)
{
	unsigned short i = 0;
	
	md5_data_reset();
	
	unsigned int readAddr = 0;

	
	for(readTimes = 0;readTimes < size/1024;readTimes++)//对整K进行md5_cal计算
	{
		//读取flash 内容
		memset(readDataBuf,0,1025);
//		flash_read((u16 )(APP2_ADDRESS_BEGIN+readAddr),(u16 *)readDataBuf,1024);
		memcpy(readDataBuf,( uint32_t*)(start_addr+readAddr),1024);
//		register_data_read((u16 )(APP2_ADDRESS_BEGIN+readAddr),1024,(u16 *)readDataBuf);	
		readAddr += 1024;
		
		for(i = 0;i < 16;i++)//刚好对读出的1Kbin文件进行md5_cal计算 
		{
			md5_data_deal(size);
			md5_cal();	
		}
		dataIndex=0;
	}
	//处理最后一包
	memset(readDataBuf,0,1025);
	memcpy(readDataBuf,(uint32_t*)(start_addr+readAddr),size%1024);
//	register_data_read(start_addr,size%1024,(u16 *)readDataBuf);
	md5_data_deal(size);
	for(i = 0;i < (size%1024)/64;i++)
	{
		md5_cal();
		md5_data_deal(size);
	}
	((char*)x)[size%64]=128;//文件结束补1,0操作 10000000
	if(size%64>55) 
	{
		md5_cal(),memset(x,0,64);
	}
	flen[1]=size/0x20000000;   //转换二进制文件大小(byte->bit)
	flen[0]=(size%0x20000000)*8;
	
	
	memcpy(x+14,flen,8);
	md5_cal();	
	
	sprintf(result,"%08x%08x%08x%08x",PP(A),PP(B),PP(C),PP(D));
	if(strstr(result,(char *)current_register_data.g_remote_update_md5)!=0)
		return 1;
	else
		return 0;
	
}

受限于单片机的内存大小,选择1K来进行校验,如果最后一包不足1K则进行补足。、

程序当中只需要调用get_flash_md5()函数,传入需要读出寄存器的地址,寄存器的长度,以及输出的校验值,即可完成MD5校验。可以将该校验值与文件本身MD5校验值对比,如果一致可以进行升级,失败则重新升级

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值