ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

MD5

2021-11-19 17:35:59  阅读:153  来源: 互联网

标签:int unsigned char context lGroup MD5


首先推荐
https://blog.csdn.net/hla199106/article/details/45129963?ops_request_misc=%7B%22request%5Fid%22%3A%22163731312016780357262123%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&request_id=163731312016780357262123&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2
我很菜,整理了一份MD5的加密代码:
MD5.h:

#ifndef _MD5H_
#define _MD5H_
#include <math.h>
#include <Windows.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>

void ROL(unsigned int &s, unsigned short cx); //32位数循环左移实现函数
void ltob(unsigned int &i); //B\L互转,接受UINT类型
unsigned int* MD5(const char* mStr); //MD5加密函数,并执行数据填充
unsigned int* MD5_2(const char* mStr); //MD5加密函数,并执行数据填充,更优

#endif

MD5.cpp:

#include "MD5.h"
 
//4组计算函数
inline unsigned int F(unsigned int X, unsigned int Y, unsigned int Z)
{
    return (X & Y) | ((~X) & Z);
}
inline unsigned int G(unsigned int X, unsigned int Y, unsigned int Z)
{
    return (X & Z) | (Y & (~Z));
}
inline unsigned int H(unsigned int X, unsigned int Y, unsigned int Z)
{
    return X ^ Y ^ Z;
}
inline unsigned int I(unsigned int X, unsigned int Y, unsigned int Z)
{
    return Y ^ (X | (~Z));
}
 
//32位数循环左移(或称右移)实现函数
void ROL(unsigned int &s, unsigned short cx)
{
    if (cx > 32)cx %= 32;
    s = (s << cx) | (s >> (32 - cx));
    return;
}
 
//B\L互转,接收UINT类型
void ltob(unsigned int &i)
{
    unsigned int tmp = i;//保存副本
    byte *psour = (byte*)&tmp, *pdes = (byte*)&i;
    pdes += 3;//调整指针,准备左右调转
    for (short j = 3; j >= 0; --j)
    {
        CopyMemory(pdes - j, psour + j, 1);
    }
    return;
}
 
//MD5循环计算函数,label=第几轮循环(1<=label<=4),lGroup数组=4个种子副本,M=数据(16组32位数指针)
void AccLoop(unsigned short label, unsigned int *lGroup, void *M)
{
    unsigned int *i1, *i2, *i3, *i4, TAcc, tmpi = 0; //定义:4个指针; T表累加器; 局部变量
    typedef unsigned int(*clac)(unsigned int X, unsigned int Y, unsigned int Z); //定义函数类型
 
    //循环左移-位数表
    const unsigned int rolarray[4][4] = {
        { 7, 12, 17, 22 },
        { 5, 9, 14, 20 },
        { 4, 11, 16, 23 },
        { 6, 10, 15, 21 }
    };
    //数据坐标表
    const unsigned short mN[4][16] = {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
        { 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12 },
        { 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2 },
        { 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 }
    };
    const unsigned int *pM = static_cast<unsigned int*>(M);//转换类型为32位的Uint
    TAcc = ((label - 1) * 16) + 1;
    clac clacArr[4] = { F, G, H, I }; //定义并初始化计算函数指针数组
 
    //一轮循环开始(16组->16次)
    for (short i = 0; i < 16; ++i)
    {
        /*进行指针自变换*/
        i1 = lGroup + ((0 + i) % 4);
        i2 = lGroup + ((1 + i) % 4);
        i3 = lGroup + ((2 + i) % 4);
        i4 = lGroup + ((3 + i) % 4);
 
        if(0 == i%2)
        {
            //计算开始: A+F(B,C,D)+M[i]+T[i+1]
            tmpi = (*i1 + clacArr[label - 1](*i2, *i3, *i4) + pM[(mN[label - 1][i])] + (unsigned int)(0x100000000UL * abs(sin((double)(TAcc + i)))));
            //循环左移
            ROL(tmpi, rolarray[label - 1][i % 4]);
            //相加并赋值到下一个种子
            *i1 = *i2 + tmpi;
        }
        else
        {
            tmpi = (*i3 + clacArr[label - 1](*i4, *i1, *i2) + pM[(mN[label - 1][i])] + (unsigned int)(0x100000000UL * abs(sin((double)(TAcc + i)))));
            //循环左移
            ROL(tmpi, rolarray[label - 1][i % 4]);
            //相加并赋值到下一个种子
            *i3 = *i4 + tmpi;
        }
    }
    return;
}
 
//加密函数
unsigned int* MD5(const char* mStr)
{
    //计算缓冲区长度,并进行数据填充
    unsigned int mLen = strlen(mStr);
    if (mLen <= 0) 
    {
        return 0;
    }
    unsigned int FillSize = 448 - ((mLen * 8) % 512); //计算需填充的bit数
    unsigned int FSbyte = FillSize / 8;               //以字节表示的填充数
    //预留512-448=64bit,填充原消息的长度
    unsigned int BuffLen = mLen + 8 + FSbyte;         //缓冲区长度
    unsigned char *md5Buff = new unsigned char[BuffLen]; //分配缓冲区
    CopyMemory(md5Buff, mStr, mLen); //复制字符串到缓冲区
 
    //数据填充
    md5Buff[mLen] = 0x80; //第一个bit填充1
    ZeroMemory(&md5Buff[mLen + 1], FSbyte - 1); //其它bit填充0
    unsigned long long lenBit = mLen * 8ULL; //计算字符串长度,准备填充后64bit
    CopyMemory(&md5Buff[mLen + FSbyte], &lenBit, 8);
 
    //数据运算
    unsigned int LoopNumber = BuffLen / 64; //以16个字为一分组,计算分组数量
    unsigned int A = 0x67452301, B = 0xEFCDAB89, C = 0x98BADCFE, D = 0x10325476;//初始4个种子,小端类型
    unsigned int *lGroup = new unsigned int[4];
    lGroup[0] = A;
    lGroup[1] = B;
    lGroup[2] = C;
    lGroup[3] = D;
 
    for (unsigned int Bcount = 0; Bcount < LoopNumber; ++Bcount) //分组大循环开始
    {
        //进入4次计算的小循环,共4*16次
        for (unsigned short Lcount = 0; Lcount < 4;)
        {
            AccLoop(++Lcount, lGroup, &md5Buff[Bcount * 64]);
        }
        //数据相加作为下一轮的种子或者最终输出
        A = (lGroup[0] += A);
        B = (lGroup[1] += B);
        C = (lGroup[2] += C);
        D = (lGroup[3] += D);
 
    }
    //转换内存中的布局后才能正常显示
    ltob(lGroup[0]);
    ltob(lGroup[1]);
    ltob(lGroup[2]);
    ltob(lGroup[3]);
    delete[] md5Buff;
    return lGroup;
}
 
/*
MD5循环计算函数,label=第几轮循环(1<=label<=4),lGroup数组=4个种子副本,M=数据(16组32位数指针)
种子数组排列方式: --A--D--C--B--,即 lGroup[0]=A; lGroup[1]=D; lGroup[2]=C; lGroup[3]=B;
*/
void AccLoop_2(unsigned short label, unsigned int *lGroup, void *M)
{
    unsigned int *i1, *i2, *i3, *i4, TAcc, tmpi = 0; //定义:4个指针; T表累加器; 局部变量
    typedef unsigned int(*clac)(unsigned int X, unsigned int Y, unsigned int Z); //定义函数类型
    const unsigned int rolarray[4][4] = {
        { 7, 12, 17, 22 },
        { 5, 9, 14, 20 },
        { 4, 11, 16, 23 },
        { 6, 10, 15, 21 }
    };//循环左移-位数表
    const unsigned short mN[4][16] = {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
        { 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12 },
        { 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2 },
        { 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 }
    };//数据坐标表
    const unsigned int *pM = static_cast<unsigned int*>(M);//转换类型为32位的Uint
    TAcc = ((label - 1) * 16) + 1; //根据第几轮循环初始化T表累加器
    clac clacArr[4] = { F, G, H, I }; //定义并初始化计算函数指针数组
 
    /*一轮循环开始(16组->16次)*/
    for (short i = 0; i < 16; ++i)
    {
        /*进行指针自变换*/
        i1 = lGroup + ((0 + i) % 4);
        i2 = lGroup + ((3 + i) % 4);
        i3 = lGroup + ((2 + i) % 4);
        i4 = lGroup + ((1 + i) % 4);
 
        /*第一步计算开始: A+F(B,C,D)+M[i]+T[i+1] 注:第一步中直接计算T表*/
        tmpi = (*i1 + clacArr[label - 1](*i2, *i3, *i4) + pM[(mN[label - 1][i])] + (unsigned int)(0x100000000UL * abs(sin((double)(TAcc + i)))));
        ROL(tmpi, rolarray[label - 1][i % 4]);//第二步:循环左移
        *i1 = *i2 + tmpi;//第三步:相加并赋值到种子
    }
    return;
}
 
/*接口函数,并执行数据填充*/
unsigned int* MD5_2(const char* mStr)
{
    unsigned int mLen = strlen(mStr); //计算字符串长度
    if (mLen < 0) return 0;
    unsigned int FillSize = 448 - ((mLen * 8) % 512); //计算需填充的bit数
    unsigned int FSbyte = FillSize / 8; //以字节表示的填充数
    unsigned int BuffLen = mLen + 8 + FSbyte; //缓冲区长度或者说填充后的长度
    unsigned char *md5Buff = new unsigned char[BuffLen]; //分配缓冲区
    CopyMemory(md5Buff, mStr, mLen); //复制字符串到缓冲区
 
    /*数据填充开始*/
    md5Buff[mLen] = 0x80; //第一个bit填充1
    ZeroMemory(&md5Buff[mLen + 1], FSbyte - 1); //其它bit填充0,另一可用函数为FillMemory
    unsigned long long lenBit = mLen * 8ULL; //计算字符串长度,准备填充
    CopyMemory(&md5Buff[mLen + FSbyte], &lenBit, 8); //填充长度
    /*数据填充结束*/
 
    /*运算开始*/
    unsigned int LoopNumber = BuffLen / 64; //以16个字为一分组,计算分组数量
    unsigned int A = 0x67452301, B = 0x0EFCDAB89, C = 0x98BADCFE, D = 0x10325476;//初始4个种子,小端类型
    //unsigned int *lGroup = new unsigned int[4]{ A, D, C, B}; //种子副本数组,并作为返回值返回
    unsigned int *lGroup = new unsigned int[4];
    lGroup[0] = A;
    lGroup[1] = D;
    lGroup[2] = C;
    lGroup[3] = B;
 
    for (unsigned int Bcount = 0; Bcount < LoopNumber; ++Bcount) //分组大循环开始
    {
        /*进入4次计算的小循环*/
        for (unsigned short Lcount = 0; Lcount < 4;)
        {
            AccLoop_2(++Lcount, lGroup, &md5Buff[Bcount * 64]);
        }
        /*数据相加作为下一轮的种子或者最终输出*/
        A = (lGroup[0] += A);
        B = (lGroup[3] += B);
        C = (lGroup[2] += C);
        D = (lGroup[1] += D);
    }
    /*转换内存中的布局后才能正常显示*/
    ltob(lGroup[0]);
    ltob(lGroup[1]);
    ltob(lGroup[2]);
    ltob(lGroup[3]);
    delete[] md5Buff; //清除内存并返回
    return lGroup;
}

main.cpp:

#include "MD5.h"
 
int main()
{
    char tmpstr[256], buf[4][10];
    std::cout << "请输入要加密的字符串:";
    std::cin >> tmpstr;
 
    //char buf[4][10];
    //char tmpstr[] ="admin";
    //MD5值:21232F297A57A5A743894A0E4A801FC3
 
    unsigned int* tmpGroup = MD5(tmpstr);
    sprintf_s(buf[0], "%8X", tmpGroup[0]);  //A
    sprintf_s(buf[1], "%8X", tmpGroup[1]);  //B
    sprintf_s(buf[2], "%8X", tmpGroup[2]);  //C
    sprintf_s(buf[3], "%8X", tmpGroup[3]);  //D
    std::cout <<"1-MD5:"<< buf[0] << buf[1] << buf[2] << buf[3] << std::endl;
 
    tmpGroup = MD5_2(tmpstr);
    sprintf_s(buf[0], "%8X", tmpGroup[0]);  //A
    sprintf_s(buf[1], "%8X", tmpGroup[3]);  //B
    sprintf_s(buf[2], "%8X", tmpGroup[2]);  //C
    sprintf_s(buf[3], "%8X", tmpGroup[1]);  //D
    std::cout <<"2-MD5:"<< buf[0] << buf[1] << buf[2] << buf[3] << std::endl;
 
    delete[] tmpGroup;
 
    return 0;
}

或者

#include <string.h>
#include <math.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
 
 
/***********************************
* 非线性函数
* (&是与,|是或,~是非,^是异或) 
* 
* 这些函数是这样设计的:
*   如果X、Y和Z的对应位是独立和均匀的,
*   那么结果的每一位也应是独立和均匀的。 
* 
* 函数F是按逐位方式操作:如果X,那么Y,否则Z。
* 函数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))  
 
 
/**************************************
*向左换移(右环移)n个单位
* ************************************/
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))  
 
 
/****************************************************
* 每次操作对a,b,c和d中的其中三个作一次非线性函数运算
*  F(b,c,d)   G(b,c,d)   H(b,c,d)   I(b,c,d)
*
* 然后将所得结果加上 第四个变量(a),
* F(b,c,d)+a
*
* 文本的一个子分组(x)
* F(b,c,d)+a+x
* 
* 和一个常数(ac)。
* F(b,c,d)+a+x+ac
*
* 再将所得结果向右环移一个不定的数(s),
* ROTATE_LEFT( F(b,c,d)+a+x+ac , s )
* 
* 并加上a,b,c或d中之一(b)。
* ROTATE_LEFT( F(b,c,d)+a+x+ac , s )+b
* 
* 最后用该结果取代a,b,c或d中之一(a)。
* a=ROTATE_LEFT( F(b,c,d)+a+x+ac , s )+b
* 
* ***************************************************/
#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; }
 
 
//储存一个MD5 text信息 
typedef struct  
{  
    unsigned int count[2];    
    //记录当前状态,其数据位数   
 
    unsigned int state[4];    
    //4个数,一共32位 记录用于保存对512bits信息加密的中间结果或者最终结果  
 
    unsigned char buffer[64];
    //一共64字节,512位      
}MD5_CTX;  
 
 
//第一位1 其后若干个0,用于MD5Final函数时的补足
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};  
 
 
//函数声明
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);  
 
 
/************************
* 函数功能:初始化一个MD5 text
* 函数参数:MD5 text 指针
* ***********************/
//初始化
void MD5Init(MD5_CTX *context)  
{  
    context->count[0] = 0;  
    context->count[1] = 0;   
    //分别赋固定值  
    context->state[0] = 0x67452301;
    context->state[1] = 0xEFCDAB89;  
    context->state[2] = 0x98BADCFE;  
    context->state[3] = 0x10325476;  
}  
 
 
/************************************************
* 函数功能:对一个MD5 text,把输入的数据进行分组,并进行加密
* 未用到的数据把其储存在MD5 text中。
*
* 参数分析:
* MD5_CTX *context       :一个MD5 text   
* unsigned char *input   :新添加的数据  
* unsigned int inputlen  :新添加数据的长度(字节)
*
***********************************************/
 
void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen)  
{  
    unsigned int i = 0,index = 0,partlen = 0;  
 
    //index:当前状态的位数对64取余,其单位是字节
    //也可以写作:  index=(context->count[0]/8)%64
    index = (context->count[0] >> 3) & 0x3F;  
 
    //partlen:可以补齐64字节的字节数
    partlen = 64 - index;
 
    //下面代码是解决一个unsignde int 无法储存极大数据导致溢出的问题
    //当前位数加上新添加的位数,由于inputlen是以字节为单位,所以其转换为位数
    //相当于context->count[0] += inputlen*8;  
    context->count[0] += inputlen << 3;  
 
    //当其出现溢出的情况时,通过以下操作把两个16位的数连在一块,生成一个
    //32位的二进制数串,从而扩大其储存范围
    if(context->count[0] < (inputlen << 3))
    {
        context->count[1]++;
    }
 
    //该语句可替换为 context->count[1]+=(inputlen<<3)>>32;
    //便于理解
    context->count[1] += inputlen >> 29;  
 
    //当其输入字节数的大于其可以补足64字节的字节数,进行补足
    if(inputlen >= partlen)  
    {  
        //向buffer中补足partlen个字节,使其到达64字节
        memcpy(&context->buffer[index], input, partlen);
 
        //buffer达到64字节512位,则把其作为一组进行运算
        MD5Transform(context->state, context->buffer);  
 
        //如果输入的数据还可以组成多个64字节,则把其可以组成
        //的作为若干组进行运算
        for(i = partlen;i+64 <= inputlen;i+=64)  
            MD5Transform(context->state, &input[i]);  
 
        //恢复0值,照应 下面 把输入 剩余字节(不能组成64字节组) 储存的操作
        index = 0;          
    }   
    //否则,把输入的数据按顺序放在原来数据后面
    else  
    {  
        i = 0;  
    }  
 
    //放置剩余数据
    memcpy(&context->buffer[index],&input[i],inputlen-i);  
}  
 
 
/*************************************************
* 函数功能:对数据进行补足,并加入数据位数信息,并进一步加密
* 
* 参数分析:
* MD5_CTX *context          :一个MD5 text
* unsigned char digest[16]  :储存加密结果的数组
*************************************************/
 
void MD5Final(MD5_CTX *context,unsigned char digest[16])  
{  
    unsigned int index = 0,padlen = 0;  
 
    //bits: 8个字节,64位
    unsigned char bits[8];  
 
    //index:对64取余结果
    index = (context->count[0] >> 3) & 0x3F;  
    //因为要填充满足使其位长对512求余的结果等于448(56位)
    //所以当其所剩余的数小于56字节,则填充56-index字节,
    //否则填充120-index字节
    //这里padlen代表其所需填充的字节
    padlen = (index < 56)?(56-index):(120-index);  
 
    //然后,在这个结果后面附加一个以64位二进制表示的填充前数据长度。
    //把填充前数据数据长度转换后放到bit字符数组中
    MD5Encode(bits,context->count,8);
 
    //根据已经存储好的数组PADDING,在信息的后面填充一个1和无数个0,
    //直到满足上面的条件时才停止用0对信息的填充
    //其填充后进行了一系列的加密操作,其定剩余48个字节
    MD5Update(context,PADDING,padlen);  
 
    //在最后添加进8个字节的数据长度信息,最后凑成一组,进行一次加密处理
    MD5Update(context,bits,8);  
 
    //把最终得到的加密信息变成字符输出,共16字节
    MD5Encode(digest,context->state,16);  
}  
 
 
/**********************************************************
* 函数功能:利用位操作,按1->4方式把数字分解成字符
*
* 参数分析:
* unsigned char  *output :输出的字符的数组
* unsigned int   *input  :输入数字的数组
* unsigned int   len     : 输入数字数组的长度(单位:位) 
* *********************************************************/
 
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len)  
{  
    unsigned int i = 0,j = 0;  
    while(j < len)  
    {  
        //这里& 0xFF为取后8位
        //i代表数字数组下标
        //j代表字符数组下标
        //把数字的8、8-16、16-24、24-32分别赋值给字符
        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;  
    }  
}  
 
 
/**********************************************************
* 函数功能:利用位操作,按4->1方式把字符合成数字
*
* 参数分析:
* unsigned int  *output :输出的数字的数组
* unsigned char *input  :输入字符的数组
* unsigned int  len     : 输入字符的长度 (单位:位)
* *********************************************************/
 
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len)  
{  
    unsigned int i = 0,j = 0;  
    while(j < len)  
    {  
        //利用位操作,把四个单位为1字节的字符,合成一个单位为4字节的数字
        //因为FF GG HH II和非线性函数都只能对数字进行处理
        //第一个字符占前8位,第二个占8-16位,第三个占16-24位,第四个占
        //24-32位。
        //i代表数字数组下标
        //j代表字符数组下标
        output[i] = (input[j]) |  
            (input[j+1] << 8) |  
            (input[j+2] << 16) |  
            (input[j+3] << 24);  
        i++;  
        j+=4;   
    }  
}  
 
 
/**************************************************************
* 函数功能:对512位的block数据进行加密,并把加密结果存入state数组中
* 对512位信息(即block字符数组)进行一次处理,每次处理包括四轮
*state[4]:md5结构中的state[4],用于保存对512bits信息加密的中间结果或者最终结果
* block[64]:欲加密的512bits信息或其中间数据
***************************************************************/
void MD5Transform(unsigned int state[4], unsigned char block[64])  
{  
    //a b c d继承上一个加密的结果,所以其具有继承性
    unsigned int a = state[0];  
    unsigned int b = state[1];  
    unsigned int c = state[2];  
    unsigned int d = state[3];  
 
    //这里只需用到16个,我把原来的unsiged int x[64]  改为了 x[16]
    unsigned int x[16];  
 
    //把字符转化成数字,便于运算
    MD5Decode(x,block,64);  
 
 
    //具体函数方式固定,不再赘述
 
    /*************第一轮******************/
    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,  0x2441453);   
    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,  0x4881d05);   
 
    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);   
 
 
    //更换原来的结果
    state[0] += a;  
    state[1] += b;  
    state[2] += c;  
    state[3] += d;  
}
 
 
int main(int argc, char *argv[])  
{  
    MD5_CTX md5;  //定义一个MD5 text
    MD5Init(&md5);//初始化
    int i;
    //unsigned char encrypt[] ="admin";//要加密内容
    //加密结果:21232f297a57a5a743894a0e4a801fc3
 
    unsigned char encrypt[1000];//要加密内容
    printf("请输入要加密的字符串:");
    gets((char *)encrypt);
 
    unsigned char decrypt[16]; //加密结果
    MD5Update(&md5, encrypt, strlen((char *)encrypt));//进行初步分组加密
 
    MD5Final(&md5,decrypt);   //进行后序的补足,并加密 
 
    printf("加密前:%s\n加密后16位:",encrypt);  
    for(i=4;i<12;i++)  
    {  
        printf("%02x",decrypt[i]);
    }  
 
    printf("\n加密前:%s\n加密后32位:",encrypt);  
    for(i=0;i<16;i++)  
    {  
        printf("%02x",decrypt[i]);
    }
    printf("\n");
 
    return 0;  
}  

备注:以上代码转自https://blog.csdn.net/Oliver_xpl/article/details/90214896?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163731312016780357262123%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163731312016780357262123&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-90214896.first_rank_v2_pc_rank_v29&utm_term=MD5%E5%8A%A0%E5%AF%86%E5%8E%9F%E7%90%86&spm=1018.2226.3001.4187

标签:int,unsigned,char,context,lGroup,MD5
来源: https://www.cnblogs.com/georgeyucjr/p/15578334.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有