做棋牌网站建设哪家便宜,网页制作教程步骤,建筑工人信息平台,做招聘网站多少钱目录
前提概要#xff1a;
MD5加密4步骤#xff1a;
C语言实现MD5算法#xff1a;#xff08;假设加密 iscbupt #xff09;
附上运行中间结果图#xff1a;
字符串和文件加密实例#xff1a; 前提概要#xff1a;
本篇内容基于haroroda博客的MD5加密算法#x…目录
前提概要
MD5加密4步骤
C语言实现MD5算法假设加密 iscbupt
附上运行中间结果图
字符串和文件加密实例 前提概要
本篇内容基于haroroda博客的MD5加密算法c语言实现和 艾蔓草博客的C语言实现md5函数代码只是进行简单的融合并附上自己的理解而已有需要的可以自己浏览上面两篇优秀的博客。 MD5加密4步骤 1附加填充位 课本原话填充一个 ‘1’ 和若干个 ‘0’ 使其长度模 512 与 448 同余然后再将消息的真实长度以 64bit 表示附加在填充结果后面从而使得消息长度恰好为 512bit 的整数倍。 举例说明 如明文为 iscbupt 7字符56bits 其 16 进制 ascII 码是1051159998117112116转换成二进制便是 01101001 01110011 01100011 01100010 01110101 01110000 01110100这是长度为 56 要使其长度模 512 与 448 同余则需补充一个 ‘1’ 和 391 个 ‘0’ 。因为消息长度为 56所以用 64 位二进制表示为 00~0056个零00111000。到目前为止 512 位全部填充完整了~ 2)初始化链接变量 课本原话MD5 中有 A、B、C、D 4 个 32 位寄存器最开始存放 4 个固定的 32 位的整数参数即初始链接变量这些参数用于第 1 轮运算。第 1 轮之后值就会变化 A0x12345678B0x89ABCDEFC0xFEDCBA98D0x76543210 3分组处理迭代压缩 课本原话MD5 算法的分组处理压缩函数与分组密码的分组处理相似。它由4大轮组成512bit 的消息分组 M[i] 被分成 16 个子分组每个子分组为 32bit 参与每大轮中16步函数运算即每大轮包括 16 个小步骤。
每步的输入是 4 个 32bit 的链接变量也就是A、B、C、D和一个32bit的消息分组就是 M[i] 输出为 32 位值。经过 4 轮共 64 步后得到的 4 个寄存器值分别与输入链接变量也就是初始的A、B、C、D进行模加即是当前消息的中间散列值。 明文是 iscbupt 的 M[i] 如下 M[0]:01101001 01110011 01100011 01100010M[1]:01110101 01110000 01110100 10000000M[2]:00000000 00000000 00000000 00000000................M[14]:00111000 00000000 00000000 00000000 #这里是我们前面补充的最后64bits长度M[15]:00000000 00000000 00000000 00000000 4分组处理中步函数 所有大轮上文所说的 4 大轮里的所有小轮16轮都是同一个步函数 A B (( A f(B,C,D) M[j] T[i]) s )) 操作即 B、C、D进入 f 函数这里的 f 函数就是课本里的非线性函数包含F、G、H、I 这四种函数得到的结果与 A 模加再与 M[j] 模加这里的 j 与第几大轮第几小轮有关然后继续与 T[i] 模加这里的 i 从 1 取到 64 然后进行循环左移 s 位左移的 2 位数也与第几大轮第几小轮有关结果再与 B 模加最后得到的结果终值赋值给 A 。 一小轮结束后将 A 赋值给 BB 赋值给 CC 赋值给 D原本的 D 赋值给 A赋值完的 A、B、C、D 便可以进入下一轮。 下面来说下上文 j、左移步数 step、T[i] 的取值情况 第一大轮 j 在这大轮是按顺序从 0 取到 15 第 1、5、9、13 小轮 step7第 2、6、10、14 小轮 step12第 3、7、11、15 小轮 step17第 4、8、12、16 小轮 step22 第二大轮 j 的取值顺序为 ----- 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12 第 1、5、9、13 小轮 step5第 2、6、10、14 小轮 step9第 3、7、11、15 小轮 step14第 4、8、12、16小轮 step20 第三大轮 j 的取值顺序为----- 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2 第 1、5、9、13 小轮 step4第 2、6、10、14 小轮 step11第 3、7、11、15 小轮 step16第 4、8、12、16 小轮 step23 第四大轮 j 的取值顺序为-----0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 第 1、5、9、13 小轮 step6第 2、6、10、14 小轮 step10第 3、7、11、15 小轮 step15第 4、8、12、16 小轮 step21
T[i] 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 MD5加密中注意点
1. MD5 加密算法里面的所有模加都是模 2 的 32 次加而不是模 2 加。 举例说明下模 2 的 32 次加就是简单的二进制加法取前 32 位而已
11101000......(省略了24个‘0’)01110000.........(省略了24个‘0’)101011000.......(省略了24个‘0’)共33位取后32位最终得到01011000........(省略了24个‘0’)。 2.初始的A、B、C、D 4个链接变量与 M[j] 在进入步函数前要先经过大小端处理T[i]不需要。 3.位数填充时64 bit若长度的二进制位数不足需要在二进制前补齐至 8 的整数倍而不是 4 的整数倍。如400110010000补齐 8 的整数倍共 16 位
补齐后是00000001 10010000而不是00011001 00000000 4.大小端处理不是单纯指 12345678 - 78563412之所以有前面这种变换是因为 12、34、56、78 分别表示 4 个十进制数也就是说表示第 1 个十进制数的十六进制数经过转换放在最后第 2 个放在第 1 个前。当 1234 表示第 1 个十进制数、5678 表示第 2 个十进制数时12345678 - 56781234 而不是 78563412。如明文长度为 400 M[14] 为 0x01900000转换后为 0x00000190 而不是 0x00009001 C语言实现MD5算法假设加密 iscbupt
源文件如下md5.h
#ifndef MD5_H#define MD5_H/*只引用一次头文件(头文件名转为大写并用 _ 代替 . 举例md5.h写为MD5_H )#ifndef HEADER_FILE#define HEADER_FILEthe entire header file context#endif*/typedef struct #定义 md5 加密算法的结构{unsigned int count[2]; #md5 加密算法的第一步附加填充位这里 32 位 Int 要看成 256bits count[2] 就是512bitsunsigned int state[4]; #md5 加密算法的第二步初始化链接变量这里存放 A、B、C、D 4 个 32 位寄存器unsigned char buffer[64]; #md5 加密算法的第三步分组处理迭代压缩这里存放 A、B、C、D 4 个 32 位寄存器}MD5_CTX;#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))/*md5 加密算法的第四步分组处理中步函数课本里的非线性函数包含F、G、H、I这四种函数。*/#define ROTATE_LEFT(x,n) ((x n) | (x (32-n))) #定义分组处理的步函数中的移位 step。#define FF(a,b,c,d,x,s,ac) \{ \a F(b,c,d) x ac; \a ROTATE_LEFT(a,s); \a b; \}#define GG(a,b,c,d,x,s,ac) \{ \a G(b,c,d) x ac; \a ROTATE_LEFT(a,s); \a b; \}#define HH(a,b,c,d,x,s,ac) \{ \a H(b,c,d) x ac; \a ROTATE_LEFT(a,s); \a b; \}#define II(a,b,c,d,x,s,ac) \{ \a I(b,c,d) x ac; \a ROTATE_LEFT(a,s); \a b; \}/*这里定义 4 大轮里的所有小轮16 轮的同一个步函数A B (( A f(B,C,D) M[j] T[i]) s ))上面的 \ 是续行符*/void MD5Init(MD5_CTX *context);void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);void MD5Final(MD5_CTX *context,unsigned char digest[16]);void MD5Transform(unsigned int state[4],unsigned char block[64]);void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len);void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len);/*这里声明了下面要用到的函数*/#endif md5.c
#include memory.h#include md5.hunsigned char PADDING[]{0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; #这里有 64 个char类型要按 bit 来看所以是 64*8512bits 我们第一步的时候说填充一个 ‘1’ 和若干个 ‘0’ 使其长度模 512 与 448 同余所以这里第一个 0x80 就是我们填充的第一个 1 造成的。放 512bits 在这里是用于后面补位的时候截取比如我们加密 iscbupt 7字符56bits那么就要补充 312bits 在这里截取前 39 位。/********************************************************* 名 称: MD5Init()* 功 能: 初始化MD5结构体* 入口参数:context要初始化的MD5结构体* 出口参数: 无*********************************************************/void MD5Init(MD5_CTX *context){context-count[0] 0; #初始化中这里存放的是传入参数的 bits 位数context-count[1] 0;context-state[0] 0x67452301; #初始化中这里是 A、B、C、D 4 个 32 位寄存器的初始值context-state[1] 0xEFCDAB89;context-state[2] 0x98BADCFE;context-state[3] 0x10325476;}/********************************************************** 名 称: MD5Update()* 功 能: 将要加密的信息传递给初始化过的MD5结构体无返回值* 入口参数:context初始化过了的MD5结构体input需要加密的信息可以任意长度inputLen指定input的长度* 出口参数: 无*********************************************************/void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) #先以传入参数 iscbupt 7字符56bits为准来讨论{unsigned int i 0,index 0,partlen 0;index (context-count[0] 3) 0x3F;#第一次调用index 0 这里右移 3 位得看成除以 8是计算要加密的字符数的(char)第一次调用 MD5Update 中并没有派上用场在后面的 MD5Final 函数中会有第 2、3 次调用 MD5Update 那时候才会用上。 0x3F是要保证截取的是非 512bits 的余数部分因为 2 的 6 次方是 64 位 512bits#第二次调用index 7#第三次调用index 56partlen 64 - index;#第一次调用partlen 64这里 partlen 是计算在不断补位中 context-count 所占的 bits 数距离 512 的整数倍还差多少位( char 型)。#第二次调用partlen 57#第三次调用partlen 8context-count[0] inputlen 3;#第一次调用context-count[0] 56这里左移 3 位要看成乘 8这里是计算输入的字符的 bits 数用于给后面加密第一步附加填充位来参考#第二次调用inputlen 是 MD5Final 中的 padlen 49所以 context-count[0] 448已经模 512 与 448 同余了。#第三次调用inputlen 是 MD5Final 中的 8所以 context-count[0] 512已经是最终的长度了。if(context-count[0] (inputlen 3))context-count[1];#这里不明觉厉context-count[1] inputlen 29;#第一次调用由于我们传入的 iscbupt 7字符56bits不足 64 位的 512bits 所以不进入该循环。#第二次调用由于我们传入的 MD5Final 中的 padlen 49 不足新 partlen 57 所以不进入该循环。#第二次调用由于我们传入的 MD5Final 中的 8 足够新 partlen 8 所以进入该循环开始加密。if(inputlen partlen)#如果传入的参数的长度直接就满足 64 位的 512bits 就先把这部分加密因为每次每次只能加密 512bits 后面补位上去的 64bits 长度什么的等补齐到 512bits 的整数倍后再继续加密。{memcpy(context-buffer[index],input,partlen); #把 64 位的 512bits 复制到 context-buffer[index] 中进行第一个 512bits 的加密。MD5Transform(context-state,context-buffer); #md5加密算法for(i partlen;i64 inputlen;i64) #把符合 512bits 的部分继续加密这里非 512bits 部分的余数并没有进入加密中因为要在后面补齐 512bits 后才能用来加密。MD5Transform(context-state,input[i]);index 0;}else{i 0;}memcpy(context-buffer[index],input[i],inputlen-i); #这里把非 512bits 部分的余数存入context-buffer[index] 中用于在 MD5Final 中补位。}/********************************************************** 名 称: MD5Final()* 功 能: 转换成32位的16进制字符串。context初始化过了的MD5结构体digest[16]用于承接加密后的 32 位密文* 出口参数: 无*********************************************************/void MD5Final(MD5_CTX *context,unsigned char digest[16]){unsigned int index 0,padlen 0;unsigned char bits[8]; #这里 8 位 char 共 64bits 是加密第一步中附加填充位时把真实长度以 64bit 表示附加在填充结果后面以达到 512bits整数倍的长度。index (context-count[0] 3) 0x3F; #在第一次调用 MD5Update 中 context-count[0] 被赋值了传入参数的 bits 数这里右移 3 位就是除 8就是被赋值会传入参数的 char 长度7位。 0x3F是要保证截取的是非 512bits 的余数部分因为 2 的 6 次方是 64 位 512bitspadlen (index 56)?(56-index):(120-index);#这里 padlen 49 这是判断传入参数是否小于 56因为最后的 8 位 64bits 是用来补充真实长度的如果传入参数大于 56 位那总长度就以 1024bits 来算。MD5Encode(bits,context-count,8); #第一次调用 MD5Update 中 context-count[0] 值为 56bits 总共64 位的 context-count 拆分成 8 个 8 位存放到 bits 中由于这里存放的是 char 类型所以 56 以 ASCII 码值 8 的形式存入。MD5Update(context,PADDING,padlen); #第二次调用 MD5Update 截取 PADDING 的前 padlen 位来做补位使其使其长度模 512 与 448 同余MD5Update(context,bits,8); #第三次调用 MD5Update 截取 bits 的前 8 位来做最后的真实长度以 64bit 表示附加在填充结果后面从而使得消息长度恰好为 512bit 的整数倍的补位。MD5Encode(digest,context-state,16);}/********************************************************** 名 称: MD5Encode()* 功 能: 将 32 位的 int 类型拆分成 8 位的 char 类型存放到 4 个数组中要注意的是存放的值是 ASCII 码的形式。* 入口参数:input要拆分的 int 类型的字符串len 字符串的长度output作为拆分后的承接载体* 出口参数: 无*********************************************************/void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len){unsigned int i 0,j 0;while(j len){output[j] input[i] 0xFF;output[j1] (input[i] 8) 0xFF;output[j2] (input[i] 16) 0xFF;output[j3] (input[i] 24) 0xFF;i;j4;}}/********************************************************** 名 称: MD5Decode()* 功 能: 将 8 位的 char 类型拼凑成成 32 位的 int 类型存放到 1 个数组中要注意的是存放的值是数字型。* 入口参数:input要拼凑的 char 类型的字符串len 字符串的长度output作为拼凑后的承接载体* 出口参数: 无*********************************************************/void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len){unsigned int i 0,j 0;while(j len){output[i] (input[j]) |(input[j1] 8) |(input[j2] 16) |(input[j3] 24);i;j4;}}/********************************************************** 名 称: MD5Transform()* 功 能: md5 加密算法实现* 入口参数:state[4]A、B、C、D 4 个 32 位寄存器block[64] 完整的符合要求的 512bits 整数倍的加密参数* 出口参数: 无*********************************************************/void MD5Transform(unsigned int state[4],unsigned char block[64]){unsigned int a state[0]; #这里是 A、B、C、D 4 个 32 位寄存器的初始值用于第1轮运算。unsigned int b state[1];unsigned int c state[2];unsigned int d state[3];unsigned int x[64];MD5Decode(x,block,64); #512bits 的消息分组M[i] 被分成 16 个子分组每个子分组为 32bits参与 4 大轮中没轮 16 步函数运算。/*所有大轮里的所有小轮都是同一个步函数 A B (( A f(B,C,D) M[j] T[i]) s ))操作 一小轮结束后将 A 赋值给 BB 赋值给 CC 赋值给 D原本的 D 赋值给 A赋值完的 A、B、C、D 便可以进入下一轮。*//* Round 1 */FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 *//* Round 2 */GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 *//* Round 3 */HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 *//* Round 4 */II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 *//*经过 4 轮共 64 步后得到的 4 个寄存器值分别与输入链接变量也就是初始的A、B、C、D进行模加即是当前消息的中间散列值这里是 16 位的要转成 32 位 16 进制的密文。*/state[0] a;state[1] b;state[2] c;state[3] d;} 附上运行中间结果图 字符串和文件加密实例
对字符串进行加密
#include stdio.h#include stdlib.h#include md5.h#include sys/types.h#include sys/stat.h#include fcntl.h#include string.hvoid main( void ){int read_len;int i ;char temp[8]{0};unsigned char digest[16]; //存放结果char hexbuf[128]12334567;unsigned char decrypt[16]{0};unsigned char decrypt32[64]{0};MD5_CTX md5c;MD5Init(md5c); //初始化read_len strlen(hexbuf);MD5Update(md5c,(unsigned char *)hexbuf,read_len);MD5Final(md5c,decrypt);strcpy((char *)decrypt32,);for(i0;i16;i){sprintf(temp,%02x,decrypt[i]);strcat((char *)decrypt32,temp);}printf(md5:%s\n,decrypt32);return;} 实例2 文件加密
#include stdio.h#include stdlib.h#include md5.h#include sys/types.h#include sys/stat.h#include fcntl.h#include string.h#define FORWORD_FW 123.cint calc_md5(char*filename,char*dest){int i;int filelen 0;int read_len;char temp[8]{0};char hexbuf[128]{0};unsigned char decrypt[16]{0};unsigned char decrypt32[64]{0};MD5_CTX md5;char fw_path[128];int fdf;fdf open(filename,O_RDWR);if(fdf0){printf(%s not exist\n,FORWORD_FW);return -1;}MD5Init(md5);while(1){read_len read(fdf, hexbuf,sizeof(hexbuf));if (read_len 0) {close(fdf);return -1;}if(read_len0){break;}filelen read_len;MD5Update(md5,(unsigned char *)hexbuf,read_len);}MD5Final(md5,decrypt);strcpy((char *)decrypt32,);for(i0;i16;i){sprintf(temp,%02x,decrypt[i]);strcat((char *)decrypt32,temp);}strcpy(dest,decrypt32);printf(md5:%s len%d\n,dest,filelen);close(fdf);return filelen;}int main(int argc, char *argv[]){int ret;int filelen;char md5_str[64]{0};char cmd[256]{0};filelen calc_md5(FORWORD_FW,md5_str);if(filelen0){printf(calc_md5 fail\n);return -1;}return 0;}