在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD5 的128 位整数。然后将此 128 位计 16 个字节转换成 16 进制表示即可。

下面是一个可生成字符串或文件MD5校验码的例子,测试过,可当做工具类直接使用,其中最主要的是getMD5String(String s)和getFileMD5String(File file)两个方法,分别用于生成字符串的md5校验值和生成文件的md5校验值,getFileMD5String_old(File file)方法可删除,不建议使用:

  1. package  com.why.md5;
  2. import  java.io.File;
  3. import  java.io.FileInputStream;
  4. import  java.io.IOException;
  5. import  java.io.InputStream;
  6. import  java.nio.MappedByteBuffer;
  7. import  java.nio.channels.FileChannel;
  8. import  java.security.MessageDigest;
  9. import  java.security.NoSuchAlgorithmException;
  10. public   class  MD5Util {
  11. /**
  12. * 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合
  13. */
  14. protected   static   char  hexDigits[] = {  '0' ,  '1' ,  '2' ,  '3' ,  '4' ,  '5' , '6' ,
  15. '7' ,  '8' ,  '9' ,  'a' ,  'b' ,  'c' ,  'd' ,  'e' ,  'f'  };
  16. protected   static  MessageDigest messagedigest =  null ;
  17. static  {
  18. try  {
  19. messagedigest = MessageDigest.getInstance("MD5" );
  20. } catch  (NoSuchAlgorithmException nsaex) {
  21. System.err.println(MD5Util.class .getName()
  22. + "初始化失败,MessageDigest不支持MD5Util。" );
  23. nsaex.printStackTrace();
  24. }
  25. }
  26. /**
  27. * 生成字符串的md5校验值
  28. *
  29. * @param s
  30. * @return
  31. */
  32. public   static  String getMD5String(String s) {
  33. return  getMD5String(s.getBytes());
  34. }
  35. /**
  36. * 判断字符串的md5校验码是否与一个已知的md5码相匹配
  37. *
  38. * @param password 要校验的字符串
  39. * @param md5PwdStr 已知的md5校验码
  40. * @return
  41. */
  42. public   static   boolean  checkPassword(String password, String md5PwdStr) {
  43. String s = getMD5String(password);
  44. return  s.equals(md5PwdStr);
  45. }
  46. /**
  47. * 生成文件的md5校验值
  48. *
  49. * @param file
  50. * @return
  51. * @throws IOException
  52. */
  53. public   static  String getFileMD5String(File file)  throws  IOException {
  54. InputStream fis;
  55. fis = new  FileInputStream(file);
  56. byte [] buffer =  new   byte [ 1024 ];
  57. int  numRead =  0 ;
  58. while  ((numRead = fis.read(buffer)) >  0 ) {
  59. messagedigest.update(buffer, 0 , numRead);
  60. }
  61. fis.close();
  62. return  bufferToHex(messagedigest.digest());
  63. }
  64. /**
  65. * JDK1.4中不支持以MappedByteBuffer类型为参数update方法,并且网上有讨论要慎用MappedByteBuffer,
  66. * 原因是当使用 FileChannel.map 方法时,MappedByteBuffer 已经在系统内占用了一个句柄,
  67. * 而使用 FileChannel.close 方法是无法释放这个句柄的,且FileChannel有没有提供类似 unmap 的方法,
  68. * 因此会出现无法删除文件的情况。
  69. *
  70. * 不推荐使用
  71. *
  72. * @param file
  73. * @return
  74. * @throws IOException
  75. */
  76. public   static  String getFileMD5String_old(File file)  throws  IOException {
  77. FileInputStream in = new  FileInputStream(file);
  78. FileChannel ch = in.getChannel();
  79. MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0 ,
  80. file.length());
  81. messagedigest.update(byteBuffer);
  82. return  bufferToHex(messagedigest.digest());
  83. }
  84. public   static  String getMD5String( byte [] bytes) {
  85. messagedigest.update(bytes);
  86. return  bufferToHex(messagedigest.digest());
  87. }
  88. private   static  String bufferToHex( byte  bytes[]) {
  89. return  bufferToHex(bytes,  0 , bytes.length);
  90. }
  91. private   static  String bufferToHex( byte  bytes[],  int  m,  int  n) {
  92. StringBuffer stringbuffer = new  StringBuffer( 2  * n);
  93. int  k = m + n;
  94. for  ( int  l = m; l < k; l++) {
  95. appendHexPair(bytes[l], stringbuffer);
  96. }
  97. return  stringbuffer.toString();
  98. }
  99. private   static   void  appendHexPair( byte  bt, StringBuffer stringbuffer) {
  100. char  c0 = hexDigits[(bt &  0xf0 ) >>  4 ]; // 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同
  101. char  c1 = hexDigits[bt &  0xf ]; // 取字节中低 4 位的数字转换
  102. stringbuffer.append(c0);
  103. stringbuffer.append(c1);
  104. }
  105. public   static   void  main(String[] args)  throws  IOException {
  106. long  begin = System.currentTimeMillis();
  107. File file = new  File( "C:/12345.txt" );
  108. String md5 = getFileMD5String(file);
  109. //      String md5 = getMD5String("a");
  110. long  end = System.currentTimeMillis();
  111. System.out.println("md5:"  + md5 +  " time:"  + ((end - begin) /  1000 ) +  "s" );
  112. }
  113. }
  1. package com.why.md5;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.nio.MappedByteBuffer;
  7. import java.nio.channels.FileChannel;
  8. import java.security.MessageDigest;
  9. import java.security.NoSuchAlgorithmException;
  10. public class MD5Util {
  11. /**
  12. * 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合
  13. */
  14. protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6',
  15. '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  16. protected static MessageDigest messagedigest = null;
  17. static {
  18. try {
  19. messagedigest = MessageDigest.getInstance("MD5");
  20. } catch (NoSuchAlgorithmException nsaex) {
  21. System.err.println(MD5Util.class.getName()
  22. + "初始化失败,MessageDigest不支持MD5Util。");
  23. nsaex.printStackTrace();
  24. }
  25. }
  26. /**
  27. * 生成字符串的md5校验值
  28. *
  29. * @param s
  30. * @return
  31. */
  32. public static String getMD5String(String s) {
  33. return getMD5String(s.getBytes());
  34. }
  35. /**
  36. * 判断字符串的md5校验码是否与一个已知的md5码相匹配
  37. *
  38. * @param password 要校验的字符串
  39. * @param md5PwdStr 已知的md5校验码
  40. * @return
  41. */
  42. public static boolean checkPassword(String password, String md5PwdStr) {
  43. String s = getMD5String(password);
  44. return s.equals(md5PwdStr);
  45. }
  46. /**
  47. * 生成文件的md5校验值
  48. *
  49. * @param file
  50. * @return
  51. * @throws IOException
  52. */
  53. public static String getFileMD5String(File file) throws IOException {
  54. InputStream fis;
  55. fis = new FileInputStream(file);
  56. byte[] buffer = new byte[1024];
  57. int numRead = 0;
  58. while ((numRead = fis.read(buffer)) > 0) {
  59. messagedigest.update(buffer, 0, numRead);
  60. }
  61. fis.close();
  62. return bufferToHex(messagedigest.digest());
  63. }
  64. /**
  65. * JDK1.4中不支持以MappedByteBuffer类型为参数update方法,并且网上有讨论要慎用MappedByteBuffer,
  66. * 原因是当使用 FileChannel.map 方法时,MappedByteBuffer 已经在系统内占用了一个句柄,
  67. * 而使用 FileChannel.close 方法是无法释放这个句柄的,且FileChannel有没有提供类似 unmap 的方法,
  68. * 因此会出现无法删除文件的情况。
  69. *
  70. * 不推荐使用
  71. *
  72. * @param file
  73. * @return
  74. * @throws IOException
  75. */
  76. public static String getFileMD5String_old(File file) throws IOException {
  77. FileInputStream in = new FileInputStream(file);
  78. FileChannel ch = in.getChannel();
  79. MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0,
  80. file.length());
  81. messagedigest.update(byteBuffer);
  82. return bufferToHex(messagedigest.digest());
  83. }
  84. public static String getMD5String(byte[] bytes) {
  85. messagedigest.update(bytes);
  86. return bufferToHex(messagedigest.digest());
  87. }
  88. private static String bufferToHex(byte bytes[]) {
  89. return bufferToHex(bytes, 0, bytes.length);
  90. }
  91. private static String bufferToHex(byte bytes[], int m, int n) {
  92. StringBuffer stringbuffer = new StringBuffer(2 * n);
  93. int k = m + n;
  94. for (int l = m; l < k; l++) {
  95. appendHexPair(bytes[l], stringbuffer);
  96. }
  97. return stringbuffer.toString();
  98. }
  99. private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
  100. char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同
  101. char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换
  102. stringbuffer.append(c0);
  103. stringbuffer.append(c1);
  104. }
  105. public static void main(String[] args) throws IOException {
  106. long begin = System.currentTimeMillis();
  107. File file = new File("C:/12345.txt");
  108. String md5 = getFileMD5String(file);
  109. //      String md5 = getMD5String("a");
  110. long end = System.currentTimeMillis();
  111. System.out.println("md5:" + md5 + " time:" + ((end - begin) / 1000) + "s");
  112. }
  113. }

MD5的全称是Message-digest Algorithm 5(信息-摘要算法),用于确保信息传输完整一致。90年代初由MIT的计算机科学实验室和RSA Data Security Inc的Ronald L. Rivest开发出来,经MD2、MD3和MD4发展而来。

任何一个字符串或文件,无论是可执行程序、图像文件、临时文件或者其他任何类型的文件,也不管它体积多大,都有且只有一个独一无二的MD5信息码,并且如果这个文件被修改过,它的MD5码也将随之改变。

Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。注意这里说的是“字节串”而不是“字符串”,因为这种变换只与字节的值有关,与字符集或编码方式无关。

MD5用的是哈希函数,在计算机网络中应用较多的不可逆加密算法有RSA公司发明的MD5算法和由美国国家技术标准研究所建议的安全散列算法SHA。

MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法 将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。所以,要遇到了md5密码的问 题,比较好的办法是:你可以用这个系统中的md5()函数重新设一个密码,如admin,把生成的一串密码的Hash值覆盖原来的Hash值就行了。

MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫 readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内 容,你对这个文件重新计算MD5时就会发现(两个MD5值不相同)。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的 数字签名应用。

  MD5还广泛用于操作系统的登陆认证上,如Unix、各类BSD系统登录密码、数字签名等诸多方。如在UNIX系统中用户的密码是以 MD5(或其它类似的算法)经Hash运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可 以确定用户登录系统的合法性。这可以避免用户的密码被具有系统管理员权限的用户知道。

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

MD5算法 
      md5算法定义在RFC 1321中,由Ron Rivest(RSA公司)在1992年提出。然而很多学者已经找出了构造md5冲突的方法。这些人中包括中国山东大学的王教授和Hans Dobbertin。所以,单纯使用md5的信息认证模式变得不可靠了。但并不是说md5不能够使用。

MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

MD5算法的计算步骤:

1.通过添加一个1和若干个0的方式,把输入数据长度(按照字节算)变成64m+56 
2.添加8个字节到输入数据中去,这样输入数据长度变成了64的倍数 
3.把数据划分成块,每块64个字节 
4.初始情况下,输出为:                                                                    
  m_state[0] = 0x67452301L;
  m_state[1] = 0xefcdab89L;
  m_state[2] = 0x98badcfeL;
  m_state[3] = 0x10325476L; 
5.分别对每块进行计算。输出最后结果。

MD5的算法在RFC1321中实际上已经提供了C的实现,需要注意的是,很多早期的C编译器的int类型是16 bit的,MD5使用了unsigned long int,并认为它是32bit的无符号整数。而在Java中int是32 bit的,long是64 bit的。在MD5的C实现中,使用了大量的位操作。这里需要指出的一点是,尽管Java提供了位操作,由于Java没有unsigned类型,对于右移 位操作多提供了一个无符号右移:>>>,等价于C中的 >> 对于unsigned 数的处理。

下面是一个MD5算法的Java实现:

    1. package  com.why.md5;
    2. /*******************************************************************************
    3. * MD5_SRC 类实现了RSA Data Security, Inc.在提交给IETF的RFC1321中的MD5_SRC message-digest
    4. * 算法。
    5. ******************************************************************************/
    6. public   class  MD5_SRC {
    7. /*
    8. * 下面这些S11-S44实际上是一个4*4的矩阵,在原始的C实现中是用#define 实现的, 这里把它们实现成为static
    9. * final是表示了只读,且能在同一个进程空间内的多个 Instance间共享
    10. */
    11. static   final   int  S11 =  7 ;
    12. static   final   int  S12 =  12 ;
    13. static   final   int  S13 =  17 ;
    14. static   final   int  S14 =  22 ;
    15. static   final   int  S21 =  5 ;
    16. static   final   int  S22 =  9 ;
    17. static   final   int  S23 =  14 ;
    18. static   final   int  S24 =  20 ;
    19. static   final   int  S31 =  4 ;
    20. static   final   int  S32 =  11 ;
    21. static   final   int  S33 =  16 ;
    22. static   final   int  S34 =  23 ;
    23. static   final   int  S41 =  6 ;
    24. static   final   int  S42 =  10 ;
    25. static   final   int  S43 =  15 ;
    26. static   final   int  S44 =  21 ;
    27. static   final   byte [] PADDING = { - 128 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , 0 ,  0 ,  0 ,  0 ,
    28. 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,
    29. 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,
    30. 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0  };
    31. /*
    32. * 下面的三个成员是keyBean计算过程中用到的3个核心数据,在原始的C实现中 被定义到keyBean_CTX结构中
    33. */
    34. private   long [] state =  new   long [ 4 ];  // state (ABCD)
    35. private   long [] count =  new   long [ 2 ];  // number of bits, modulo 2^64 (lsb first)
    36. private   byte [] buffer =  new   byte [ 64 ];  // input buffer
    37. /*
    38. * digestHexStr是keyBean的唯一一个公共成员,是最新一次计算结果的 16进制ASCII表示.
    39. */
    40. public  String digestHexStr;
    41. /*
    42. * digest,是最新一次计算结果的2进制内部表示,表示128bit的keyBean值.
    43. */
    44. private   byte [] digest =  new   byte [ 16 ];
    45. /*
    46. * getkeyBeanofStr是类keyBean最主要的公共方法,入口参数是你想要进行keyBean变换的字符串
    47. * 返回的是变换完的结果,这个结果是从公共成员digestHexStr取得的.
    48. */
    49. public  String getkeyBeanofStr(String inbuf) {
    50. keyBeanInit();
    51. keyBeanUpdate(inbuf.getBytes(), inbuf.length());
    52. keyBeanFinal();
    53. digestHexStr = "" ;
    54. for  ( int  i =  0 ; i <  16 ; i++) {
    55. digestHexStr += byteHEX(digest[i]);
    56. }
    57. return  digestHexStr;
    58. }
    59. // 这是keyBean这个类的标准构造函数,JavaBean要求有一个public的并且没有参数的构造函数
    60. public  MD5_SRC() {
    61. keyBeanInit();
    62. return ;
    63. }
    64. /* keyBeanInit是一个初始化函数,初始化核心变量,装入标准的幻数 */
    65. private   void  keyBeanInit() {
    66. count[0 ] = 0L;
    67. count[1 ] = 0L;
    68. // /* Load magic initialization constants.
    69. state[0 ] = 0x67452301L;
    70. state[1 ] = 0xefcdab89L;
    71. state[2 ] = 0x98badcfeL;
    72. state[3 ] = 0x10325476L;
    73. return ;
    74. }
    75. /*
    76. * F, G, H ,I 是4 个基本的keyBean函数,在原始的keyBean的C实现中,由于它们是
    77. * 简单的位运算,可能出于效率的考虑把它们实现成了宏,在java中,我们把它们 实现成了private 方法,名字保持了原来C中的。
    78. */
    79. private   long  F( long  x,  long  y,  long  z) {
    80. return  (x & y) | ((~x) & z);
    81. }
    82. private   long  G( long  x,  long  y,  long  z) {
    83. return  (x & z) | (y & (~z));
    84. }
    85. private   long  H( long  x,  long  y,  long  z) {
    86. return  x ^ y ^ z;
    87. }
    88. private   long  I( long  x,  long  y,  long  z) {
    89. return  y ^ (x | (~z));
    90. }
    91. /*
    92. * FF,GG,HH和II将调用F,G,H,I进行近一步变换 FF, GG, HH, and II transformations for
    93. * rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent
    94. * recomputation.
    95. */
    96. private   long  FF( long  a,  long  b,  long  c,  long  d,  long  x,  long  s,  long  ac) {
    97. a += F(b, c, d) + x + ac;
    98. a = ((int ) a << s) | (( int ) a >>> ( 32  - s));
    99. a += b;
    100. return  a;
    101. }
    102. private   long  GG( long  a,  long  b,  long  c,  long  d,  long  x,  long  s,  long  ac) {
    103. a += G(b, c, d) + x + ac;
    104. a = ((int ) a << s) | (( int ) a >>> ( 32  - s));
    105. a += b;
    106. return  a;
    107. }
    108. private   long  HH( long  a,  long  b,  long  c,  long  d,  long  x,  long  s,  long  ac) {
    109. a += H(b, c, d) + x + ac;
    110. a = ((int ) a << s) | (( int ) a >>> ( 32  - s));
    111. a += b;
    112. return  a;
    113. }
    114. private   long  II( long  a,  long  b,  long  c,  long  d,  long  x,  long  s,  long  ac) {
    115. a += I(b, c, d) + x + ac;
    116. a = ((int ) a << s) | (( int ) a >>> ( 32  - s));
    117. a += b;
    118. return  a;
    119. }
    120. /*
    121. * keyBeanUpdate是keyBean的主计算过程,inbuf是要变换的字节串,inputlen是长度,这个
    122. * 函数由getkeyBeanofStr调用,调用之前需要调用keyBeaninit,因此把它设计成private的
    123. */
    124. private   void  keyBeanUpdate( byte [] inbuf,  int  inputLen) {
    125. int  i, index, partLen;
    126. byte [] block =  new   byte [ 64 ];
    127. index = (int ) (count[ 0 ] >>>  3 ) &  0x3F ;
    128. // /* Update number of bits */
    129. if  ((count[ 0 ] += (inputLen <<  3 )) < (inputLen <<  3 ))
    130. count[1 ]++;
    131. count[1 ] += (inputLen >>>  29 );
    132. partLen = 64  - index;
    133. // Transform as many times as possible.
    134. if  (inputLen >= partLen) {
    135. keyBeanMemcpy(buffer, inbuf, index, 0 , partLen);
    136. keyBeanTransform(buffer);
    137. for  (i = partLen; i +  63  < inputLen; i +=  64 ) {
    138. keyBeanMemcpy(block, inbuf, 0 , i,  64 );
    139. keyBeanTransform(block);
    140. }
    141. index = 0 ;
    142. } else
    143. i = 0 ;
    144. // /* Buffer remaining input */
    145. keyBeanMemcpy(buffer, inbuf, index, i, inputLen - i);
    146. }
    147. /*
    148. * keyBeanFinal整理和填写输出结果
    149. */
    150. private   void  keyBeanFinal() {
    151. byte [] bits =  new   byte [ 8 ];
    152. int  index, padLen;
    153. // /* Save number of bits */
    154. Encode(bits, count, 8 );
    155. // /* Pad out to 56 mod 64.
    156. index = (int ) (count[ 0 ] >>>  3 ) &  0x3f ;
    157. padLen = (index < 56 ) ? ( 56  - index) : ( 120  - index);
    158. keyBeanUpdate(PADDING, padLen);
    159. // /* Append length (before padding) */
    160. keyBeanUpdate(bits, 8 );
    161. // /* Store state in digest */
    162. Encode(digest, state, 16 );
    163. }
    164. /*
    165. * keyBeanMemcpy是一个内部使用的byte数组的块拷贝函数,从input的inpos开始把len长度的
    166. * 字节拷贝到output的outpos位置开始
    167. */
    168. private   void  keyBeanMemcpy( byte [] output,  byte [] input,  int  outpos,
    169. int  inpos,  int  len) {
    170. int  i;
    171. for  (i =  0 ; i < len; i++)
    172. output[outpos + i] = input[inpos + i];
    173. }
    174. /*
    175. * keyBeanTransform是keyBean核心变换程序,由keyBeanUpdate调用,block是分块的原始字节
    176. */
    177. private   void  keyBeanTransform( byte  block[]) {
    178. long  a = state[ 0 ], b = state[ 1 ], c = state[ 2 ], d = state[ 3 ];
    179. long [] x =  new   long [ 16 ];
    180. Decode(x, block, 64 );
    181. /* Round 1 */
    182. a = FF(a, b, c, d, x[0 ], S11, 0xd76aa478L);  /* 1 */
    183. d = FF(d, a, b, c, x[1 ], S12, 0xe8c7b756L);  /* 2 */
    184. c = FF(c, d, a, b, x[2 ], S13, 0x242070dbL);  /* 3 */
    185. b = FF(b, c, d, a, x[3 ], S14, 0xc1bdceeeL);  /* 4 */
    186. a = FF(a, b, c, d, x[4 ], S11, 0xf57c0fafL);  /* 5 */
    187. d = FF(d, a, b, c, x[5 ], S12, 0x4787c62aL);  /* 6 */
    188. c = FF(c, d, a, b, x[6 ], S13, 0xa8304613L);  /* 7 */
    189. b = FF(b, c, d, a, x[7 ], S14, 0xfd469501L);  /* 8 */
    190. a = FF(a, b, c, d, x[8 ], S11, 0x698098d8L);  /* 9 */
    191. d = FF(d, a, b, c, x[9 ], S12, 0x8b44f7afL);  /* 10 */
    192. c = FF(c, d, a, b, x[10 ], S13, 0xffff5bb1L);  /* 11 */
    193. b = FF(b, c, d, a, x[11 ], S14, 0x895cd7beL);  /* 12 */
    194. a = FF(a, b, c, d, x[12 ], S11, 0x6b901122L);  /* 13 */
    195. d = FF(d, a, b, c, x[13 ], S12, 0xfd987193L);  /* 14 */
    196. c = FF(c, d, a, b, x[14 ], S13, 0xa679438eL);  /* 15 */
    197. b = FF(b, c, d, a, x[15 ], S14, 0x49b40821L);  /* 16 */
    198. /* Round 2 */
    199. a = GG(a, b, c, d, x[1 ], S21, 0xf61e2562L);  /* 17 */
    200. d = GG(d, a, b, c, x[6 ], S22, 0xc040b340L);  /* 18 */
    201. c = GG(c, d, a, b, x[11 ], S23, 0x265e5a51L);  /* 19 */
    202. b = GG(b, c, d, a, x[0 ], S24, 0xe9b6c7aaL);  /* 20 */
    203. a = GG(a, b, c, d, x[5 ], S21, 0xd62f105dL);  /* 21 */
    204. d = GG(d, a, b, c, x[10 ], S22, 0x2441453L);  /* 22 */
    205. c = GG(c, d, a, b, x[15 ], S23, 0xd8a1e681L);  /* 23 */
    206. b = GG(b, c, d, a, x[4 ], S24, 0xe7d3fbc8L);  /* 24 */
    207. a = GG(a, b, c, d, x[9 ], S21, 0x21e1cde6L);  /* 25 */
    208. d = GG(d, a, b, c, x[14 ], S22, 0xc33707d6L);  /* 26 */
    209. c = GG(c, d, a, b, x[3 ], S23, 0xf4d50d87L);  /* 27 */
    210. b = GG(b, c, d, a, x[8 ], S24, 0x455a14edL);  /* 28 */
    211. a = GG(a, b, c, d, x[13 ], S21, 0xa9e3e905L);  /* 29 */
    212. d = GG(d, a, b, c, x[2 ], S22, 0xfcefa3f8L);  /* 30 */
    213. c = GG(c, d, a, b, x[7 ], S23, 0x676f02d9L);  /* 31 */
    214. b = GG(b, c, d, a, x[12 ], S24, 0x8d2a4c8aL);  /* 32 */
    215. /* Round 3 */
    216. a = HH(a, b, c, d, x[5 ], S31, 0xfffa3942L);  /* 33 */
    217. d = HH(d, a, b, c, x[8 ], S32, 0x8771f681L);  /* 34 */
    218. c = HH(c, d, a, b, x[11 ], S33, 0x6d9d6122L);  /* 35 */
    219. b = HH(b, c, d, a, x[14 ], S34, 0xfde5380cL);  /* 36 */
    220. a = HH(a, b, c, d, x[1 ], S31, 0xa4beea44L);  /* 37 */
    221. d = HH(d, a, b, c, x[4 ], S32, 0x4bdecfa9L);  /* 38 */
    222. c = HH(c, d, a, b, x[7 ], S33, 0xf6bb4b60L);  /* 39 */
    223. b = HH(b, c, d, a, x[10 ], S34, 0xbebfbc70L);  /* 40 */
    224. a = HH(a, b, c, d, x[13 ], S31, 0x289b7ec6L);  /* 41 */
    225. d = HH(d, a, b, c, x[0 ], S32, 0xeaa127faL);  /* 42 */
    226. c = HH(c, d, a, b, x[3 ], S33, 0xd4ef3085L);  /* 43 */
    227. b = HH(b, c, d, a, x[6 ], S34, 0x4881d05L);  /* 44 */
    228. a = HH(a, b, c, d, x[9 ], S31, 0xd9d4d039L);  /* 45 */
    229. d = HH(d, a, b, c, x[12 ], S32, 0xe6db99e5L);  /* 46 */
    230. c = HH(c, d, a, b, x[15 ], S33, 0x1fa27cf8L);  /* 47 */
    231. b = HH(b, c, d, a, x[2 ], S34, 0xc4ac5665L);  /* 48 */
    232. /* Round 4 */
    233. a = II(a, b, c, d, x[0 ], S41, 0xf4292244L);  /* 49 */
    234. d = II(d, a, b, c, x[7 ], S42, 0x432aff97L);  /* 50 */
    235. c = II(c, d, a, b, x[14 ], S43, 0xab9423a7L);  /* 51 */
    236. b = II(b, c, d, a, x[5 ], S44, 0xfc93a039L);  /* 52 */
    237. a = II(a, b, c, d, x[12 ], S41, 0x655b59c3L);  /* 53 */
    238. d = II(d, a, b, c, x[3 ], S42, 0x8f0ccc92L);  /* 54 */
    239. c = II(c, d, a, b, x[10 ], S43, 0xffeff47dL);  /* 55 */
    240. b = II(b, c, d, a, x[1 ], S44, 0x85845dd1L);  /* 56 */
    241. a = II(a, b, c, d, x[8 ], S41, 0x6fa87e4fL);  /* 57 */
    242. d = II(d, a, b, c, x[15 ], S42, 0xfe2ce6e0L);  /* 58 */
    243. c = II(c, d, a, b, x[6 ], S43, 0xa3014314L);  /* 59 */
    244. b = II(b, c, d, a, x[13 ], S44, 0x4e0811a1L);  /* 60 */
    245. a = II(a, b, c, d, x[4 ], S41, 0xf7537e82L);  /* 61 */
    246. d = II(d, a, b, c, x[11 ], S42, 0xbd3af235L);  /* 62 */
    247. c = II(c, d, a, b, x[2 ], S43, 0x2ad7d2bbL);  /* 63 */
    248. b = II(b, c, d, a, x[9 ], S44, 0xeb86d391L);  /* 64 */
    249. state[0 ] += a;
    250. state[1 ] += b;
    251. state[2 ] += c;
    252. state[3 ] += d;
    253. }
    254. /*
    255. * Encode把long数组按顺序拆成byte数组,因为java的long类型是64bit的,只拆低32bit,以适应原始C实现的用途
    256. */
    257. private   void  Encode( byte [] output,  long [] input,  int  len) {
    258. int  i, j;
    259. for  (i =  0 , j =  0 ; j < len; i++, j +=  4 ) {
    260. output[j] = (byte ) (input[i] & 0xffL);
    261. output[j + 1 ] = ( byte ) ((input[i] >>>  8 ) & 0xffL);
    262. output[j + 2 ] = ( byte ) ((input[i] >>>  16 ) & 0xffL);
    263. output[j + 3 ] = ( byte ) ((input[i] >>>  24 ) & 0xffL);
    264. }
    265. }
    266. /*
    267. * Decode把byte数组按顺序合成成long数组,因为java的long类型是64bit的,
    268. * 只合成低32bit,高32bit清零,以适应原始C实现的用途
    269. */
    270. private   void  Decode( long [] output,  byte [] input,  int  len) {
    271. int  i, j;
    272. for  (i =  0 , j =  0 ; j < len; i++, j +=  4 )
    273. output[i] = b2iu(input[j]) | (b2iu(input[j + 1 ]) <<  8 )
    274. | (b2iu(input[j + 2 ]) <<  16 ) | (b2iu(input[j +  3 ]) <<  24 );
    275. return ;
    276. }
    277. /*
    278. * b2iu是我写的一个把byte按照不考虑正负号的原则的”升位”程序,因为java没有unsigned运算
    279. */
    280. public   static   long  b2iu( byte  b) {
    281. return  b <  0  ? b &  0x7F  +  128  : b;
    282. }
    283. /*
    284. * byteHEX(),用来把一个byte类型的数转换成十六进制的ASCII表示,
    285. * 因为java中的byte的toString无法实现这一点,我们又没有C语言中的 sprintf(outbuf,"%02X",ib)
    286. */
    287. public   static  String byteHEX( byte  ib) {
    288. char [] Digit = {  '0' ,  '1' ,  '2' ,  '3' ,  '4' ,  '5' ,  '6' ,  '7' ,  '8' , '9' ,  'A' ,
    289. 'B' ,  'C' ,  'D' ,  'E' ,  'F'  };
    290. char [] ob =  new   char [ 2 ];
    291. ob[0 ] = Digit[(ib >>>  4 ) &  0X0F ];
    292. ob[1 ] = Digit[ib &  0X0F ];
    293. String s = new  String(ob);
    294. return  s;
    295. }
    296. public   static   void  main(String args[]) {
    297. MD5_SRC m = new  MD5_SRC();
    298. System.out.println("keyBean Test suite:" );
    299. System.out.println("keyBean(\"\"):" +m.getkeyBeanofStr( "" ));
    300. System.out.println("keyBean(\"a\"):" +m.getkeyBeanofStr( "a" ));
    301. System.out.println("keyBean(\"abc\"):" +m.getkeyBeanofStr( "abc" ));
    302. System.out.println("keyBean(\"message digest\"):" +m.getkeyBeanofStr( "message digest" ));
    303. System.out.println("keyBean(\"abcdefghijklmnopqrstuvwxyz\"):" +
    304. m.getkeyBeanofStr("abcdefghijklmnopqrstuvwxyz" ));
    305. System.out.println("keyBean(\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"):" +
    306. m.getkeyBeanofStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ));
    307. }
    308. }

Android MD5校验码的生成与算法实现的更多相关文章

  1. java生成MD5校验码

    在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD5 的128 位整数.然后将此 128 位计 ...

  2. C# 获取文件MD5校验码

    using System; using System.IO; using System.Security.Cryptography; using System.Text; public class M ...

  3. Java 获取 文件md5校验码

    讯雷下载的核心思想是校验文件的md5值,两个文件若md5相同则为同一文件. 当得到用户下载某个文件的请求后它根据数据库中保留的文件md5比对出拥有此文件的url, 将用户请求挂接到此url上并仿造一个 ...

  4. 脚本_根据 md5 校验码,检测文件是否被修改

    #!bin/bash#功能:根据 md5 校验码,检测文件是否被修改#作者:liusingbon#本示例脚本检测的是/etc 目录下所有的 conf 结尾的文件,根据实际情况,您可以修改为其他目录或文 ...

  5. Android二维码的生成,解析以及扫描功能

    <1> 布局只有2个按钮,实现生成二维码和解析二维码 <Button android:layout_width="wrap_content" android:la ...

  6. Android 二维码扫描/生成

    先看看实现效果 1.在module的build.gradle中执行compile操作 compile 'cn.yipianfengye.android:zxing-library:2.2' 2.在Ap ...

  7. 030_根据 md5 校验码,检测文件是否被修改

    #!/bin/bash#本示例脚本检测的是/etc 目录下所有的 conf 结尾的文件,根据实际情况,可以修改为其他目录或文件#本脚本在目标数据没有被修改时执行一次,当怀疑数据被人篡改,再执行一次#将 ...

  8. md5和SHA校验码

    md5已经不安全了,中国山东大学女学霸王小云破解了一系列密码,当真是巾帼不让须眉.说是破解,其实就是给你一个md5码,让你求出这个md5码所对应的原始信息,显然一个md5对应无数种原始信息.而md5的 ...

  9. MD5校验

    好久没有写随笔了,正好这两天可以休整一下,借此机会总结下最近使用python的小体会. 个人体会文件校验在下载文件时使用较多,在linux下最简单的实现方式就是: 1 $ md5sum filenam ...

随机推荐

  1. php 传变量到 js 文件

    php 传变量到 js 文件 // 传变量到js $oncj="taocanonc(".$i.",".$alli.",".$row1[mon ...

  2. [Angular CLI] Build application without remove dist folder for Docker Volume

    When we develop the Angular app inside Docker container, we can simulate Production envioment by bui ...

  3. 如何通过 iframe 共享 jQuery $.data?

    index.html <div id="div1"> </div> <iframe src="ajax2.html" name=& ...

  4. Android ListView 和 ***Adapter 从本地/网络获取歌曲列表

    本文内容 环境 项目结构 测试数据 演示 1:SimpleAdapter 演示 2:BaseAdapter 演示 3:CustomLazyList 演示 4:CustomLazyCompleteLis ...

  5. Python 使用pymongo操作mongodb库

    Python 使用pymongo操作mongodb库 2016-12-31 21:55 1115人阅读 评论(0) 收藏 举报  分类: - - - Python(10)  版权声明:本文为博主原创文 ...

  6. linux:C++实现ping

    转载自: //http://blog.chinaunix.net/uid-25909722-id-2762079.html #include <stdio.h> #include < ...

  7. Python脚本生成sitemap

    项目须要用脚本生成sitemap,中间学习了一下sitemap的格式和lxml库的使用方法.把结果记录一下,方便以后须要直接拿来用. 来自Python脚本生成sitemap 安装lxml 首先须要pi ...

  8. js开发思路

    $.ui = $.ui || {}; var version = $.ui.version = "1.12.1"; // 是否为ie浏览器 var ie = $.ui.ie = ! ...

  9. 高级javaScript程序形成过程(进阶)

    实现过程 1.创建对象 if (window.ke){return;} 2.创建私有变量 var _TIME = new Date().getTime(); 3.创建私有函数 _fn(){} 4.创建 ...

  10. SQL Server中float转字符串进度丢失

    写了个函数接受varchar的参数, 但实际传入的是float, 但是转换后舍入成2位小数了, 单独执行没问题, 从table中查询输出就有问题 REF SELECT CAST(CAST(字段 AS ...