zoukankan      html  css  js  c++  java
  • java(计算机)常见加密算法详解

      来源:http://blog.csdn.net/janronehoo/article/category/1152295

     如基本的单向加密算法:

    • BASE64 严格地说,属于编码格式,而非加密算法
    • MD5(Message Digest algorithm 5,信息摘要算法)
    • SHA(Secure Hash Algorithm,安全散列算法)
    • HMAC(Hash Message Authentication Code,散列消息鉴别码)


        复杂的对称加密(DES、PBE)、非对称加密算法:

      • DES(Data Encryption Standard,数据加密算法)
      • PBE(Password-based encryption,基于密码验证)
      • RSA(算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman)
      • DH(Diffie-Hellman算法,密钥一致协议)
      • DSA(Digital Signature Algorithm,数字签名)
      • ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)


    -------------------------------------------------------------------------------------------------------------------------------------------

    本篇内容简要介绍BASE64、MD5、SHA、HMAC几种加密算法。
    BASE64编码算法不算是真正的加密算法。
    MD5、SHA、HMAC这三种加密算法,可谓是非可逆加密,就是不可解密的加密方法,我们称之为单向加密算法。我们通常只把他们作为加密的基础。单纯的以上三种的加密并不可靠。

    BASE64
    按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)
    常见于邮件、http加密,截取http信息,你就会发现登录操作的用户名、密码字段通过BASE64加密的。

                           

    主要就是BASE64Encoder、BASE64Decoder两个类,我们只需要知道使用对应的方法即可。另,BASE加密后产生的字节位数是8的倍数,如果不够位数以=符号填充。

    sun不推荐使用它们自己的base64,所以用apache的挺好!


    MD5
    MD5 -- message-digest algorithm 5 (信息-摘要算法)缩写,广泛用于加密和解密技术,常用于文件校验。校验?不管文件多大,经过MD5后都能生成唯一的MD5值。好比现在的ISO校验,都是MD5校验。怎么用?当然是把ISO经过MD5后产生MD5的值。一般下载linux-ISO的朋友都见过下载链接旁边放着MD5的串。就是用来验证文件是否一致的。



    通常我们不直接使用上述MD5加密。通常将MD5产生的字节数组交给BASE64再加密一把,得到相应的字符串。


    SHA
    SHA(Secure Hash Algorithm,安全散列算法),数字签名等密码学应用中重要的工具,被广泛地应用于电子商务等信息安全领域。虽然,SHA与MD5通过碰撞法都被破解了,但是SHA仍然是公认的安全加密算法,较之MD5更为安全。



    HMAC
    HMAC(Hash Message Authentication Code,散列消息鉴别码,基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。



    BASE64的加密解密是双向的,可以求反解。
    MD5、SHA以及HMAC是单向加密,任何数据加密后只会产生唯一的一个加密串,通常用来校验数据在传输过程中是否被修改。其中HMAC算法有一个密钥,增强了数据传输过程中的安全性,强化了算法外的不可控因素。[img]http://www.iteye.com/images/smiles/icon_biggrin.gif" alt="[/img]
    单向加密的用途主要是为了校验数据在传输过程中是否被修改。


    代码如下:

    Java代码

    1. import      java.math.BigInteger;
    2. import java.security.InvalidKeyException;     
    3. import      java.security.MessageDigest;
    4. import      java.security.NoSuchAlgorithmException;
    5. import      javax.crypto.KeyGenerator;
    6. import      javax.crypto.Mac;
    7. import      javax.crypto.SecretKey;
    8. import      javax.crypto.spec.SecretKeySpec;
    9. import      org.apache.commons.codec.binary.Base64;
    10.  
    11. public class      MyEncrypt {
    12. public static      final String KEY_SHA = "SHA";
    13. public static      final String KEY_MD5 = "MD5";
    14. public static      final String KEY_MAC = "HmacMD5";
    15.  
    16.  
    17. // sun不推荐使用它们自己的base64,用apache的挺好     
    18. /**
    19. * BASE64解密
    20. */
    21. public static      byte[] decryptBASE64(byte[] dest) {
    22. if (dest == null)      {
    23. return null;
    24. }
    25. return      Base64.decodeBase64(dest);
    26. }
    27.  
    28. /**
    29. * BASE64加密
    30. */
    31. public static      byte[] encryptBASE64(byte[] origin) {
    32. if (origin ==      null) {
    33. return null;
    34. }
    35. return      Base64.encodeBase64(origin);
    36. }
    37.  
    38. /**
    39. * MD5加密
    40. *
    41. * @throws      NoSuchAlgorithmException
    42. */
    43. public static      byte[] encryptMD5(byte[] data)
    44. throws      NoSuchAlgorithmException {
    45. if (data == null)      {
    46. return null;
    47. }
    48. MessageDigest      md5 = MessageDigest.getInstance(KEY_MD5);
    49. md5.update(data);     
    50. return      md5.digest();
    51. }
    52.  
    53. /**
    54. * SHA加密
    55. *
    56. * @throws      NoSuchAlgorithmException
    57. */
    58. public static      byte[] encryptSHA(byte[] data)
    59. throws      NoSuchAlgorithmException {
    60. if (data == null)      {
    61. return null;
    62. }
    63. MessageDigest      sha = MessageDigest.getInstance(KEY_SHA);
    64. sha.update(data);     
    65. return      sha.digest();
    66. }
    67.  
    68. /**
    69. * 初始化HMAC密钥
    70. *
    71. * @throws      NoSuchAlgorithmException
    72. */
    73. public static      String initMacKey() throws NoSuchAlgorithmException {
    74. KeyGenerator      keyGenerator = KeyGenerator.getInstance(KEY_MAC);
    75. SecretKey      secretKey = keyGenerator.generateKey();
    76. return new      String(encryptBASE64(secretKey.getEncoded()));
    77. }
    78.  
    79. /**
    80. * HMAC加密
    81. *
    82. * @throws      NoSuchAlgorithmException
    83. * @throws      InvalidKeyException
    84. */
    85. public static      byte[] encryptHMAC(byte[] data, String key)
    86. throws      NoSuchAlgorithmException, InvalidKeyException {
    87. SecretKey      secretKey = new SecretKeySpec(decryptBASE64(key.getBytes()),
    88. KEY_MAC);
    89. Mac mac =      Mac.getInstance(secretKey.getAlgorithm());
    90. mac.init(secretKey);     
    91. return      mac.doFinal(data);
    92.  
    93. }
    94.  
    95. public static      void main(String[] args) throws Exception {
    96. // TODO      Auto-generated method stub
    97. String data =      "简单加密";
    98. System.out.println(new      BigInteger(encryptBASE64(data.getBytes())).toString(16));
    99. System.out.println(new      BigInteger(encryptBASE64(data.getBytes())).toString(32));
    100. System.out.println(new      String(decryptBASE64(encryptBASE64(data.getBytes()))));
    101.  
    102. System.out.println(new      BigInteger(encryptMD5(data.getBytes())).toString());
    103. System.out.println(new      BigInteger(encryptSHA(data.getBytes())).toString());
    104.  
    105. System.out.println(new      BigInteger(encryptHMAC(data.getBytes(), initMacKey())).toString());
    106. }
    107.  
    108. }

    import java.math.BigInteger;

    import java.security.InvalidKeyException;

    import java.security.MessageDigest;

    import java.security.NoSuchAlgorithmException;

    import javax.crypto.KeyGenerator;

    import javax.crypto.Mac;

    import javax.crypto.SecretKey;

    import javax.crypto.spec.SecretKeySpec;

    import org.apache.commons.codec.binary.Base64;

     

    public class MyEncrypt {

    public static final String KEY_SHA = "SHA";

    public static final String KEY_MD5 = "MD5";

    public static final String KEY_MAC = "HmacMD5";

     

     

    // sun不推荐使用它们自己的base64,用apache的挺好

    /**

    * BASE64解密

    */

    public static byte[] decryptBASE64(byte[] dest) {

    if (dest == null) {

    return null;

    }

    return Base64.decodeBase64(dest);

    }

     

    /**

    * BASE64加密

    */

    public static byte[] encryptBASE64(byte[] origin) {

    if (origin == null) {

    return null;

    }

    return Base64.encodeBase64(origin);

    }

     

    /**

    * MD5加密

    *

    * @throws NoSuchAlgorithmException

    */

    public static byte[] encryptMD5(byte[] data)

    throws NoSuchAlgorithmException {

    if (data == null) {

    return null;

    }

    MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);

    md5.update(data);

    return md5.digest();

    }

     

    /**

    * SHA加密

    *

    * @throws NoSuchAlgorithmException

    */

    public static byte[] encryptSHA(byte[] data)

    throws NoSuchAlgorithmException {

    if (data == null) {

    return null;

    }

    MessageDigest sha = MessageDigest.getInstance(KEY_SHA);

    sha.update(data);

    return sha.digest();

    }

     

    /**

    * 初始化HMAC密钥

    *

    * @throws NoSuchAlgorithmException

    */

    public static String initMacKey() throws NoSuchAlgorithmException {

    KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);

    SecretKey secretKey = keyGenerator.generateKey();

    return new String(encryptBASE64(secretKey.getEncoded()));

    }

     

    /**

    * HMAC加密

    *

    * @throws NoSuchAlgorithmException

    * @throws InvalidKeyException

    */

    public static byte[] encryptHMAC(byte[] data, String key)

    throws NoSuchAlgorithmException, InvalidKeyException {

    SecretKey secretKey = new SecretKeySpec(decryptBASE64(key.getBytes()),

    KEY_MAC);

    Mac mac = Mac.getInstance(secretKey.getAlgorithm());

    mac.init(secretKey);

    return mac.doFinal(data);

     

    }

     

    public static void main(String[] args) throws Exception {

    // TODO Auto-generated method stub

    String data = "简单加密";

    System.out.println(new BigInteger(encryptBASE64(data.getBytes())).toString(16));

    System.out.println(new BigInteger(encryptBASE64(data.getBytes())).toString(32));

    System.out.println(new String(decryptBASE64(encryptBASE64(data.getBytes()))));

     

    System.out.println(new BigInteger(encryptMD5(data.getBytes())).toString());

    System.out.println(new BigInteger(encryptSHA(data.getBytes())).toString());

     

    System.out.println(new BigInteger(encryptHMAC(data.getBytes(), initMacKey())).toString());

    }

     

    }



    ------------------------------------------------------------------------------------------------------------------------------------------------------------

    可变MD5加密(Java实现)

    可变在这里含义很简单,就是最终的加密结果是可变的,而非必需按标准MD5加密实现。Java类库security中的MessageDigest类就提供了MD5加密的支持,实现起来非常方便。为了实现更多效果,我们可以如下设计MD5工具类。

    Java代码

    1. import      java.security.MessageDigest;
    2.  
    3. /**
    4. * 标准MD5加密方法,使用java类库的security包的MessageDigest类处理
    5. */
    6. public class MD5      {
    7. /**
    8. * 获得MD5加密密码的方法
    9. */
    10. public static      String getMD5ofStr(String origString) {
    11. String      origMD5 = null;
    12. try {
    13. MessageDigest      md5 = MessageDigest.getInstance("MD5");
    14. //      md5.update(origString.getBytes());
    15. byte[] result      = md5.digest(origString.getBytes());
    16. origMD5 =      byteArray2HexStr(result);
    17. // if      ("123".equals(origString)) {
    18. //      System.out.println(new String(result));
    19. //      System.out.println(new BigInteger(result).toString(16));
    20. // }
    21. } catch      (Exception e) {
    22. e.printStackTrace();     
    23. }
    24. return      origMD5;
    25. }
    26.  
    27. /**
    28. * 处理字节数组得到MD5密码的方法
    29. */
    30. private static      String byteArray2HexStr(byte[] bs) {
    31. StringBuffer      sb = new StringBuffer();
    32. for (byte b :      bs) {
    33. sb.append(byte2HexStr(b));     
    34. }
    35. return      sb.toString();
    36. }
    37.  
    38. /**
    39. * 字节标准移位转十六进制方法
    40. */
    41. private static      String byte2HexStr(byte b) {
    42. String hexStr      = null;
    43. int n = b;
    44. if (n < 0)      {
    45. // 若需要自定义加密,请修改这个移位算法即可
    46. n = b & 0x7F      + 128;
    47. }
    48. hexStr =      Integer.toHexString(n / 16) + Integer.toHexString(n % 16);
    49. return      hexStr.toUpperCase();
    50. }
    51.  
    52. /**
    53. * 提供一个MD5多次加密方法
    54. */
    55. public static      String getMD5ofStr(String origString, int times) {
    56. String md5 =      getMD5ofStr(origString);
    57. for (int i = 0;      i < times - 1; i++) {
    58. md5 =      getMD5ofStr(md5);
    59. }
    60. return      getMD5ofStr(md5);
    61. }
    62.  
    63. /**
    64. * 密码验证方法
    65. */
    66. public static      boolean verifyPassword(String inputStr, String MD5Code) {
    67. return      getMD5ofStr(inputStr).equals(MD5Code);
    68. }
    69.  
    70. /**
    71. * 重载一个多次加密时的密码验证方法
    72. */
    73. public static      boolean verifyPassword(String inputStr, String MD5Code,
    74. int times) {
    75. return      getMD5ofStr(inputStr, times).equals(MD5Code);
    76. }
    77.  
    78. /**
    79. * 提供一个测试的主函数
    80. */
    81. public static      void main(String[] args) {
    82. System.out.println("123:"      + getMD5ofStr("123"));
    83. System.out.println("123456789:"      + getMD5ofStr("123456789"));
    84. System.out.println("sarin:"      + getMD5ofStr("sarin"));
    85. System.out.println("123:"      + getMD5ofStr("123", 4));
    86. }
    87. }

    import java.security.MessageDigest;

     

    /**

     * 标准MD5加密方法,使用java类库的security包的MessageDigest类处理

     */

    public class MD5 {

      /**

       * 获得MD5加密密码的方法

       */

      public static String getMD5ofStr(String origString) {

        String origMD5 = null;

        try {

          MessageDigest md5 = MessageDigest.getInstance("MD5");

          // md5.update(origString.getBytes());

          byte[] result = md5.digest(origString.getBytes());

          origMD5 = byteArray2HexStr(result);

          // if ("123".equals(origString)) {

          // System.out.println(new String(result));

          // System.out.println(new BigInteger(result).toString(16));

          // }

        } catch (Exception e) {

          e.printStackTrace();

        }

        return origMD5;

      }

     

      /**

       * 处理字节数组得到MD5密码的方法

       */

      private static String byteArray2HexStr(byte[] bs) {

        StringBuffer sb = new StringBuffer();

        for (byte b : bs) {

          sb.append(byte2HexStr(b));

        }

        return sb.toString();

      }

     

      /**

       * 字节标准移位转十六进制方法

       */

      private static String byte2HexStr(byte b) {

        String hexStr = null;

        int n = b;

        if (n < 0) {

          // 若需要自定义加密,请修改这个移位算法即可

          n = b & 0x7F + 128;

        }

        hexStr = Integer.toHexString(n / 16) + Integer.toHexString(n % 16);

        return hexStr.toUpperCase();

      }

     

      /**

       * 提供一个MD5多次加密方法

       */

      public static String getMD5ofStr(String origString, int times) {

        String md5 = getMD5ofStr(origString);

        for (int i = 0; i < times - 1; i++) {

          md5 = getMD5ofStr(md5);

        }

        return getMD5ofStr(md5);

      }

     

      /**

       * 密码验证方法

       */

      public static boolean verifyPassword(String inputStr, String MD5Code) {

        return getMD5ofStr(inputStr).equals(MD5Code);

      }

     

      /**

       * 重载一个多次加密时的密码验证方法

       */

      public static boolean verifyPassword(String inputStr, String MD5Code,

          int times) {

        return getMD5ofStr(inputStr, times).equals(MD5Code);

      }

     

      /**

       * 提供一个测试的主函数

       */

      public static void main(String[] args) {

        System.out.println("123:" + getMD5ofStr("123"));

        System.out.println("123456789:" + getMD5ofStr("123456789"));

        System.out.println("sarin:" + getMD5ofStr("sarin"));

        System.out.println("123:" + getMD5ofStr("123", 4));

      }

    }

    可以看出实现的过程非常简单,因为由java类库提供了处理支持。但是要清楚的是这种方式产生的密码不是标准的MD5码,它需要进行移位处理才能得到标准MD5码。这个程序的关键之处也在这了,怎么可变?调整移位算法不就可变了么!不进行移位,也能够得到32位的密码,这就不是标准加密了,只要加密和验证过程使用相同的算法就可以了。
    MD5加密还是很安全的,像CMD5那些穷举破解的只是针对标准MD5加密的结果进行的,如果自定义移位算法后,它还有效么?可以说是无解的了,所以MD5非常安全可靠。
    为了更可变,还提供了多次加密的方法,可以在MD5基础之上继续MD5,就是对32位的第一次加密结果再MD5,恩,这样去破解?没有任何意义。
    这样在MIS系统中使用,安全可靠,欢迎交流,希望对使用者有用。
    我们最后看看由MD5加密算法实现的类,那是非常庞大的。

    Java代码

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