zoukankan      html  css  js  c++  java
  • java加密算法研究


        ●  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,椭圆曲线密码编码学)[/size]

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

    本篇内容简要介绍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. }  

     

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

    可变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. }  
     

    可以看出实现的过程非常简单,因为由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. }    
     
  • 相关阅读:
    out/host/linuxx86/obj/EXECUTABLES/aapt_intermediates/aapt 64 32 操作系统
    linux 查看路由器 电脑主机 端口号 占用
    linux proc进程 pid stat statm status id 目录 解析 内存使用
    linux vim 设置大全详解
    ubuntu subclipse svn no libsvnjavahl1 in java.library.path no svnjavahl1 in java.library.path no s
    win7 安装 ubuntu 双系统 详解 easybcd 工具 不能进入 ubuntu 界面
    Atitit.json xml 序列化循环引用解决方案json
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    Atitit.跨语言  文件夹与文件的io操作集合  草案
    Atitit.atijson 类库的新特性设计与实现 v3 q31
  • 原文地址:https://www.cnblogs.com/smilesmile/p/3842272.html
Copyright © 2011-2022 走看看