MD5的C++实现

本文详细介绍了MD5的基本概念,并提供了C++实现MD5算法的步骤和关键代码片段,帮助读者理解MD5的计算过程。

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的整数倍,将补充后的数据以512bit分成i个分组,每次的运算都由前一轮的128位结果值和第i块512bit值进行运算。初始的128位值为初试链接变量
需要注意的是端的规则,这让我对此也有了比较深刻的认识
具体详细伪代码过程可百度百科或者维基百科,我的注释应该比较清楚了
/*
*<md5>.cpp Version<1.0> <Oct.23,2013>
*
*copyright(cpp) 2013-2014 <XXX>(SNO:XXXXX).
*all rights reserved. 
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<memory.h>

using namespace std;

//The max length of strings we will deal with
#define MAXLEN 10000

//rename some data types
typedef unsigned int uint32t;
typedef unsigned char byte;

//declare some global variables that will be used in the later
//array k will store const num array( 4294967296*abs(sin(i))intergral part)
uint32t k[64];
int ord[64]={ 7,12,17,22,  7,12,17,22, 7,12,17,22, 7,12,17,22,
            5, 9,14,20,  5, 9,14,20, 5, 9,14,20, 5, 9,14,20,
            4,11,16,23,  4,11,16,23, 4,11,16,23, 4,11,16,23,
            6,10,15,21,  6,10,15,21, 6,10,15,21, 6,10,15,21};
  //ord array store const num in 64 runs

//link variable in the begining
uint32t A=0x67452301,B= 0xefcdab89,C= 0x98badcfe,D= 0x10325476;
//16 byte 16*8=128 bits,will store final information
byte finalMess[16];
//pad array store bits will append to the original data to get length%512=448
//a message will append 1bit at least,append 512 bits at most
//0x80=128=10000000,first bit is 1,others is 0
byte pad[64]={0x80};
//char array will reflcate num to unm system at the base of 16
char Hex[16]=
   {  '0','1','2','3',
      '4','5','6','7',
      '8','9','a','b',
      'c','d','e','f'
   };

//functions statments
void initial();
void encrypt(byte* str,int len);
int changeNumBytes( byte str[],int len);
int changeSourceTobit( char str[],int len);
uint32t F(uint32t a,uint32t b, uint32t c){ return ((a&b)|((~a)&c)) ;}
uint32t G(uint32t a,uint32t b, uint32t c){ return ( (a&c)|(b&(~c)));}
uint32t H(uint32t a,uint32t b, uint32t c){ return a^b^c;}
uint32t I(uint32t a,uint32t b, uint32t c){ return (b^(a|(~c))) ;}
void setBit(uint32t w[],char str[]);
void changeInt2byte(uint32t* input,byte* output,int length );
void changeByte2Int( byte* input,uint32t* ouput, int length);

int main()
{
	//data declaration,source is char array get input
	// s is unsigned char array with the same content of source 
    byte s[MAXLEN];
    char source[MAXLEN];
    int len;

    initial();
	//initial const data

    while(gets(source) )
    {
		//get length of input as bytes;
        len=strlen(source);
		//copy content from source to s
        memcpy(s,source,len);
		//change length of message to len%64==56 bytes
        len=changeNumBytes(s,len);
		//encrypt data using md5 method
        encrypt(s,len);

    }
}

void initial()
{
    
     long long coef=1;
     coef=coef<<32;
    for( int i=0; i<64; i++)
        k[i]=floor( abs( sin(i+1) )*(coef) );
}

//if length>2^32,this wil get error
int changeNumBytes( byte str[],int len)
{
    int add;
    uint32t count[2];//count represent 64bit int of length
    count[0]=len<<3; //len<<3=len*8,the num of bits instead of bytes
    count[1]=0;//I assume length less than 2^32
	
    byte bits[8];
  
    add=len<56?(56-len):(120-len%64);
    memcpy(str+len,pad,add);
	//change count to byte in little-endian
    changeInt2byte(count,bits,8);
    memcpy(str+len+add,bits,8);
    return len+add+8;
}


void encrypt( byte str[], int len)
{
    int n_blocks=len/64;
    int block_ord,i,j;
    uint32t value[4];
    uint32t temp_a=A;
    uint32t temp_b=B;
    uint32t temp_c=C;
    uint32t temp_d=D;

    for( block_ord=0; block_ord<n_blocks; block_ord++)
    {

        uint32t words[16];
        changeByte2Int(str+64*block_ord,words,64);
      
        uint32t a=A,b=B,c=C,d=D;
        uint32t f,g,temp;
        
        for( i=0; i<64; i++)
        {
            if( 0<=i && i<=15)
                f=F(b,c,d),g=i;
            else if( 16<=i && i<32)
                f=G(b,c,d),g=(5*i+1)%16;
            else if( 32<=i && i<48 )
                f=H(b,c,d),g=(3*i+5)%16;
            else
                f=I(b,c,d),g=(7*i)%16;

            temp=d;
            d=c;
            c=b;
            b+=((a+f+k[i]+words[g])<<ord[i] |(a+f+k[i]+words[g])>>(32-ord[i]));
            a=temp;
         
        }
        temp_a+=a;
        temp_b+=b;
        temp_c+=c;
        temp_d+=d;
    }
    value[0]=temp_a;
    value[1]=temp_b;
    value[2]=temp_c;
    value[3]=temp_d;
   
    changeInt2byte(value,finalMess,16);
    for( j=0; j<16; j++)
    {
        cout<<Hex[finalMess[j]/16];
        cout<<Hex[finalMess[j]%16];
    }
    cout<<endl;
  

}

void changeInt2byte(uint32t* input,byte* output, int length)
{
      for(int i=0,j=0;j<length;++i,j+=4)
      {
        output[j]=(byte)(input[i]&(0xff));
         output[j+1]=(byte)(input[i]>>8 & 0xff);
         output[j+2]=(byte)(input[i]>>16 &0xff);
         output[j+3]=(byte)(input[i]>>24 & 0xff);
      }
}

//change byte into 32bit unsigned int as liitle-endian
void changeByte2Int(byte* input, uint32t* output,int length)
{
     for(int i=0,j=0; j<length; ++i,j+=4)
     {
        output[i]= (((uint32t)input[j] ) | (((uint32t)input[j+1] )<<8) |
                       (((uint32t)input[j+2] ) <<16) | (((uint32t)input[j+3])<<24) );
     }
}




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值