zoukankan      html  css  js  c++  java
  • MD5算法的c++实现

    需要注意的几点:

    (1)md5存取的数据长度仅为64位,位于数据的最前端,大于令其自然溢出。

    (2)update函数和final函数处理得很繁琐,需要仔细分析。

    (3)16位md5码取32位md5码的中间16位。

    1、Md5.hpp

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    typedef struct{
        unsigned int count[2];
        unsigned int state[4];
        unsigned char buffer[64];
    }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))
    #define ROTATE_LEFT(x,n) ((x<<n)|(x>>(32-n)))
    #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;}
    
    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);

    2、Md5.cpp

    #include "Md5.hpp"
    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){
        context->count[0]=0;
        context->count[1]=0;
        context->state[0]=0x67452301;//链接变量,注意与大端字节序的区别,内存中是小端字节序
        context->state[1]=0xEFCDAB89;
        context->state[2]=0x98BADCFE;
        context->state[3]=0x10325476;
    }
    
    void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen){
        unsigned int i=0,index=0,partlen=0;
        index=(context->count[0]>>3)&0x3F;//模64字节的余数,第一次调用为0
        partlen=64-index;//第一次partlen为64
        //预留最前面的64位存放数据长度
        context->count[0]+=inputlen<<3;//文本总的位数,低32位
        if(context->count[0]<(inputlen<<3)) context->count[1]++;
        context->count[1]+=inputlen>>29;//先左移3,求出位数,再右移32位,求出左32位
        
        if(inputlen>=partlen){
            memcpy(&context->buffer[index], input, partlen);
            MD5Transform(context->state, context->buffer);
            //512位为1组
            for(i=partlen;i+64<=inputlen;i+=64) MD5Transform(context->state,&input[i]);
            index=0;
        }
        else i=0;
        memcpy(&context->buffer[index], &input[i], inputlen-i);//最后剩下的一部分
    }
    
    //32位md5
    void MD5Final(MD5_CTX *context, unsigned char digest[16]){
        unsigned int index=0,padlen=0;
        unsigned char bits[8];
        index=(context->count[0]>>3)&0x3F;//模64字节的余数
        padlen=(index<56)?(56-index):(120-index);//需要填充的长度,注意长度占8字节
        MD5Encode(bits,context->count,8);
        MD5Update(context,PADDING,padlen);
        MD5Update(context,bits,8);//这里调用时,index=0
        MD5Encode(digest,context->state,16);
    }
    
    void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len){
        unsigned int i = 0, j = 0;//len是char的长度
        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;
        }
    }
    
    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;
        }
    }
    
    void MD5Transform(unsigned int state[4], unsigned char block[64]){
        unsigned int a = state[0];
        unsigned int b = state[1];
        unsigned int c = state[2];
        unsigned int d = state[3];
        unsigned int x[16];
        
        MD5Decode(x, block, 64);
        FF(a, b, c, d, x[0], 7, 0xd76aa478);//32位运算
        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;
    }

    3、Test.cpp

    #include "Md5.hpp"
    using namespace std;
    int main(){
        
        int i;
        unsigned char encrypt[] = "admin";//"admin";//21232f297a57a5a743894a0e4a801fc3
        unsigned char decrypt[16];
        
        MD5_CTX md5;
        
        MD5Init(&md5);
        MD5Update(&md5, encrypt, (int)strlen((char *)encrypt));//只是个中间步骤
        MD5Final(&md5, decrypt);//32位
        
        printf("加密前:%s
    加密后16位:",encrypt);
        for (i = 4; i<12; i++){
            printf("%02x", decrypt[i]);
        }
        
        
        printf("
    加密前:%s
    加密后32位:",encrypt);
        for (i = 0; i<16; i++){
            printf("%02x", decrypt[i]);
        }
     
        return 0;
    }
  • 相关阅读:
    Representation Data in OpenCascade BRep
    Render OpenCascade Geometry Surfaces in OpenSceneGraph
    Render OpenCascade Geometry Curves in OpenSceneGraph
    OpenCascade Shape Representation in OpenSceneGraph
    Geometry Surface of OpenCascade BRep
    Geometry Curve of OpenCascade BRep
    Tyvj2017清北冬令营入学测试
    Spfa算法模板
    洛谷1016 旅行家的预算
    洛谷1290 欧几里得的游戏
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7842055.html
Copyright © 2011-2022 走看看