目录
前提概要:
MD5加密4步骤:
C语言实现MD5算法:(假设加密 iscbupt )
附上运行中间结果图:
字符串和文件加密实例:
本篇内容基于haroroda博客的MD5加密算法(c语言实现)和 艾蔓草博客的C语言实现md5函数代码,只是进行简单的融合并附上自己的理解而已,有需要的可以自己浏览上面两篇优秀的博客。
(1)附加填充位
课本原话:填充一个 ‘1’ 和若干个 ‘0’ 使其长度模 512 与 448 同余,然后再将消息的真实长度以 64bit 表示附加在填充结果后面,从而使得消息长度恰好为 512bit 的整数倍。
举例说明:
如明文为 iscbupt (7字符,56bits)
其 16 进制 ascII 码是105,115,99,98,117,112,116,转换成二进制便是 01101001 01110011 01100011 01100010 01110101 01110000 01110100,这是长度为 56 ,要使其长度模 512 与 448 同余,则需补充一个 ‘1’ 和 391 个 ‘0’ 。因为消息长度为 56,所以用 64 位二进制表示为 00~00(56个零)00111000。到目前为止 512 位全部填充完整了~
(2)初始化链接变量
课本原话:MD5 中有 A、B、C、D 4 个 32 位寄存器,最开始存放 4 个固定的 32 位的整数参数,即初始链接变量,这些参数用于第 1 轮运算。(第 1 轮之后值就会变化)
A=0x12345678,B=0x89ABCDEF,C=0xFEDCBA98,D=0x76543210
(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 01100010
M[1]:01110101 01110000 01110100 10000000
M[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 赋值给 B,B 赋值给 C,C 赋值给 D,原本的 D 赋值给 A,赋值完的 A、B、C、D 便可以进入下一轮。
下面来说下上文 j、左移步数 step、T[i] 的取值情况:
第一大轮:
j 在这大轮是按顺序从 0 取到 15
第 1、5、9、13 小轮 step=7;第 2、6、10、14 小轮 step=12;第 3、7、11、15 小轮 step=17;第 4、8、12、16 小轮 step=22
第二大轮:
j 的取值顺序为 ----- 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12
第 1、5、9、13 小轮 step=5;第 2、6、10、14 小轮 step=9;第 3、7、11、15 小轮 step=14;第 4、8、12、16小轮 step=20
第三大轮:
j 的取值顺序为----- 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2
第 1、5、9、13 小轮 step=4;第 2、6、10、14 小轮 step=11;第 3、7、11、15 小轮 step=16;第 4、8、12、16 小轮 step=23
第四大轮:
j 的取值顺序为-----0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9
第 1、5、9、13 小轮 step=6;第 2、6、10、14 小轮 step=10;第 3、7、11、15 小轮 step=15;第 4、8、12、16 小轮 step=21
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 的整数倍。如400=110010000(补齐 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
源文件如下:md5.h
#ifndef MD5_H
#define MD5_H
/*
只引用一次头文件:(头文件名转为大写并用 '_' 代替 '.' ,举例:md5.h写为MD5_H )
#ifndef HEADER_FILE
#define HEADER_FILE
the entire header file context
#endif
*/
typedef struct #定义 md5 加密算法的结构
{
unsigned int count[2]; #md5 加密算法的第一步附加填充位,这里 32 位 Int 要看成 256bits ,count[2] 就是512bits
unsigned 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
#include "md5.h"
unsigned 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*8=512bits ,我们第一步的时候说填充一个 ‘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 = 56
partlen = 64 - index;
#第一次调用:partlen = 64,这里 partlen 是计算在不断补位中 context->count 所占的 bits 数距离 512 的整数倍还差多少位( char 型)。
#第二次调用:partlen = 57
#第三次调用:partlen = 8
context->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;i+64 <= inputlen;i+=64) #把符合 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 位 512bits
padlen = (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[j+1] = (input[i] >> 8) & 0xFF;
output[j+2] = (input[i] >> 16) & 0xFF;
output[j+3] = (input[i] >> 24) & 0xFF;
i++;
j+=4;
}
}
/*********************************************************
* 名 称: 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[j+1] << 8) |
(input[j+2] << 16) |
(input[j+3] << 24);
i++;
j+=4;
}
}
/*********************************************************
* 名 称: 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 赋值给 B,B 赋值给 C,C 赋值给 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
#include
#include "md5.h"
#include
#include
#include
#include
void 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(i=0;i<16;i++)
{
sprintf(temp,"%02x",decrypt[i]);
strcat((char *)decrypt32,temp);
}
printf("md5:%s\n",decrypt32);
return;
}
实例2 文件加密:
#include
#include
#include "md5.h"
#include
#include
#include
#include
#define FORWORD_FW "123.c"
int 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(fdf<0)
{
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_len==0)
{
break;
}
filelen += read_len;
MD5Update(&md5,(unsigned char *)hexbuf,read_len);
}
MD5Final(&md5,decrypt);
strcpy((char *)decrypt32,"");
for(i=0;i<16;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(filelen<0)
{
printf("calc_md5 fail\n");
return -1;
}
return 0;
}