0xAA55 发表于 2015-2-28 02:43:01

【C】C语言实现MD5算法

现在MD5已被证实其并不安全了!不过它也还是有些作用的。//=============================================================================
//作者:0xAA55
//网站:http://www.0xaa55.com
//版权所有(C)技术宅的结界 2013-2015
//请保留原作者信息,否则视为侵权
//-----------------------------------------------------------------------------
//rfc1321

#include"md5.h"
#include<memory.h>

//MD5寄存器
typedef struct
{
        uint32_t A;
        uint32_t B;
        uint32_t C;
        uint32_t D;
        uint32_t AA;
        uint32_t BB;
        uint32_t CC;
        uint32_t DD;
}MD5Registers,*MD5RegistersP;

static uint32_t F(uint32_t x,uint32_t y,uint32_t z){return (x&y)|(~x&z);}
static uint32_t G(uint32_t x,uint32_t y,uint32_t z){return (x&z)|(y&~z);}
static uint32_t H(uint32_t x,uint32_t y,uint32_t z){return x^y^z;}
static uint32_t I(uint32_t x,uint32_t y,uint32_t z){return y^(x|~z);}

static uint32_t Rol(uint32_t v,uint8_t Count){return (v<<Count)|(v>>(32-Count));}

static uint32_t FF(uint32_t a,uint32_t b,uint32_t c,uint32_t d,
                                   uint32_t X,uint32_t s,uint32_t T)
{return b+Rol((a+F(b,c,d)+X+T),s);}
static uint32_t GG(uint32_t a,uint32_t b,uint32_t c,uint32_t d,
                                   uint32_t X,uint32_t s,uint32_t T)
{return b+Rol((a+G(b,c,d)+X+T),s);}
static uint32_t HH(uint32_t a,uint32_t b,uint32_t c,uint32_t d,
                                   uint32_t X,uint32_t s,uint32_t T)
{return b+Rol((a+H(b,c,d)+X+T),s);}
static uint32_t II(uint32_t a,uint32_t b,uint32_t c,uint32_t d,
                                   uint32_t X,uint32_t s,uint32_t T)
{return b+Rol((a+I(b,c,d)+X+T),s);}

//=============================================================================
//函数:InitRegs
//描述:初始化MD5寄存器
//-----------------------------------------------------------------------------
static void InitRegs(MD5RegistersP pReg)
{
        //初始4个32位寄存器
        pReg->A=0x67452301;
        pReg->B=0xEFCDAB89;
        pReg->C=0x98BADCFE;
        pReg->D=0x10325476;
}

//=============================================================================
//函数:DigestChunk
//描述:将一个64字节的“块”作为数据压入计算
//-----------------------------------------------------------------------------
static void DigestChunk(MD5RegistersP pReg,void*pData)
{
#        define p ((uint32_t*)pData)
        pReg->AA=pReg->A;
        pReg->BB=pReg->B;
        pReg->CC=pReg->C;
        pReg->DD=pReg->D;

        pReg->A=FF(pReg->A,pReg->B,pReg->C,pReg->D,p,0x07,0xD76AA478);
        pReg->D=FF(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0C,0xE8C7B756);
        pReg->C=FF(pReg->C,pReg->D,pReg->A,pReg->B,p,0x11,0x242070DB);
        pReg->B=FF(pReg->B,pReg->C,pReg->D,pReg->A,p,0x16,0xC1BDCEEE);
        pReg->A=FF(pReg->A,pReg->B,pReg->C,pReg->D,p,0x07,0xF57C0FAF);
        pReg->D=FF(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0C,0x4787C62A);
        pReg->C=FF(pReg->C,pReg->D,pReg->A,pReg->B,p,0x11,0xA8304613);
        pReg->B=FF(pReg->B,pReg->C,pReg->D,pReg->A,p,0x16,0xFD469501);
        pReg->A=FF(pReg->A,pReg->B,pReg->C,pReg->D,p,0x07,0x698098D8);
        pReg->D=FF(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0C,0x8B44F7AF);
        pReg->C=FF(pReg->C,pReg->D,pReg->A,pReg->B,p,0x11,0xFFFF5BB1);
        pReg->B=FF(pReg->B,pReg->C,pReg->D,pReg->A,p,0x16,0x895CD7BE);
        pReg->A=FF(pReg->A,pReg->B,pReg->C,pReg->D,p,0x07,0x6B901122);
        pReg->D=FF(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0C,0xFD987193);
        pReg->C=FF(pReg->C,pReg->D,pReg->A,pReg->B,p,0x11,0xA679438E);
        pReg->B=FF(pReg->B,pReg->C,pReg->D,pReg->A,p,0x16,0x49B40821);

        pReg->A=GG(pReg->A,pReg->B,pReg->C,pReg->D,p,0x05,0xF61E2562);
        pReg->D=GG(pReg->D,pReg->A,pReg->B,pReg->C,p,0x09,0xC040B340);
        pReg->C=GG(pReg->C,pReg->D,pReg->A,pReg->B,p,0x0E,0x265E5A51);
        pReg->B=GG(pReg->B,pReg->C,pReg->D,pReg->A,p,0x14,0xE9B6C7AA);
        pReg->A=GG(pReg->A,pReg->B,pReg->C,pReg->D,p,0x05,0xD62F105D);
        pReg->D=GG(pReg->D,pReg->A,pReg->B,pReg->C,p,0x09,0x02441453);
        pReg->C=GG(pReg->C,pReg->D,pReg->A,pReg->B,p,0x0E,0xD8A1E681);
        pReg->B=GG(pReg->B,pReg->C,pReg->D,pReg->A,p,0x14,0xE7D3FBC8);
        pReg->A=GG(pReg->A,pReg->B,pReg->C,pReg->D,p,0x05,0x21E1CDE6);
        pReg->D=GG(pReg->D,pReg->A,pReg->B,pReg->C,p,0x09,0xC33707D6);
        pReg->C=GG(pReg->C,pReg->D,pReg->A,pReg->B,p,0x0E,0xF4D50D87);
        pReg->B=GG(pReg->B,pReg->C,pReg->D,pReg->A,p,0x14,0x455A14ED);
        pReg->A=GG(pReg->A,pReg->B,pReg->C,pReg->D,p,0x05,0xA9E3E905);
        pReg->D=GG(pReg->D,pReg->A,pReg->B,pReg->C,p,0x09,0xFCEFA3F8);
        pReg->C=GG(pReg->C,pReg->D,pReg->A,pReg->B,p,0x0E,0x676F02D9);
        pReg->B=GG(pReg->B,pReg->C,pReg->D,pReg->A,p,0x14,0x8D2A4C8A);

        pReg->A=HH(pReg->A,pReg->B,pReg->C,pReg->D,p,0x04,0xFFFA3942);
        pReg->D=HH(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0B,0x8771F681);
        pReg->C=HH(pReg->C,pReg->D,pReg->A,pReg->B,p,0x10,0x6D9D6122);
        pReg->B=HH(pReg->B,pReg->C,pReg->D,pReg->A,p,0x17,0xFDE5380C);
        pReg->A=HH(pReg->A,pReg->B,pReg->C,pReg->D,p,0x04,0xA4BEEA44);
        pReg->D=HH(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0B,0x4BDECFA9);
        pReg->C=HH(pReg->C,pReg->D,pReg->A,pReg->B,p,0x10,0xF6BB4B60);
        pReg->B=HH(pReg->B,pReg->C,pReg->D,pReg->A,p,0x17,0xBEBFBC70);
        pReg->A=HH(pReg->A,pReg->B,pReg->C,pReg->D,p,0x04,0x289B7EC6);
        pReg->D=HH(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0B,0xEAA127FA);
        pReg->C=HH(pReg->C,pReg->D,pReg->A,pReg->B,p,0x10,0xD4EF3085);
        pReg->B=HH(pReg->B,pReg->C,pReg->D,pReg->A,p,0x17,0x04881D05);
        pReg->A=HH(pReg->A,pReg->B,pReg->C,pReg->D,p,0x04,0xD9D4D039);
        pReg->D=HH(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0B,0xE6DB99E5);
        pReg->C=HH(pReg->C,pReg->D,pReg->A,pReg->B,p,0x10,0x1FA27CF8);
        pReg->B=HH(pReg->B,pReg->C,pReg->D,pReg->A,p,0x17,0xC4AC5665);

        pReg->A=II(pReg->A,pReg->B,pReg->C,pReg->D,p,0x06,0xF4292244);
        pReg->D=II(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0A,0x432AFF97);
        pReg->C=II(pReg->C,pReg->D,pReg->A,pReg->B,p,0x0F,0xAB9423A7);
        pReg->B=II(pReg->B,pReg->C,pReg->D,pReg->A,p,0x15,0xFC93A039);
        pReg->A=II(pReg->A,pReg->B,pReg->C,pReg->D,p,0x06,0x655B59C3);
        pReg->D=II(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0A,0x8F0CCC92);
        pReg->C=II(pReg->C,pReg->D,pReg->A,pReg->B,p,0x0F,0xFFEFF47D);
        pReg->B=II(pReg->B,pReg->C,pReg->D,pReg->A,p,0x15,0x85845DD1);
        pReg->A=II(pReg->A,pReg->B,pReg->C,pReg->D,p,0x06,0x6FA87E4F);
        pReg->D=II(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0A,0xFE2CE6E0);
        pReg->C=II(pReg->C,pReg->D,pReg->A,pReg->B,p,0x0F,0xA3014314);
        pReg->B=II(pReg->B,pReg->C,pReg->D,pReg->A,p,0x15,0x4E0811A1);
        pReg->A=II(pReg->A,pReg->B,pReg->C,pReg->D,p,0x06,0xF7537E82);
        pReg->D=II(pReg->D,pReg->A,pReg->B,pReg->C,p,0x0A,0xBD3AF235);
        pReg->C=II(pReg->C,pReg->D,pReg->A,pReg->B,p,0x0F,0x2AD7D2BB);
        pReg->B=II(pReg->B,pReg->C,pReg->D,pReg->A,p,0x15,0xEB86D391);

        pReg->A+=pReg->AA;
        pReg->B+=pReg->BB;
        pReg->C+=pReg->CC;
        pReg->D+=pReg->DD;
}

//=============================================================================
//函数:MD5Sum
//描述:计算MD5校验和,其中pMD5Out接收结果(函数将写入16个字节到pMD5Out)
//-----------------------------------------------------------------------------
void MD5Sum
(
        void                *pData,        //数据指针
        size_t                cbData,        //数据大小(Bytes)
        uint32_t        *pMD5Out//输出MD5
)
{
        MD5Registers Regs={0};
        uint8_t PadBuf={0};//用于计算最后的填充内容的缓冲区
        size_t i;
        size_t cbLast=cbData;

        //=========================================================================
        //MD5算法:
        //第一:数据补充
        //1、将数据看成是bit流,在最后一个bit的后面添加一个1。
        //2、再在数据的后面不断补充0,直到数据的总位数与512求余==448
        //3、将数据的总位数以uint64_t格式补充到最后
        //第二:运算
        //1、初始化MD5寄存器
        //2、将数据划分为n个512 bit的块,对每个块进行DigestChunk运算
        //3、最后将MD5寄存器的值返回

        //初始化MD5寄存器
        InitRegs(&Regs);

        //将数据拆成64字节一个块,先分析逐个块,直到最后一个块(然后再来处理“补齐”)
        for(i=0;i+64<=cbData;i+=64)
        {
                DigestChunk(&Regs,pData);
                (uint8_t*)pData+=64;
                cbLast-=64;
        }

        //如果最后一个块有内容则复制到最后的填充内容的缓冲区
        if(cbData)
                memcpy(PadBuf,pData,cbLast);

        //补充1
        PadBuf=0x80;

        //然后在这个填充数据块的结尾补充[数据的总位数]。

        //如果有空余的空间可用于补充,则补充
        if(cbLast<56)
        {
                *(uint64_t*)&(PadBuf)=(uint64_t)cbData*8;
                DigestChunk(&Regs,PadBuf);
        }
        else//否则再补充56个,然后再补充
        {
                DigestChunk(&Regs,PadBuf);
                memset(PadBuf,0,sizeof(PadBuf));
                *(uint64_t*)&(PadBuf)=(uint64_t)cbData*8;
                DigestChunk(&Regs,PadBuf);
        }

        //最后返回MD5寄存器的值
        pMD5Out=Regs.A;
        pMD5Out=Regs.B;
        pMD5Out=Regs.C;
        pMD5Out=Regs.D;
}以下程序用于计算一个字符串的MD5值。
命令:md5 <string>
BIN:
SRC:
页: [1]
查看完整版本: 【C】C语言实现MD5算法