安全访问认证 MD5 个人

安全访问认证

        MD5还广泛用于操作系统的登陆认证上,如Unix、各类BSD系统登录密码、数字签名等诸多方面。如在Unix系统中用户的密码是以MD5(或其它类似的算法)经Hash运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这可以避免用户的密码被具有系统管理员权限的用户知道。MD5将任意长度的“字节串”映射为一个128bit的大整数,并且是通过该128bit反推原始字符串是困难的,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。所以,要遇到了md5密码的问题,比较好的办法是:你可以用这个系统中的md5()函数重新设一个密码,如admin,把生成的一串密码的Hash值覆盖原来的Hash值就行了。

        正是因为这个原因,现在被黑客使用最多的一种破译密码的方法就是一种被称为"跑字典"的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用MD5程序计算出这些字典项的MD5值,然后再用目标的MD5值在这个字典中检索。我们假设密码的最大长度为8位字节(8 Bytes),同时密码只能是字母和数字,共26+26+10=62个字节,排列组合出的字典的项数则是P(62,1)+P(62,2)….+P(62,8),那也已经是一个很天文的数字了,存储这个字典就需要TB级的磁盘阵列,而且这种方法还有一个前提,就是能获得目标账户的密码MD5值的情况下才可以。这种加密技术被广泛的应用于Unix系统中,这也是为什么Unix系统比一般操作系统更为坚固一个重要原因。

C++实现

#include<iostream>
#include<string>
using  namespace  std;
#define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))//右移的时候,高位一定要补零,而不是补充符号位
#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 A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476
//strBaye的长度
unsigned  int  strlength;
//A,B,C,D的临时变量
unsigned  int  atemp;
unsigned  int  btemp;
unsigned  int  ctemp;
unsigned  int  dtemp;
//常量ti unsigned int(abs(sin(i+1))*(2pow32))
const  unsigned  int  k[]={
         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};
//向左位移数
const  unsigned  int  s[]={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};
const  char  str16[]= "0123456789abcdef" ;
void  mainLoop(unsigned  int  M[])
{
     unsigned  int  f,g;
     unsigned  int  a=atemp;
     unsigned  int  b=btemp;
     unsigned  int  c=ctemp;
     unsigned  int  d=dtemp;
     for  (unsigned  int  i = 0; i < 64; i++)
     {
         if (i<16){
             f=F(b,c,d);
             g=i;
         } else  if  (i<32)
         {
             f=G(b,c,d);
             g=(5*i+1)%16;
         } else  if (i<48){
             f=H(b,c,d);
             g=(3*i+5)%16;
         } else {
             f=I(b,c,d);
             g=(7*i)%16;
         }
         unsigned  int  tmp=d;
         d=c;
         c=b;
         b=b+shift((a+f+k[i]+M[g]),s[i]);
         a=tmp;
     }
     atemp=a+atemp;
     btemp=b+btemp;
     ctemp=c+ctemp;
     dtemp=d+dtemp;
}
/*
*填充函数
*处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
*填充方式为先加一个1,其它位补零
*最后加上64位的原来长度
*/
unsigned  int * add(string str)
{
     unsigned  int  num=((str.length()+8)/64)+1; //以512位,64个字节为一组
     unsigned  int  *strByte= new  unsigned  int [num*16];     //64/4=16,所以有16个整数
     strlength=num*16;
     for  (unsigned  int  i = 0; i < num*16; i++)
         strByte[i]=0;
     for  (unsigned  int  i=0; i <str.length(); i++)
     {
         strByte[i>>2]|=(str[i])<<((i%4)*8); //一个整数存储四个字节,i>>2表示i/4 一个unsigned int对应4个字节,保存4个字符信息
     }
     strByte[str.length()>>2]|=0x80<<(((str.length()%4))*8); //尾部添加1 一个unsigned int保存4个字符信息,所以用128左移
     /*
     *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位
     */
     strByte[num*16-2]=str.length()*8;
     return  strByte;
}
string changeHex( int  a)
{
     int  b;
     string str1;
     string str= "" ;
     for ( int  i=0;i<4;i++)
     {
         str1= "" ;
         b=((a>>i*8)%(1<<8))&0xff;    //逆序处理每个字节
         for  ( int  j = 0; j < 2; j++)
         {
             str1.insert(0,1,str16[b%16]);
             b=b/16;
         }
         str+=str1;
     }
     return  str;
}
string getMD5(string source)
{
     atemp=A;     //初始化
     btemp=B;
     ctemp=C;
     dtemp=D;
     unsigned  int  *strByte=add(source);
     for (unsigned  int  i=0;i<strlength/16;i++)
     {
         unsigned  int  num[16];
         for (unsigned  int  j=0;j<16;j++)
             num[j]=strByte[i*16+j];
         mainLoop(num);
     }
     return  changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp));
}
unsigned  int  main()
{
     string ss;
//    cin>>ss;
     string s=getMD5( "abc" );
     cout<<s;
     return  0;
}

JAVA实现

public  class  MD5{
     /*
     *四个链接变量
     */
     private  final  int  A= 0x67452301 ;
     private  final  int  B= 0xefcdab89 ;
     private  final  int  C= 0x98badcfe ;
     private  final  int  D= 0x10325476 ;
     /*
     *ABCD的临时变量
     */
     private  int  Atemp,Btemp,Ctemp,Dtemp;
     
     /*
     *常量ti
     *公式:floor(abs(sin(i+1))×(2pow32)
     */
     private  final  int  K[]={
         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 };
     /*
     *向左位移数,计算方法未知
     */
     private  final  int  s[]={ 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 };
     
     
     /*
     *初始化函数
     */
     private  void  init(){
         Atemp=A;
         Btemp=B;
         Ctemp=C;
         Dtemp=D;
     }
     /*
     *移动一定位数
     */
     private     int     shift( int  a, int  s){
         return (a<<s)|(a>>>( 32 -s)); //右移的时候,高位一定要补零,而不是补充符号位
     }
     /*
     *主循环
     */
     private  void  MainLoop( int  M[]){
         int  F,g;
         int  a=Atemp;
         int  b=Btemp;
         int  c=Ctemp;
         int  d=Dtemp;
         for ( int  i =  0 ; i <  64 ; i ++){
             if (i< 16 ){
                 F=(b&c)|((~b)&d);
                 g=i;
             } else  if (i< 32 ){
                 F=(d&b)|((~d)&c);
                 g=( 5 *i+ 1 )% 16 ;
             } else  if (i< 48 ){
                 F=b^c^d;
                 g=( 3 *i+ 5 )% 16 ;
             } else {
                 F=c^(b|(~d));
                 g=( 7 *i)% 16 ;
             }
             int  tmp=d;
             d=c;
             c=b;
             b=b+shift(a+F+K[i]+M[g],s[i]);
             a=tmp;
         }
         Atemp=a+Atemp;
         Btemp=b+Btemp;
         Ctemp=c+Ctemp;
         Dtemp=d+Dtemp;
     
     }
     /*
     *填充函数
     *处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
     *填充方式为先加一个0,其它位补零
     *最后加上64位的原来长度
     */
     private  int [] add(String str){
         int  num=((str.length()+ 8 )/ 64 )+ 1 ; //以512位,64个字节为一组
         int  strByte[]= new  int [num* 16 ]; //64/4=16,所以有16个整数
         for ( int  i= 0 ;i<num* 16 ;i++){ //全部初始化0
             strByte[i]= 0 ;
         }
         int     i;
         for (i= 0 ;i<str.length();i++){
             strByte[i>> 2 ]|=str.charAt(i)<<((i% 4 )* 8 ); //一个整数存储四个字节,小端序
         }
         strByte[i>> 2 ]|= 0x80 <<((i% 4 )* 8 ); //尾部添加1
         /*
         *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位
         */
         strByte[num* 16 - 2 ]=str.length()* 8 ;
             return  strByte;
     }
     /*
     *调用函数
     */
     public  String getMD5(String source){
         init();
         int  strByte[]=add(source);
         for ( int  i= 0 ;i<strByte.length/ 16 ;i++){
         int  num[]= new  int [ 16 ];
         for ( int  j= 0 ;j< 16 ;j++){
             num[j]=strByte[i* 16 +j];
         }
         MainLoop(num);
         }
         return  changeHex(Atemp)+changeHex(Btemp)+changeHex(Ctemp)+changeHex(Dtemp);
     
     }
     /*
     *整数变成16进制字符串
     */
     private  String changeHex( int  a){
         String str= "" ;
         for ( int  i= 0 ;i< 4 ;i++){
             str+=String.format( "%2s" , Integer.toHexString(((a>>i* 8 )%( 1 << 8 ))& 0xff )).replace( ' ' '0' );
 
         }
         return  str;
     }
     /*
     *单例
     */
     private  static  MD5 instance;
     public  static  MD5 getInstance(){
         if (instance== null ){
             instance= new  MD5();
         }
         return  instance;
     }
     
     private  MD5(){};
     
     public  static  void  main(String[] args){
         String str=MD5.getInstance().getMD5( "" );
         System.out.println(str);
     }
}

VB2010实现

Imports  System
 
Imports  System.Security.Cryptography
 
Imports  System.Text
 
 
Module  Example
     '哈希输入字符串并返回一个 32 字符的十六进制字符串哈希。
 
     Function  GetMd5Hash( ByVal  input  As  String As  String
 
         '创建新的一个 MD5CryptoServiceProvider 对象的实例。
 
         Dim  md5Hasher  As  New  MD5CryptoServiceProvider()
 
         '输入的字符串转换为字节数组,并计算哈希。
 
         Dim  data  As  Byte () = md5Hasher.ComputeHash(Encoding. Default .GetBytes(input))
 
         '创建一个新的 StringBuilder 收集的字节,并创建一个字符串。
 
         Dim  sBuilder  As  New  StringBuilder()
 
         '通过每个字节的哈希数据和格式为十六进制字符串的每一个循环。
 
         For  As  Integer  = 0  To  data.Length - 1
 
             sBuilder.Append(data(i).ToString( "x2" ))
 
         Next
 
         '返回十六进制字符串。
 
         Return  sBuilder.ToString()
 
     End  Function
 
 
     '验证对一个字符串的哈希值。
 
     Function  VerifyMd5Hash( ByVal  input  As  String ByVal  hash  As  String As  Boolean
 
         '哈希的输入。
 
         Dim  hashOfInput  As  String  = GetMd5Hash(input)
 
         '创建 StringComparer 的哈希进行比较。
 
         Dim  comparer  As  StringComparer = StringComparer.OrdinalIgnoreCase
 
         Return  comparer.Compare(hashOfInput, hash) = 0
 
     End  Function
 
 
     Sub  Main()
 
         Dim  source  As  String  "Hello World!"
 
         Dim  hash  As  String  = GetMd5Hash(source)
 
         Console.WriteLine($ "进行MD5加密的字符串为:{source},加密的结果是:{hash}。" )
 
         Console.WriteLine( "正在验证哈希……" )
 
         If  VerifyMd5Hash(source, hash)  Then
 
             Console.WriteLine("哈希值是
相同的。")
 
Else
 
             Console.WriteLine( "哈希值是不相同的。" )
 
EndIf
 
     EndSub
 
EndModule
 
 
'此代码示例产生下面的输出:
 
 
'进行MD5加密的字符串为:Hello World!,加密的结果是:ed076287532e86365e841e92bfc50d8c。
 
'正在验证哈希……
 
'哈希值是相同的。

JavaScript实现

unction  md5(string) {
     function  md5_RotateLeft(lValue, iShiftBits) {
         return  (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
     }
     function  md5_AddUnsigned(lX, lY) {
         var  lX4, lY4, lX8, lY8, lResult;
         lX8 = (lX & 0x80000000);
         lY8 = (lY & 0x80000000);
         lX4 = (lX & 0x40000000);
         lY4 = (lY & 0x40000000);
         lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
         if  (lX4 & lY4) {
             return  (lResult ^ 0x80000000 ^ lX8 ^ lY8);
         }
         if  (lX4 | lY4) {
             if  (lResult & 0x40000000) {
                 return  (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
             else  {
                 return  (lResult ^ 0x40000000 ^ lX8 ^ lY8);
             }
         else  {
             return  (lResult ^ lX8 ^ lY8);
         }
     }
     function  md5_F(x, y, z) {
         return  (x & y) | ((~x) & z);
     }
     function  md5_G(x, y, z) {
         return  (x & z) | (y & (~z));
     }
     function  md5_H(x, y, z) {
         return  (x ^ y ^ z);
     }
     function  md5_I(x, y, z) {
         return  (y ^ (x | (~z)));
     }
     function  md5_FF(a, b, c, d, x, s, ac) {
         a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_F(b, c, d), x), ac));
         return  md5_AddUnsigned(md5_RotateLeft(a, s), b);
     };
     function  md5_GG(a, b, c, d, x, s, ac) {
         a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_G(b, c, d), x), ac));
         return  md5_AddUnsigned(md5_RotateLeft(a, s), b);
     };
     function  md5_HH(a, b, c, d, x, s, ac) {
         a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_H(b, c, d), x), ac));
         return  md5_AddUnsigned(md5_RotateLeft(a, s), b);
     };
     function  md5_II(a, b, c, d, x, s, ac) {
         a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_I(b, c, d), x), ac));
         return  md5_AddUnsigned(md5_RotateLeft(a, s), b);
     };
     function  md5_ConvertToWordArray(string) {
         var  lWordCount;
         var  lMessageLength = string.length;
         var  lNumberOfWords_temp1 = lMessageLength + 8;
         var  lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
         var  lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
         var  lWordArray = Array(lNumberOfWords - 1);
         var  lBytePosition = 0;
         var  lByteCount = 0;
         while  (lByteCount < lMessageLength) {
             lWordCount = (lByteCount - (lByteCount % 4)) / 4;
             lBytePosition = (lByteCount % 4) * 8;
             lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
             lByteCount++;
         }
         lWordCount = (lByteCount - (lByteCount % 4)) / 4;
         lBytePosition = (lByteCount % 4) * 8;
         lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
         lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
         lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
         return  lWordArray;
     };
     function  md5_WordToHex(lValue) {
         var  WordToHexValue =  "" ,
         WordToHexValue_temp =  "" ,
         lByte, lCount;
         for  (lCount = 0; lCount <= 3; lCount++) {
             lByte = (lValue >>> (lCount * 8)) & 255;
             WordToHexValue_temp =  "0"  + lByte.toString(16);
             WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
         }
         return  WordToHexValue;
     };
     function  md5_Utf8Encode(string) {
         string = string.replace(/\r\n/g,  "\n" );
         var  utftext =  "" ;
         for  ( var  n = 0; n < string.length; n++) {
             var  c = string.charCodeAt(n);
             if  (c < 128) {
                 utftext += String.fromCharCode(c);
             else  if  ((c > 127) && (c < 2048)) {
                 utftext += String.fromCharCode((c >> 6) | 192);
                 utftext += String.fromCharCode((c & 63) | 128);
             else  {
                 utftext += String.fromCharCode((c >> 12) | 224);
                 utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                 utftext += String.fromCharCode((c & 63) | 128);
             }
         }
         return  utftext;
     };
     var  x = Array();
     var  k, AA, BB, CC, DD, a, b, c, d;
     var  S11 = 7,
     S12 = 12,
     S13 = 17,
     S14 = 22;
     var  S21 = 5,
     S22 = 9,
     S23 = 14,
     S24 = 20;
     var  S31 = 4,
     S32 = 11,
     S33 = 16,
     S34 = 23;
     var  S41 = 6,
     S42 = 10,
     S43 = 15,
     S44 = 21;
     string = md5_Utf8Encode(string);
     x = md5_ConvertToWordArray(string);
     a = 0x67452301;
     b = 0xEFCDAB89;
     c = 0x98BADCFE;
     d = 0x10325476;
     for  (k = 0; k < x.length; k += 16) {
         AA = a;
         BB = b;
         CC = c;
         DD = d;
         a = md5_FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
         d = md5_FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
         c = md5_FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
         b = md5_FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
         a = md5_FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
         d = md5_FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
         c = md5_FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
         b = md5_FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
         a = md5_FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
         d = md5_FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
         c = md5_FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
         b = md5_FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
         a = md5_FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
         d = md5_FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
         c = md5_FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
         b = md5_FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
         a = md5_GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
         d = md5_GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
         c = md5_GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
         b = md5_GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
         a = md5_GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
         d = md5_GG(d, a, b, c, x[k + 10], S22, 0x2441453);
         c = md5_GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
         b = md5_GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
         a = md5_GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
         d = md5_GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
         c = md5_GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
         b = md5_GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
         a = md5_GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
         d = md5_GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
         c = md5_GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
         b = md5_GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
         a = md5_HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
         d = md5_HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
         c = md5_HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
         b = md5_HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
         a = md5_HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
         d = md5_HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
         c = md5_HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
         b = md5_HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
         a = md5_HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
         d = md5_HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
         c = md5_HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
         b = md5_HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
         a = md5_HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
         d = md5_HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
         c = md5_HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
         b = md5_HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
         a = md5_II(a, b, c, d, x[k + 0], S41, 0xF4292244);
         d = md5_II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
         c = md5_II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
         b = md5_II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
         a = md5_II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
         d = md5_II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
         c = md5_II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
         b = md5_II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
         a = md5_II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
         d = md5_II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
         c = md5_II(c, d, a, b, x[k + 6], S43, 0xA3014314);
         b = md5_II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
         a = md5_II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
         d = md5_II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
         c = md5_II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
         b = md5_II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
         a = md5_AddUnsigned(a, AA);
         b = md5_AddUnsigned(b, BB);
         c = md5_AddUnsigned(c, CC);
         d = md5_AddUnsigned(d, DD);
     }
     return  (md5_WordToHex(a) + md5_WordToHex(b) + md5_WordToHex(c) + md5_WordToHex(d)).toLowerCase();
}

伪代码实现

//Note:Allvariablesareunsigned32bitsandwrapmodulo2^32whencalculatingvarint[64]r,k//rspecifiestheper-roundshiftamountsr[0..15]:={7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22}r[16..31]:={5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20}r[32..47]:={4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23}r[48..63]:={6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21}//Usebinaryintegerpartofthesinesofintegersasconstants:forifrom0to63k[i]:=floor(abs(sin(i+1))×2^32)//Initializevariables:varinth0:=0x67452301varinth1:=0xEFCDAB89varinth2:=0x98BADCFEvarinth3:=0x10325476//Pre-processing:append"1"bittomessageappend"0"bitsuntilmessagelengthinbits≡448(mod512)appendbitlengthofmessageas64-bitlittle-endianintegertomessage//Processthemessageinsuccessive512-bitchunks:foreach512-bitchunkofmessagebreakchunkintosixteen32-bitlittle-endianwordsw[i],0≤i≤15//Initializehashvalueforthischunk:varinta:=h0varintb:=h1varintc:=h2varintd:=h3//Mainloop:forifrom0to63if0≤i≤15thenf:=(bandc)or((notb)andd)g:=ielseif16≤i≤31f:=(dandb)or((notd)andc)g:=(5×i+1)mod16elseif32≤i≤47f:=bxorcxordg:=(3×i+5)mod16elseif48≤i≤63f:=cxor(bor(notd))g:=(7×i)mod16temp:=dd:=cc:=bb:=((a+f+k[i]+w[g])leftrotater[i])+ba:=temp//Addthischunk'shashtoresultsofar:h0:=h0+ah1:=h1+bh2:=h2+ch3:=h3+dvarintdigest:=h0appendh1appendh2appendh3//(expressedaslittle-endian)MD5加密工具

王小云

破解MD5密码算法,运算量达到2的80次方。即使采用现在最快的巨型计算机,也要运算100万年以上才能破解。但王小云和她的研究小组用普通的个人电脑,几分钟内就可以找到有效结果。


【摘自 百度百科   只是略有感触 想收藏下】

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值