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) );
}
}
本文详细介绍了MD5的基本概念,并提供了C++实现MD5算法的步骤和关键代码片段,帮助读者理解MD5的计算过程。
1491

被折叠的 条评论
为什么被折叠?



