MD5算法

 

#include<stdio.h>

#include<string.h>

#include<math.h>

#include<stdlib.h>

 

//循环左移n位

int cir_left(int source,int n)

{

 unsigned int tmp = source;

 return (tmp << n)|(tmp >> (32-n));

}

 

//transfer char array[] to int array[]

void encode_c2i(char C_array[],int I_array[],int length)

{

 int i,j;

 for(i = 0; i < length; i++)

 {

  I_array[i] = (C_array[i*4]&0x000000ff) + ((C_array[i*4+1]<<8)&0x0000ff00)

     + ((C_array[i*4+2]<<16)&0x00ff0000) + ((C_array[i*4+3]<<24)&0xff000000);

  I_array[i] = 0;

  for(j = 3; j >= 0; j--)

  {

   I_array[i]  = I_array[i] << 8;

   I_array[i] += ((int)C_array[i*4+j])&0x000000ff;

  }

 }

}

//transfer int array[16] to char array[64]

void decode_i2c(int I_array[],char C_array[],int length)

{

 int i;

 for(i = 0; i < length; i++)

 {

  C_array[i*4] = I_array[i];

  C_array[i*4+1] = I_array[i] >> 8;

  C_array[i*4+2] = I_array[i] >> 16;

  C_array[i*4+3] = I_array[i] >> 24;

 }

}

 

 

int fun_F(int in, int y, int z)

{

 return (in&y)|(~(in)&z);

}

int fun_G(int in, int y, int z)

{

 return (in&z)|(y&~(z));

}

int fun_H(int in, int y, int z)

{

 return in^y^z;

}

int fun_I(int in, int y, int z)

{

 return y^(in|~(z));

}

 

 

int fun_FF(int a, int b,int c, int d, int Xk, int s, int Ti)

{

 int tmp;

 tmp = a + fun_F(b,c,d) + Xk + Ti;

 return b + cir_left(tmp,s);

}

int fun_GG(int a, int b,int c, int d, int Xk, int s, int Ti)

{

 int tmp;

 tmp = a + fun_G(b,c,d) + Xk + Ti;

 return b + cir_left(tmp,s);

}

int fun_HH(int a, int b,int c, int d, int Xk, int s, int Ti)

{

 int tmp;

 tmp = a + fun_H(b,c,d) + Xk + Ti;

 return b + cir_left(tmp,s);

}

int fun_II(int a, int b,int c, int d, int Xk, int s, int Ti)

{

 int tmp;

 tmp = a + fun_I(b,c,d) + Xk + Ti;

 return b + cir_left(tmp,s);

}

 

//实现64个字节的转换

void MD5_kerl(int in[16],int out[4],int T[64])

{

 int out_cpy[4];

 int i;

 for(i = 0; i < 4; i++)

 {

  out_cpy[i] = out[i];

 }

 //first loop

 out[0] = fun_FF(out[0],out[1],out[2],out[3],in[0],7,T[0]);

 out[3] = fun_FF(out[3],out[0],out[1],out[2],in[1],12,T[1]);

 out[2] = fun_FF(out[2],out[3],out[0],out[1],in[2],17,T[2]);

 out[1] = fun_FF(out[1],out[2],out[3],out[0],in[3],22,T[3]);

 out[0] = fun_FF(out[0],out[1],out[2],out[3],in[4],7,T[4]);

 out[3] = fun_FF(out[3],out[0],out[1],out[2],in[5],12,T[5]);

 out[2] = fun_FF(out[2],out[3],out[0],out[1],in[6],17,T[6]);

 out[1] = fun_FF(out[1],out[2],out[3],out[0],in[7],22,T[7]);

 out[0] = fun_FF(out[0],out[1],out[2],out[3],in[8],7,T[8]);

 out[3] = fun_FF(out[3],out[0],out[1],out[2],in[9],12,T[9]);

 out[2] = fun_FF(out[2],out[3],out[0],out[1],in[10],17,T[10]);

 out[1] = fun_FF(out[1],out[2],out[3],out[0],in[11],22,T[11]);

 out[0] = fun_FF(out[0],out[1],out[2],out[3],in[12],7,T[12]);

 out[3] = fun_FF(out[3],out[0],out[1],out[2],in[13],12,T[13]);

 out[2] = fun_FF(out[2],out[3],out[0],out[1],in[14],17,T[14]);

 out[1] = fun_FF(out[1],out[2],out[3],out[0],in[15],22,T[15]);

 

 //second loop

 out[0] = fun_GG(out[0],out[1],out[2],out[3],in[1],5,T[16]);

 out[3] = fun_GG(out[3],out[0],out[1],out[2],in[6],9,T[17]);

 out[2] = fun_GG(out[2],out[3],out[0],out[1],in[11],14,T[18]);

 out[1] = fun_GG(out[1],out[2],out[3],out[0],in[0],20,T[19]);

 out[0] = fun_GG(out[0],out[1],out[2],out[3],in[5],5,T[20]);

 out[3] = fun_GG(out[3],out[0],out[1],out[2],in[10],9,T[21]);

 out[2] = fun_GG(out[2],out[3],out[0],out[1],in[15],14,T[22]);

 out[1] = fun_GG(out[1],out[2],out[3],out[0],in[4],20,T[23]);

 out[0] = fun_GG(out[0],out[1],out[2],out[3],in[9],5,T[24]);

 out[3] = fun_GG(out[3],out[0],out[1],out[2],in[14],9,T[25]);

 out[2] = fun_GG(out[2],out[3],out[0],out[1],in[3],14,T[26]);

 out[1] = fun_GG(out[1],out[2],out[3],out[0],in[8],20,T[27]);

 out[0] = fun_GG(out[0],out[1],out[2],out[3],in[13],5,T[28]);

 out[3] = fun_GG(out[3],out[0],out[1],out[2],in[2],9,T[29]);

 out[2] = fun_GG(out[2],out[3],out[0],out[1],in[7],14,T[30]);

 out[1] = fun_GG(out[1],out[2],out[3],out[0],in[12],20,T[31]);

 //third loop

 out[0] = fun_HH(out[0],out[1],out[2],out[3],in[5],4,T[32]);

 out[3] = fun_HH(out[3],out[0],out[1],out[2],in[8],11,T[33]);

 out[2] = fun_HH(out[2],out[3],out[0],out[1],in[11],16,T[34]);

 out[1] = fun_HH(out[1],out[2],out[3],out[0],in[14],23,T[35]);

 out[0] = fun_HH(out[0],out[1],out[2],out[3],in[1],4,T[36]);

 out[3] = fun_HH(out[3],out[0],out[1],out[2],in[4],11,T[37]);

 out[2] = fun_HH(out[2],out[3],out[0],out[1],in[7],16,T[38]);

 out[1] = fun_HH(out[1],out[2],out[3],out[0],in[10],23,T[39]);

 out[0] = fun_HH(out[0],out[1],out[2],out[3],in[13],4,T[40]);

 out[3] = fun_HH(out[3],out[0],out[1],out[2],in[0],11,T[41]);

 out[2] = fun_HH(out[2],out[3],out[0],out[1],in[3],16,T[42]);

 out[1] = fun_HH(out[1],out[2],out[3],out[0],in[6],23,T[43]);

 out[0] = fun_HH(out[0],out[1],out[2],out[3],in[9],4,T[44]);

 out[3] = fun_HH(out[3],out[0],out[1],out[2],in[12],11,T[45]);

 out[2] = fun_HH(out[2],out[3],out[0],out[1],in[15],16,T[46]);

 out[1] = fun_HH(out[1],out[2],out[3],out[0],in[2],23,T[47]);

 //fourth loop

 out[0] = fun_II(out[0],out[1],out[2],out[3],in[0],6,T[48]);

 out[3] = fun_II(out[3],out[0],out[1],out[2],in[7],10,T[49]);

 out[2] = fun_II(out[2],out[3],out[0],out[1],in[14],15,T[50]);

 out[1] = fun_II(out[1],out[2],out[3],out[0],in[5],21,T[51]);

 out[0] = fun_II(out[0],out[1],out[2],out[3],in[12],6,T[52]);

 out[3] = fun_II(out[3],out[0],out[1],out[2],in[3],10,T[53]);

 out[2] = fun_II(out[2],out[3],out[0],out[1],in[10],15,T[54]);

 out[1] = fun_II(out[1],out[2],out[3],out[0],in[1],21,T[55]);

 out[0] = fun_II(out[0],out[1],out[2],out[3],in[8],6,T[56]);

 out[3] = fun_II(out[3],out[0],out[1],out[2],in[15],10,T[57]);

 out[2] = fun_II(out[2],out[3],out[0],out[1],in[6],15,T[58]);

 out[1] = fun_II(out[1],out[2],out[3],out[0],in[13],21,T[59]);

 out[0] = fun_II(out[0],out[1],out[2],out[3],in[4],6,T[60]);

 out[3] = fun_II(out[3],out[0],out[1],out[2],in[11],10,T[61]);

 out[2] = fun_II(out[2],out[3],out[0],out[1],in[2],15,T[62]);

 out[1] = fun_II(out[1],out[2],out[3],out[0],in[9],21,T[63]);

 for(i = 0; i < 4; i++)

 {

  out[i] += out_cpy[i];

 }

 

}

 

//获取T数组

void get_T_Array(int T[64])

{

 int i,tmp;

 for(i = 0; i < 64; i++)

 {

  tmp = 1;

  tmp = tmp << 16;

  T[i] = (unsigned int)(fabs(sin((double)i+1)) * tmp * tmp);

 

 }

}

//输入明文,返回密文,通过参数返回密文长度

char* MD5_fun(char* str_plain, int* o_len)

{

 int len;

 int len_bit;

 char* str_padding;

 char * str_cypher;

 int len_cypher;

 int len_padding;

 int i;

 int j;

 int T[64];

 int in[16];

 int out[4];

 char* tmp1 = (char*)malloc(64);

 char* tmp2 = (char*)malloc(16);

 len = strlen(str_plain);

 if(len % 64 > 56)

 {

  len_padding = (len/64 + 2) * 64;//?

 }

 else

 {

  len_padding =  (len/64 + 1) * 64;

 }

 str_padding = (char*)malloc(len_padding);

 len_cypher = len_padding / 4;//?

 str_cypher = (char*)malloc(len_cypher);

 for(i = 0; i < len; i++)

 {

  str_padding[i] = str_plain[i];

 }

 str_padding[len] = 0x80;

 for(i = len+1; i < len_padding; i++)

 {

  str_padding[i] = 0;

 }

 

 len_bit = len * 8;

 str_padding[len_padding-8] = len_bit ;

 str_padding[len_padding-7] = len_bit >> 8;

 str_padding[len_padding-6] = len_bit >> 16;

 str_padding[len_padding-5] = len_bit >> 24;

 get_T_Array(T);

 for(i = 0; i < len_padding / 64; i++)

 {

  for(j = 0; j < 64; j++)

  {

   tmp1[j] = str_padding[i*64+j];

  }

  encode_c2i(tmp1,in,16);

  out[0] = 0x67452301;

  out[1] = 0xefcdab89;

  out[2] = 0x98badcfe;

  out[3] = 0x10325476;

  MD5_kerl(in,out,T);

 

  decode_i2c(out,tmp2,4);

  for(j = 0; j < 16; j++)

  {

   str_cypher[i*16+j] = tmp2[j];

  }

 }

 *o_len = len_cypher;

 return str_cypher;

 

}

 

 

int main()

{

 int v1,v2,len;

 int i;

 char* result = MD5_fun("abc",&len);

 

 //以十六进制的形式输出密文

 for(i = 0; i < len; i++)

 {

  v1 = result[i] & 0x000000ff;

  v2 = v1 >> 4;

  v1 = v1 & 0x0000000f;

  if(v2 >= 10)

  {

   printf("%c",0x61-10+v2);

  }

  else

  {

   printf("%c",0x30+v2);

  }

  if(v1 >= 10)

  {

   printf("%c",0x61-10+v1);

  }

  else

  {

   printf("%c",0x30+v1);

  }

 }

 

 

 return 0;

}

 

 

 

 

 

我们假设有一段b位的信息输入,并且我们想要找到他的信息摘要。这里b是一个任意
    的无符号整数;b可能为0;它不一定是8的倍数,也可能是任意大的长度。我们假想
    信息串的比特流如下:

    m_0 m_1...m_(b-1)

    接下来的5个步骤描述了如何计算该信息的摘要。

3.1 附加填充位

    消息需要进行填充,使得它的长度(位)对512求余为448,即消息的长度加上64比特
    后刚好是512的整数倍。填充是必需进行的,即使消息的长度对512求余的结果已经是
    448。

    填充规则如下:先填充一比特的“1”,然后一直填充“0”,直到消息的长度对512求余
    的结果是448。总共,至少要填充1比特,最多填充512比特。
3.2 附加长度    一个64位的无符号整数b(消息被填充前的长度)被附加在先前被填充的消息后面。如
    果b的实际长度超过64位,只附加b的低64位(这些比特会被放在两个32位的字中填充的时候按照先前的约定,低位优先)。    此时,目标消息(被填充了附加位和长度b)的长度刚好是512比特的整数倍。即,消息
    的长度刚好是16个字(32位)的整数倍。定义M[0 ... N-1]为目标消息的字串,N是16
    的整数倍。

3.3 初始化MD缓存    一个4个字的缓存(A,B,C,D)被用于计算消息的摘要。这里每一个A,B,C,D都是一个32
    位的寄存器。这些寄存器使用如下的16进制的值进行初始化(低位优先):    A : 01 23 45 67
    B : 89 ab cd ef
    C : fe dc ba 98
    D : 76 54 32 10

3.4 16个字一组处理消息

    我们首先定义4个辅助函数,每个函数的输入是3个32位的字,输出是1个32位的字。

    F(X,Y,Z) = XY v not(x) Z
    G(X,Y,Z) = XZ v Y not(Z)
    H(X,Y,Z) = X xor Y xor Z

I(X,Y,Z) = Y xor (X v not(Z))

    在每一个比特位置,F有约束:如果X则Y,否则Z。(函数F中 v 可以被符号 + 替代,
    因为 XY 与 not(x) Z 不可能再同一个比特位置上都为“1”) 注意到如果比特流X,Y
    和Z是各自独立的和公正的,则F(X,Y,Z)的每个比特也是各自独立的和公正的。

    函数G,H和I与函数F相类似,它们都是“按位平行”从X,Y,Z比特流中产生输出,这
    样的方式使得如果X,Y,Z对应的比特是各自独立的和公正的,则G(X,Y,Z), H(X,Y,Z),
    I(X,Y,Z)的每个比特也是各自独立的和公正的。注意到函数H是一个对输入进行按位异
    或或等于的函数(译者注:原文Note that the function H is the bit-wise "xor" or
    "parity" function of its inputs)。


    这一步需要用到一个64位的常数组T[1...64],它有sine函数构造。定义T[i]位常数
    组中的第i个元素,它的值等于经过4294967296次abs(sin(i))后的值的整数部分(其
    中i是弧度 )。数组元素在附录中给出。

         过程如下:


         /*16个字节一组处理*/
    For i=0 to N/16-1 do

        /*把第i组放入X中*/
        For j=0 to 15 do
            Set x[j] to M[i*16+j]
        end/*j的循环*/

        /*将A存入AA,B存入BB,C存入CC,D存入DD*/
        AA = A
        BB = B
        CC = C
        DD = D

        /*第一次循环*/
        /*定义[abcd k s i]为操作
          a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s )*/
        /*执行16次操作*/
        [ABCD  0 7  1] [DABC  1 12  2] [CDAB  2 17  3] [BCDA  3 22  4]

[ABCD  4 7  5] [DABC  5 12  6] [CDAB  6 17  7] [BCDA  7 22  8]

[ABCD  8 7  9] [DABC  9 12 10] [CDAB 10 17 11] [BCDA 11 22 12]

[ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]

/*第二次循环*/
/*定义[abcd k s i]为操作
 a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s )*/
/*执行16次操作*/
[ABCD  1 5 17] [DABC  6 9 18] [CDAB 11 14 19] [BCDA  0 20 20]

[ABCD  5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA  4 20 24]

[ABCD  9 5 25] [DABC 14 9 26] [CDAB  3 14 27] [BCDA  8 20 28]

[ABCD 13 5 29] [DABC  2 9 30] [CDAB  7 14 31] [BCDA 12 20 32]

    /*第三次循环*/
    /*定义[abcd k s i]为操作
      a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s )*/
    /*执行16次操作*/
    [ABCD  5 4 33] [DABC  8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]

[ABCD  1 4 37] [DABC  4 11 38] [CDAB  7 16 39] [BCDA 10 23 40]

[ABCD 13 4 41] [DABC  0 11 42] [CDAB  3 16 43] [BCDA  6 23 44]

[ABCD  9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA  2 23 48]

    /*第四次循环*/
    /*定义[abcd k s i]为操作
      a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s )*/
    /*执行16次操作*/
    [ABCD  0 6 49] [DABC  7 10 50] [CDAB 14 15 51] [BCDA  5 21 52]

[ABCD 12 6 53] [DABC  3 10 54] [CDAB 10 15 55] [BCDA  1 21 56]

[ABCD  8 6 57] [DABC 15 10 58] [CDAB  6 15 59] [BCDA 13 21 60]

[ABCD  4 6 61] [DABC 11 10 62] [CDAB  2 15 63] [BCDA  9 21 64]

    /*然后进行如下加法操作。(增加四个寄存器的值)*/

    A = A + AA

B = B + BB

C = C + CC

D = D + DD

end/*i的循环*/


3.5 输出

    信息摘要产生后输出的形式为A,B,C,D。即,以A为低位字节开头,D为高位字节结束。

    这些就是MD5的完整描述。在附录中有以C语言实现的一个例子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值