本帖最后由 哒哒哒 于 2019-9-4 18:05 编辑
md5("Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!")=2348fbde8521869a98337279f55711b5 Build target '目标 1'
compiling md5.c...
linking...
Program Size: data=90.3 xdata=64 code=2203
creating hex file from "MD5"...
"MD5" - 0 Error(s), 0 Warning(s). V2.0 版本修订历史:
修改只读速度(向左移位数) 为二维数组
取消只读数组 (分组下标) 改为公式生成
取消部分函数与全局变量(数组) 并修改部分全局变量为局部变量
对算法进行优化 明文长度不限 只占用64字节片外RAM (XRAM)(XDATA)
(V1.0版会将所有明文填入XRAM并大量占用空间,且计算长度有限)
(本程序不包含串口程序)被蓝色包含的内存区域就是计算出的MD5值:
- /*
- V2.0 版本修订历史:
- 修改只读速度(向左移位数) 为二维数组
- 取消只读数组 (分组下标) 改为公式生成
- 取消部分函数与全局变量(数组) 并修改部分全局变量为局部变量
- 对算法进行优化 明文长度不限 只占用64字节片外RAM (XRAM)(XDATA)
- (V1.0版会将所有明文填入XRAM并大量占用空间,且计算长度有限)
- */
- #include "reg51.h"
- #include "intrins.h"
- #include "stdio.h"
- #define U8 unsigned char
- #define U16 unsigned int
- #define U32 unsigned long
- sfr AUXR = 0x8E;
- union md5_key { //MD5答案分组
- U32 l[4];
- U8 c[16];
- };
- union md5_data { //MD5数据分组
- U32 l[16]; //16个32位分组
- U8 c[64]; //64个8位分组
- };
- union udata { //32位大小端转换专用分组
- U32 l;
- U8 c[4];
- };
- //--------只读数组--------
- U32 code ti[]={ //常量ti
- 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
- 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,
- 0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,
- 0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,
- 0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
- 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,
- 0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,
- 0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,
- 0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
- 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,
- 0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
- 0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
- 0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391
- };
- U8 code ss[4][4]={ //向左移位数
- {7,12,17,22},
- {5,9,14,20},
- {4,11,16,23},
- {6,10,15,21}
- };
- U32 rib32(U32 l){ //32位大小端转换(十六进制整数0x12345678,反转后将返回0x78563412)
- union udata j,k;
- U8 m;
- j.l=l;
- for(m=0;m<4;m++){
- k.c[m]=j.c[m^3];
- }
- return k.l;
- }
- union md5_key md5_bin(U8 *i){ //计算字符串MD5值 (返回值类型为union md5_key结构的二进制MD5)
- union md5_key md5_key;
- union md5_data xdata md;
- U32 A,B,C,D,aa,bb,cc,dd; //MD5计算时需要用到的8个整数变量
- U32 z,g,pc=0,len=0,gn;
- U8 a,c,r,m;
- bit f,s128=0;
- //--------初始化MD5的4个变量--------
- md5_key.l[0]=0x67452301;
- md5_key.l[1]=0xefcdab89;
- md5_key.l[2]=0x98badcfe;
- md5_key.l[3]=0x10325476;
- for(;*i!=0;i++) len++; //统计字符串总长度
- gn=((len+8)>>6)+1; //计算块数
- i-=len; //指针位置减去总长度,否则会读到其他无用数据
- for(z=1;z<=gn;z++){ //变量z:块计数
- for(c=0;c<64;c++){ //变量C从0加到63
- f=pc>=len; //PC指针大于等于总长度时f为1,否则为0
- a=pc&63^3; //A指针等于PC指针的低6位再异或(取反)低2位用于反转大小端
- md.c[a] = f ? 0 : *i++; //位变量f为1时送回0,否则将字符串送MD5数据分组
- if(f && !s128){ //f为1 且 没有执行标记128(最后一个分组进行)
- s128=1; //标记128已经写入数据分组
- md.c[a]=128; //将128写入数据分组
- }
- pc++;
- }
- if(z == gn) { //最后一块,添加位长
- md.l[14]=len;md.l[15]=0; //添加字节数到MD5数据分组
- for(a=0;a<3;a++){ //字节数带进位左移3位(乘8)即为位数
- f=0; //此处位变量f是进位标志
- for(c=56;c<64;c++){ //参与左移的为分组最后8字节
- m=md.c[c^3]; //将数据分组送入变量m (地址异或3用于大小端反转读取)
- r=m<<1|f; //移位结果 (m左移1位再补上进位f)
- f=m>>7; //进位结果 (m的最高位)
- md.c[c^3]=r; //将变量r的值送回MD5数据分组
- }
- }
- }
- //--------MD5核心算法(循环次数为变量gn的值)--------
- A=md5_key.l[0];B=md5_key.l[1];
- C=md5_key.l[2];D=md5_key.l[3];
- for(a=0;a<64;a++){
- switch(a>>4){
- case 0:{g=(B&C)|((~B)&D);c=a;break;}
- case 1:{g=(D&B)|((~D)&C);c=5*a+1;break;}
- case 2:{g=B^C^D;c=3*a+5;break;}
- case 3:{g=C^(B|(~D));c=7*a;break;}
- }
- A=B+_lrol_(A+g+md.l[c&15]+ti[a],ss[a>>4][a&3]); // _lrol_() 为 intrins.h 自带的32位整数循环左移函数
- aa=A;bb=B;cc=C;dd=D;
- A=dd;B=aa;C=bb;D=cc;
- }
- md5_key.l[0]+=A;md5_key.l[1]+=B;
- md5_key.l[2]+=C;md5_key.l[3]+=D;
- }
- for(c=0;c<4;c++){ //计算完成对MD5答案分组进行大小端转换
- md5_key.l[c]=rib32(md5_key.l[c]);
- }
- return md5_key;
- }
- //将union md5_key结构转换成文本MD5字符串 参数1: union md5_key结构 参数2:1大写0小写
- U8* md5_to_text(union md5_key md5_key,bit u){
- U8 y[33];
- U8 a,r=0,m;
- bit f=0;
- y[32]=0;
- for(a=0;a<32;a+=2){
- do {
- m= f ? md5_key.c[r]&15 : md5_key.c[r]>>4;
- y[a+(U8)f]=(m <10?48:u?55:87)+m;
- f=!f;
- } while(f);
- r++;
- }
- return y;
- }
- U8* md5(U8 *i,bit u){ //计算字符串的MD5值 参数1:明文文本 参数2:1大写0小写 (返回16进制MD5字符串)
- return md5_to_text(md5_bin(i),u);
- }
- void main(){
- md5("Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!",1);
- P3=0xAA;
- while(1);
- }
复制代码 |