zoukankan      html  css  js  c++  java
  • 算法系列9《MD5》

     

        MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。

        将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。

       MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。



       对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
       在MD5算法中,首先需要对信息进行填充,使其位长对512求余的结果等于448。因此,信息的位长(Bits Length)将被扩展至N*512+448,N为一个非负整数,N可以是零。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,信息的位长=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。总体流程如下图所示,表示第i个分组,每次的运算都由前一轮的128位结果值和第i块512bit值进行运算。初始的128位值为初试链接变量,这些参数用于第一轮的运算,以大端字节序来表示,他们分别为:A=0x01234567,B=0x89ABCDEF,C=0xFEDCBA98,D=0x76543210。



    C++代码实现






    1. 《MD5.h》


    #pragma once
    
    /* POINTER defines a generic pointer type */ 
    typedef unsigned char *POINTER; 
    
    /* UINT2 defines a two byte word */ 
    typedef unsigned short int UINT2; 
    
    /* UINT4 defines a four byte word */ 
    typedef unsigned long int UINT4; 
    
    class cMd5
    {
    private:
        unsigned int m_Content[16];
        unsigned int m_ContentLen;
        unsigned int m_TotalLen;
        static unsigned int m_T[64];
        unsigned int m_A, m_B, m_C, m_D;
    
    private:
        inline void FF(unsigned int& a, unsigned int b, unsigned int c, unsigned int d, int k, int i, int s);
        inline void GG(unsigned int& a, unsigned int b, unsigned int c, unsigned int d, int k, int i, int s);
        inline void HH(unsigned int& a, unsigned int b, unsigned int c, unsigned int d, int k, int i, int s);
        inline void II(unsigned int& a, unsigned int b, unsigned int c, unsigned int d, int k, int i, int s);
        inline unsigned int roateLeft(unsigned int a, unsigned int c);
        void transform();
    
    
    
    	/* MD5 context. */ 
    	typedef struct _MD5_CTX{ 
    		UINT4 state[4];                                   /* state (ABCD) */ 
    		UINT4 count[2];						/* bit ,2^64(Low before) */ 
    		unsigned char buffer[64];                         /* input buffer */ 
    	} MD5_CTX; 
    
    	void MD5Init (MD5_CTX *); 
    	void MD5Update (MD5_CTX *, unsigned char *, unsigned int); 
    	void MD5Final (unsigned char [16], MD5_CTX *); 
    	void MD5String(char *string, long buflen, char digest[]); 
    
    	static void MD5Transform (UINT4 [4], unsigned char [64]); 
    	static void Encode (unsigned char *, UINT4 *, unsigned int); 
    	static void Decode (UINT4 *, unsigned char *, unsigned int); 
    	static void MD5_memcpy (POINTER, POINTER, unsigned int); 
    	static void MD5_memset (POINTER, int, unsigned int); 
    
    public:
    	cMd5();
    	virtual ~cMd5();
        //initialize
        void beginCal();
        //Show that no longer input data, will add a filling
        void endCal();
        //Is initialized, input data, in endCal call before, can continue to add data
        void addData(unsigned char* data, unsigned int size);
        //End after operation, get the code
        unsigned char* getCode();
        void  clearMemoryHelper(char* p);
    };
    

    2. 《MD5.CPP》


    #include "stdafx.h"
    #include "Md5.h"
    #include <string.h>
    #include <stdio.h>
    
    unsigned int cMd5::m_T[64] = {
              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
              };
    
    cMd5::cMd5()
    {
    
    }
    cMd5::~cMd5()
    {
    
    }
    
    void cMd5::FF(unsigned int& a, unsigned int b, unsigned int c, unsigned int d, int k, int i, int s)
    {
        a = b  +  roateLeft(a  +  ((b & c) | ((~b) & d))  +  m_Content[k]  +  m_T[i], s);
    }
    void cMd5::GG(unsigned int& a, unsigned int b, unsigned int c, unsigned int d, int k, int i, int s)
    {
        a = b  +  roateLeft(a  +  ((b & d) | (c & (~d)))  +  m_Content[k]  +  m_T[i], s);
    }
    void cMd5::HH(unsigned int& a, unsigned int b, unsigned int c, unsigned int d, int k, int i, int s)
    {
        a = b  +  roateLeft(a  +  (b ^ c ^ d)  +  m_Content[k]  +  m_T[i], s);
    }
    void cMd5::II(unsigned int& a, unsigned int b, unsigned int c, unsigned int d, int k, int i, int s)
    {
        a = b  +  roateLeft(a  +  (c ^ (b | (~d)))  +  m_Content[k]  +  m_T[i], s);
    }
    unsigned int cMd5::roateLeft(unsigned int a, unsigned int c)
    {
        return ( (a << c) | (a >> (32-c)) );
    }
    void cMd5::transform()
    {
        unsigned int AA, BB, CC, DD;
        AA = m_A;
        BB = m_B;
        CC = m_C;
        DD = m_D;
        //1 round
        FF(AA, BB, CC, DD, 0, 0, 7);
        FF(DD, AA, BB, CC, 1, 1, 12);
        FF(CC, DD, AA, BB, 2, 2, 17);
        FF(BB, CC, DD, AA, 3, 3, 22);
        FF(AA, BB, CC, DD, 4, 4, 7);
        FF(DD, AA, BB, CC, 5, 5, 12);
        FF(CC, DD, AA, BB, 6, 6, 17);
        FF(BB, CC, DD, AA, 7, 7, 22);
        FF(AA, BB, CC, DD, 8, 8, 7);
        FF(DD, AA, BB, CC, 9, 9, 12);
        FF(CC, DD, AA, BB, 10, 10, 17);
        FF(BB, CC, DD, AA, 11, 11, 22);
        FF(AA, BB, CC, DD, 12, 12, 7);
        FF(DD, AA, BB, CC, 13, 13, 12);
        FF(CC, DD, AA, BB, 14, 14, 17);
        FF(BB, CC, DD, AA, 15, 15, 22);
        //2 round
        GG(AA, BB, CC, DD, 1, 16, 5);
        GG(DD, AA, BB, CC, 6, 17, 9);
        GG(CC, DD, AA, BB, 11, 18, 14);
        GG(BB, CC, DD, AA, 0, 19, 20);
        GG(AA, BB, CC, DD, 5, 20, 5);
        GG(DD, AA, BB, CC, 10, 21, 9);
        GG(CC, DD, AA, BB, 15, 22, 14);
        GG(BB, CC, DD, AA, 4, 23, 20);
        GG(AA, BB, CC, DD, 9, 24, 5);
        GG(DD, AA, BB, CC, 14, 25, 9);
        GG(CC, DD, AA, BB, 3, 26, 14);
        GG(BB, CC, DD, AA, 8, 27, 20);
        GG(AA, BB, CC, DD, 13, 28, 5);
        GG(DD, AA, BB, CC, 2, 29, 9);
        GG(CC, DD, AA, BB, 7, 30, 14);
        GG(BB, CC, DD, AA, 12, 31, 20);
        //3 round
        HH(AA, BB, CC, DD, 5, 32, 4);
        HH(DD, AA, BB, CC, 8, 33, 11);
        HH(CC, DD, AA, BB, 11, 34, 16);
        HH(BB, CC, DD, AA, 14, 35, 23);
        HH(AA, BB, CC, DD, 1, 36, 4);
        HH(DD, AA, BB, CC, 4, 37, 11);
        HH(CC, DD, AA, BB, 7, 38, 16);
        HH(BB, CC, DD, AA, 10, 39, 23);
        HH(AA, BB, CC, DD, 13, 40, 4);
        HH(DD, AA, BB, CC, 0, 41, 11);
        HH(CC, DD, AA, BB, 3, 42, 16);
        HH(BB, CC, DD, AA, 6, 43, 23);
        HH(AA, BB, CC, DD, 9, 44, 4);
        HH(DD, AA, BB, CC, 12, 45, 11);
        HH(CC, DD, AA, BB, 15, 46, 16);
        HH(BB, CC, DD, AA, 2, 47, 23);
        //4 round
        II(AA, BB, CC, DD, 0, 48, 6);
        II(DD, AA, BB, CC, 7, 49, 10);
        II(CC, DD, AA, BB, 14, 50, 15);
        II(BB, CC, DD, AA, 5, 51, 21);
        II(AA, BB, CC, DD, 12, 52, 6);
        II(DD, AA, BB, CC, 3, 53, 10);
        II(CC, DD, AA, BB, 10, 54, 15);
        II(BB, CC, DD, AA, 1, 55, 21);
        II(AA, BB, CC, DD, 8, 56, 6);
        II(DD, AA, BB, CC, 15, 57, 10);
        II(CC, DD, AA, BB, 6, 58, 15);
        II(BB, CC, DD, AA, 13, 59, 21);
        II(AA, BB, CC, DD, 4, 60, 6);
        II(DD, AA, BB, CC, 11, 61, 10);
        II(CC, DD, AA, BB, 2, 62, 15);
        II(BB, CC, DD, AA, 9, 63, 21);
        m_A = m_A  +  AA;
        m_B = m_B  +  BB;
        m_C = m_C  +  CC;
        m_D = m_D  +  DD;
    }
    //initialize
    void cMd5::beginCal()
    {
        memset(m_Content, 0, 64);
        m_ContentLen = 0;
        m_TotalLen = 0;
        m_A = 0x67452301;
        m_B = 0xEFCDAB89;
        m_C = 0x98BADCFE;
        m_D = 0x10325476;
    }
    void cMd5::endCal()
    {
        memset((char*)m_Content  +  m_ContentLen, 0x80, 1);
        if (m_ContentLen < 56){
         memset((char*)m_Content  +  m_ContentLen  +  1, 0, 55 - m_ContentLen);
        }
        else{
         memset((char*)m_Content  +  m_ContentLen  +  1, 0, 63 - m_ContentLen);
         transform();
         memset((char*)m_Content, 0, 56);
        }
        unsigned int h, l;
        h = 0;
        l = m_TotalLen;
        h |= ((l & 0x80000000) >> 31);
        h <<= 1;
        l <<= 1;
        h |= ((l & 0x80000000) >> 31);
        h <<= 1;
        l <<= 1;
        h |= ((l & 0x80000000) >> 31);
        h <<= 1;
        l <<= 1;
        memcpy(m_Content  +  14, &l, 4);
        memcpy(m_Content  +  15, &h, 4);
        transform();
    }
    void cMd5::addData(unsigned char* data, unsigned int size)
    {
        unsigned int i = 0;
        unsigned int remain = 64 - m_ContentLen;
        if (remain > size)
    		remain = size;
        memcpy(((char*)m_Content)  +  m_ContentLen, data, remain);
    		i  += remain;
        m_ContentLen  += remain;
        m_TotalLen  += remain;
        if (m_ContentLen < 64)
    		return;
        transform();
        while (i  +  64 <= size)
    	{
    		memcpy(m_Content, data  +  i, 64);
    		transform();
    		i  += 64;
    		m_TotalLen  += 64;
        }
        m_ContentLen = size - i;
        m_TotalLen  += m_ContentLen;
        memcpy(m_Content, data  +  i, m_ContentLen);
    }
    unsigned char* cMd5::getCode()
    {
        unsigned char * code = new unsigned char[16];
        memcpy(code, &m_A, 4);
        memcpy(code  +  4, &m_B, 4);
        memcpy(code  +  8, &m_C, 4);
        memcpy(code  +  12, &m_D, 4);
        return code;
    }
    void cMd5::clearMemoryHelper(char* p)
    {
        delete []p;
    }
    



    文/yanxin8原创,获取更多信息请访问http://yanxin8.com/278.html





  • 相关阅读:
    数论分块与整除相
    P3254——DP&&入门
    P3384——树链剖分&&模板
    树链剖分模板
    P4145——线段树点修改&&模板题
    P1198最大数——线段树点修改&&模板题
    线段树(四)——两个标记(add和set)
    epoll 知识总结
    C++中的mutable关键字
    [LeetCode] Max Points on a Line
  • 原文地址:https://www.cnblogs.com/iplus/p/4467104.html
Copyright © 2011-2022 走看看