基于51单片机MD5算法实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于51单片机MD5算法实现
2010-09-15 18:03
/*
**********************************************************************************************
* 文件名称:md5.h
* 作 者:曾光辉
* 版 本:
* 硬件平台:
* 软件平台:
* 说 明:
* 创建日期:2010-9-2
* 修改记录:
**********************************************************************************************
*/
#ifndef __MD5_H__
#define __MD5_H__
// 类型定义
#ifndef _TYPE
#define _TYPE
typedef unsigned char INT8U;
typedef unsigned int INT16U;
typedef unsigned long INT32U;
typedef double INT64U;
#endif
// 宏定义
/*md5转换用到的常量,算法本身规定的*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
/* 循环左移 */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
// 外部函数
void md5(INT8U* );
#endif
/*
**********************************************************************************************
* 文件名称:md5.c
* 作 者:曾光辉
* 版 本:
* 硬件平台:
* 软件平台:
* 说 明:本程序实现的是一种非规范md5算法。它不规范的地方在于有:
1)字符串的bit长度是8的整数倍,而不是任意的。2)字符串的bit长度被限制在0~65535之间。
* 创建日期:2010-9-1
* 修改记录:
**********************************************************************************************
*/
// 文件包含
#include"md5.h"
#include
#include
// 全局变量
INT32U xdata x[16];/*分组暂存区*/
INT32U xdata a,b,c,d;/*中间变量*/
INT32U xdata state[4];/*md5码*/
/*
**********************************************************************************************
* 函数名称:INT32U f();INT32U g();INT32U h();INT32U i();void ff();void gg();void hh();void ii()
* 函数功能:md5算法定义的函数
* 入口参数:
* 出口参数:
* 作 者:曾光辉
* 说 明:
* 创建日期:2010-9-2
* 修改记录:
**********************************************************************************************
*/
INT32U f(INT32U x,INT32U y,INT32U z)
{
return (x&y)|((~x)&z);
}
INT32U g(INT32U x,INT32U y,INT32U z)
{
return (x&z)|(y&(~z));
}
INT32U h(INT32U x,INT32U y,INT32U z)
{
return x^y^z;
}
INT32U i(INT32U x,INT32U y,INT32U z)
{
return y^(x|(~z));
}
// 第一轮运算函数
void ff(INT32U x,INT32U s,INT32U ac)
{
if(s==S11||s==S21||s==S31||s==S41){
a+=f(b,c,d)+x+ac;
a=ROTATE_LEFT(a,s);
a+=b;
}
if(s==S12||s==S22||s==S32||s==S42){
d+=f(a,b,c)+x+ac;
d=ROTATE_LEFT(d,s);
d+=a;
}
if(s==S13||s==S23||s==S33||s==S43){
c+=f(d,a,b)+x+ac;
c=ROTATE_LEFT(c,s);
c+=d;
}
if(s==S14||s==S24||s==S34||s==S44){
b+=f(c,
d,a)+x+ac;
b=ROTATE_LEFT(b,s);
b+=c;
}
}
// 第二轮运算函数
void gg(INT32U x,INT32U s,INT32U ac)
{
if(s==S11||s==S21||s==S31||s==S41){
a+=g(b,c,d)+x+ac;
a=ROTATE_LEFT(a,s);
a+=b;
}
if(s==S12||s==S22||s==S32||s==S42){
d+=g(a,b,c)+x+ac;
d=ROTATE_LEFT(d,s);
d+=a;
}
if(s==S13||s==S23||s==S33||s==S43){
c+=g(d,a,b)+x+ac;
c=ROTATE_LEFT(c,s);
c+=d;
}
if(s==S14||s==S24||s==S34||s==S44){
b+=g(c,d,a)+x+ac;
b=ROTATE_LEFT(b,s);
b+=c;
}
}
// 第三轮运算函数
void hh(INT32U x,INT32U s,INT32U ac)
{
if(s==S11||s==S21||s==S31||s==S41){
a+=h(b,c,d)+x+ac;
a=ROTATE_LEFT(a,s);
a+=b;
}
if(s==S12||s==S22||s==S32||s==S42){
d+=h(a,b,c)+x+ac;
d=ROTATE_LEFT(d,s);
d+=a;
}
if(s==S13||s==S23||s==S33||s==S43){
c+=h(d,a,b)+x+ac;
c=ROTATE_LEFT(c,s);
c+=d;
}
if(s==S14||s==S24||s==S34||s==S44){
b+=h(c,d,a)+x+ac;
b=ROTATE_LEFT(b,s);
b+=c;
}
}
// 第四轮运算函数
void ii(INT32U x,INT32U s,INT32U ac)
{
if(s==S11||s==S21||s==S31||s==S41){
a+=i(b,c,d)+x+ac;
a=ROTATE_LEFT(a,s);
a+=b;
}
if(s==S12||s==S22||s==S32||s==S42){
d+=i(a,b,c)+x+ac;
d=ROTATE_LEFT(d,s);
d+=a;
}
if(s==S13||s==S23||s==S33||s==S43){
c+=i(d,a,b)+x+ac;
c=ROTATE_LEFT(c,s);
c+=d;
}
if(s==S14||s==S24||s==S34||s==S44){
b+=i(c,d,a)+x+ac;
b=ROTATE_LEFT(b,s);
b+=c;
}
}
/*
**********************************************************************************************
* 函数名称:INT32U GetStrLen()
* 函数功能:获取字符串的长度
* 入口参数:ptr--字符串指针
* 出口参数:len--32位的返回值
* 作 者:曾光辉
* 说 明:原md5算法要求存储字符串长度的变量为64位,即8个字节。这里只用了4个字节,根据应用场合
的不同修改相应的变量定义及函数md5()中对x[14]x[15]的赋值语句即可。
* 创建日期:2010-9-1
* 修改记录:
**********************************************************************************************
*/
INT32U GetStrLen(INT8U xdata*data ptr)
{
INT32U xdata len=0;
INT8U xdata*data pTmp;
pTmp=ptr;
while(pTmp!=NULL&&(*pTmp)!='\0')
{
len++;
pTmp++;
}
return len;
}
/*
**********************************************************************************************
* 函数名称:void md5_ClearX()
* 函数功能:将分组暂存器x[]清零
* 入口参数:
* 出口参数:
* 作 者:曾光辉
* 说 明:
* 创建日期:2010-9-1
* 修改记录:
**********************************************************************************************
*/
void md5_ClearX()
{
INT8U data i;
for(i=0;i<16;i++)
{
x[i]=0x00000000;
}
}
/*
**********************************************************************************************
* 函数名称:void ByteToWord()
* 函数功能:将指定8位字符串整合为一个个32位的字,存入分组暂存器x[]中,字的个数由用户指定
* 入口参数:*ptr--8位
字符串指针 n--指定的字的个数
* 出口参数:全局x[]
* 作 者:曾光辉
* 说 明:用户需在调用此函数之前先获得字符串的长度,然后再确定有效的“n”值。例如,当字符串
长度为7时,不能指定n为2或更大的数,即不能这样调用 ByteToWord(ptr,2)。
* 创建日期:2010-9-1
* 修改记录:
**********************************************************************************************
*/
void ByteToWord(INT8U xdata*data ptr,INT8U n)
{
INT8U data i,j;
INT8U xdata*data pTmp;
//INT32U xdata tmp=0x00000000;
pTmp=ptr;
for(i=0;i
x[i]=0x00000000;
for(j=0;i<4;j++)
{
x[i]+=*pTmp;
x[i]=x[i]>>8;
pTmp++;
}
}
}
/*
**********************************************************************************************
* 函数名称:void md5_Print()
* 函数功能:输出md5的结果
* 入口参数:
* 出口参数:
* 作 者:曾光辉
* 说 明:
* 创建日期:2010-9-1
* 修改记录:
**********************************************************************************************
*/
void md5_Print()
{
INT8U i;
for(i=0;i<4;i++)
{
printf("%02bx",(INT8U)state[i]);
printf("%02bx",(INT8U)(state[i]>>8));
printf("%02bx",(INT8U)(state[i]>>16));
printf("%02bx",(INT8U)(state[i]>>24));
}
}
/*
**********************************************************************************************
* 函数名称:void md5_ProChunk()
* 函数功能:md5分组处理
* 入口参数:
* 出口参数:
* 作 者:曾光辉
* 说 明:
* 创建日期:2010-9-1
* 修改记录:
**********************************************************************************************
*/
void md5_ProChunk()
{
a=state[0];
b=state[1];
c=state[2];
d=state[3];
/* 第一轮运算 */
ff(x[ 0], S11, 0xd76aa478); /* 1 */
ff(x[ 1], S12, 0xe8c7b756); /* 2 */
ff(x[ 2], S13, 0x242070db); /* 3 */
ff(x[ 3], S14, 0xc1bdceee); /* 4 */
ff(x[ 4], S11, 0xf57c0faf); /* 5 */
ff(x[ 5], S12, 0x4787c62a); /* 6 */
ff(x[ 6], S13, 0xa8304613); /* 7 */
ff(x[ 7], S14, 0xfd469501); /* 8 */
ff(x[ 8], S11, 0x698098d8); /* 9 */
ff(x[ 9], S12, 0x8b44f7af); /* 10 */
ff(x[10], S13, 0xffff5bb1); /* 11 */
ff(x[11], S14, 0x895cd7be); /* 12 */
ff(x[12], S11, 0x6b901122); /* 13 */
ff(x[13], S12, 0xfd987193); /* 14 */
ff(x[14], S13, 0xa679438e); /* 15 */
ff(x[15], S14, 0x49b40821); /* 16 */
/* 第二轮运算 */
gg(x[ 1], S21, 0xf61e2562); /* 17 */
gg(x[ 6], S22, 0xc040b340); /* 18 */
gg(x[11], S23, 0x265e5a51); /* 19 */
gg(x[ 0], S24, 0xe9b6c7aa); /* 20 */
gg(x[ 5], S21, 0xd62f105d); /* 21 */
gg(x[10], S22, 0x2441453); /* 22 */
gg(x[15], S23, 0xd8a1e681); /* 23 */
gg(x[ 4], S24, 0xe7d3fbc8); /* 24 */
gg(x[ 9], S21, 0x21e1cde6); /* 25 */
gg(x[14], S22, 0xc33707d6); /* 26 */
gg(x[ 3], S23, 0xf4d50d87); /* 27 */
gg(x[ 8], S24, 0x455a14ed); /* 28 */
gg(x[13], S21, 0xa9e3e905); /* 29 */
gg(x[ 2], S22, 0xfcefa3f8); /* 30 */
gg(x[ 7], S23, 0x676f02d9); /* 31 */
gg(x[12], S24, 0x8d2a4c8a); /* 32 */
/* 第三轮运算 */
hh(x[ 5], S31, 0xfffa3942); /* 33 */
hh(x[ 8], S32, 0x8771f681); /* 34 */
hh(x[11], S33, 0x6d9d6122); /* 35 */
hh(x[14], S34, 0xfde5380c); /* 36 */
hh(x[ 1], S31, 0xa4beea44); /* 37 */
hh(x[ 4], S32, 0x4bdecfa9); /* 38 */
hh(x[ 7], S33, 0xf6bb4b60); /* 39 */
hh(x[10], S34, 0xbebfbc70); /* 40 */
hh(x[13], S31, 0x289b7ec6); /* 41 */
hh(x[ 0], S32, 0xeaa127fa); /* 42 */
hh(x[ 3], S33, 0xd4ef3085); /* 43 */
hh(x[ 6], S34, 0x4881d05); /* 44 */
hh(x[ 9], S31, 0xd9d4d039); /* 45 */
hh(x[12], S32, 0xe6db99e5); /* 46 */
hh(x[15], S33, 0x1fa27cf8); /* 47 */
hh(x[ 2], S34, 0xc4ac5665); /*48 */
/* 第四轮运算 */
ii(x[ 0], S41, 0xf4292244); /* 49 */
ii(x[ 7], S42, 0x432aff97); /* 50 */
ii(x[14], S43, 0xab9423a7); /* 51 */
ii(x[ 5], S44, 0xfc93a039); /* 52 */
ii(x[12], S41, 0x655b59c3); /* 53 */
ii(x[ 3], S42, 0x8f0ccc92); /* 54 */
ii(x[10], S43, 0xffeff47d); /* 55 */
ii(x[ 1], S44, 0x85845dd1); /* 56 */
ii(x[ 8], S41, 0x6fa87e4f); /* 57 */
ii(x[15], S42, 0xfe2ce6e0); /* 58 */
ii(x[ 6], S43, 0xa3014314); /* 59 */
ii(x[13], S44, 0x4e0811a1); /* 60 */
ii(x[ 4], S41, 0xf7537e82); /* 61 */
ii(x[11], S42, 0xbd3af235); /* 62 */
ii(x[ 2], S43, 0x2ad7d2bb); /* 63 */
ii(x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
/*
**********************************************************************************************
* 函数名称:void md5(INT8U* ptr)
* 函数功能:计算md5
* 入口参数:
* 出口参数:
* 作 者:曾光辉
* 说 明:
* 创建日期:2010-9-1
* 修改记录:
**********************************************************************************************
*/
void md5(INT8U* ptr)
{
INT32U xdata len,xdata len1;
INT8U xdata*data pTmp;
INT8U xdata n,m;
pTmp=ptr;
len=GetStrLen(pTmp);//获取字符串长度
len1=len;
state[0]=0x67452301;
state[1]=0xefcdab89;
state[2]=0x98badcfe;
state[3]=0x10325476;
// 功能0:处理不需要补位的完整分组
while((len/64)>0)
{
md5_ClearX();//由于ByteToWord()用的是循环移位,如果不清零x[]的话可能会产生错误,所以此处要清零
ByteToWord(pTmp,16);//将分组转换到x[]中
md5_ProChunk();//分组处理
len-=64;//处理完一个分组后,未进行处理的分组长度要减去64 Byte(512 bit)
pTmp+=64;//指向下一个分组
}
// 功能0
// 功能1:处理需要进行补位的分组
md5_ClearX();
ByteToWord(pTmp,len/4);//字符串转换成字存入x[]
// 功能1.0 将多余的字节组合进下一个字并进行补位后存入x[]
n=len%4;
m=len/4;
switch(n)
{
case 0:
x[m]=x[m]|0x00000080;//多余0字节的情况
break;
case 1:
x[m]=*pTmp;
x[m]=x[m]|0x00008000;//多余1字节的情况
break;
case 2:
x[m]=*(pTmp+1);
x[m]=x[m]<<8;
x[m]=x[m]+(*pTmp);
x[m]=x[m]|0x00800000;//多余2字节的情况
break;
case 3:
x
[m]=*(pTmp+2);
x[m]=x[m]<<8;
x[m]=x[m]+*(pTmp+1);
x[m]=x[m]<<8;
x[m]=x[m]+(*pTmp);
x[m]=x[m]|0x80000000;//多余3字节的情况
default:;
}
// 功能1.0
if(len>=56)//当此分组的长度大于等于56时需多处理一个分组
{
md5_ProChunk();
md5_ClearX();
}
x[14]=len1*8;//添加字符串‘位’长度信息
//x[15]..
md5_ProChunk();
// 功能1
md5_Print();//输出结果
}