1.消息摘要簡介
消息摘要(Message Digest)又稱為數字摘要(Digital Digest)。它是一個唯一對應一個消息或文本的固定長度的值,它由一個單向Hash加密函數對消息進行作用而產生。如果消息在途中改變了,則接收者通過對收到消息的新產生的摘要與原摘要比較,就可知道消息是否被改變了。因此消息摘要保證了消息的完整性。 消息摘要采用單向Hash 函數將需加密的明文"摘要"成一串128bit(16byte)的密文,這一串密文亦稱為數字指紋(Finger Print),它有固定的長度,且不同的明文摘要成密文,其結果總是不同的,而同樣的明文其摘要必定一致。這樣這串摘要便可成為驗證明文是否是"真身"的"指紋"了。
常見是算法:
MD5、SHA、CRC 等。
使用場景:
1. 對用戶密碼進行 md5 加密后保存到數據庫里
2. 軟件下載站使用消息摘要計算文件指紋,防止被篡改
3. 數字簽名(后面知識點)
比如Tomcat的官方下載網頁,為了防止下載的Tomcat是“假冒”的,提供了MD5碼,我們將Tomcat的zip文件下載后計算一下MD5,如果計算出來的MD5跟官方公布的MD5一致,那么說明我們下載的就是純正的了。
http://tomcat.apache.org/download-70.cgi

2.MD5算法原理
對MD5算法簡要的敘述可以為:MD5以512bit分組來處理輸入的信息,且每一分組又被劃分為16個32位子分組,經過了一系列的處理后,算法的輸出由四個32位分組組成,將這四個32位分組級聯后將生成一個128位散列值。
第一步、填充:如果輸入信息的長度(bit)對512求余的結果不等于448,就需要填充使得對512求余的結果等于448。填充的方法是填充一個1和n個0。填充完后,信息的長度就為N*512+448(bit);
第二步、記錄信息長度:用64位來存儲填充前信息長度。這64位加在第一步結果的后面,這樣信息長度就變為N*512+448+64=(N+1)*512位。
第三步、裝入標準的幻數(四個整數):標準的幻數(物理順序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定義應該是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有點暈哈,其實想一想就明白了。
第四步、四輪循環運算:循環的次數是分組的個數(N+1)
參考文章:http://blog.csdn.net/forgotaboutgirl/article/details/7258109

3.MD5的安全性
普遍認為MD5是很安全的,因為暴力破解的時間是一般人無法接受的。實際上如果把用戶的密碼MD5處理后再存儲到數據庫,其實是很不安全的。因為用戶的密碼是比較短的,而且很多用戶的密碼都使用生日,手機號碼,身份證號碼,電話號碼等等。或者使用常用的一些吉利的數字,或者某個英文單詞。如果我把常用的密碼先MD5處理,把數據存儲起來,然后再跟你的MD5結果匹配,這時我就有可能得到明文。比如某個MD5破解網站http://www.cmd5.com/default.aspx

我把其網站下的公告復制如下:
本站針對md5等全球通用公開的加密算法進行反向查詢,建立了密文對應查詢數據庫,很多復雜密文只有本站才可查詢,支持多種算法,實時查詢記錄超過24萬億條,共占用160T硬盤,成功率95%以上,建站十年,國內外享有盛譽。
4.MD5 算法實現
~~~
1. package com;
2.
3. import java.io.File;
4. import java.io.FileInputStream;
5. import java.io.FileNotFoundException;
6. import java.io.IOException;
7. import java.security.MessageDigest;
8. import java.security.NoSuchAlgorithmException;
9.
10. public class MD5Test {
11.
12. public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
13. String str = "你好黑馬";
14. String result = getMD5(str);
15. System.out.println(result);
16. File file = new File("C:\\tomcat\\apache-tomcat-7.0.77-windows-x64.zip");
17. String result2 = getMD5(file);
18. System.out.println("下載的Tomact的MD5="+result2);
19. }
20.
21. //獲取文件的MD5值
22. private static String getMD5(File file) throws NoSuchAlgorithmException, IOException {
23. MessageDigest messageDigest = MessageDigest.getInstance("MD5");
24.
25. FileInputStream fis = new FileInputStream(file);
26. int len;
27. byte[] buffer = new byte[1024];
28. while((len=fis.read(buffer))!=-1){
29. messageDigest.update(buffer, 0, len);
30. }
31. fis.close();
32.
33. byte[] digest = messageDigest.digest();
34. //對計算結果進行16進制編碼
35. return Hex.encode(digest);
36. }
37.
38. //獲取字符串的MD5值
39. private static String getMD5(String str) throws NoSuchAlgorithmException {
40. MessageDigest messageDigest = MessageDigest.getInstance("MD5");
41. byte[] digest = messageDigest.digest(str.getBytes());
42.
43. return Hex.encode(digest);
44. }
45.
46. }
~~~
上面代碼中,我們對下載的文件進行了MD5計算,得到的值如下圖所示:

官網上公布的Tomact的MD5如下圖所示。

對比發現,計算的結果跟官方公布的MD5值是一致的,因此可以認為我們下載的Tomcat的真的。
5.SHA算法實現
安全哈希算法(Secure Hash Algorithm)主要適用于數字簽名標準 (Digital Signature Standard DSS)里面定義的數字簽名算法(Digital Signature Algorithm DSA)。對于長度小于2^64位的消息,SHA1會產生一個160bit(20byte)的消息摘要。當接收到消息的時候,這個消息摘要可以用來驗證數據的完整性。在傳輸的過程中,數據很可能會發生變化,那么這時候就會產生不同的消息摘要。
SHA1有如下特性:不可以從消息摘要中復原信息;兩個不同的消息不會產生同樣的消息摘要,(但會有1x10 ^ 48分之一的機率出現相同的消息摘要,一般使用時忽略)。
SHA算法還有子算法,比如SHA-256和SHA-512。分別代表會產生256位和512位的消息摘要。
SHA的代碼實現跟MD5在使用上是一致的。只需要將算法名稱改為SHA即可。
~~~
1. package com;
2.
3. import java.io.File;
4. import java.io.FileInputStream;
5. import java.io.FileNotFoundException;
6. import java.io.IOException;
7. import java.security.MessageDigest;
8. import java.security.NoSuchAlgorithmException;
9.
10. public class SHATest {
11. public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
12. String str = "你好黑馬";
13. String result = getSHA(str);
14. System.out.println(result);
15. File file = new File("C:\\tomcat\\apache-tomcat-7.0.77-windows-x64.zip");
16. String result2 = getSHA(file);
17. System.out.println("下載的Tomact的SHA="+result2);
18. }
19.
20. private static String getSHA(File file) throws NoSuchAlgorithmException, IOException {
21. MessageDigest messageDigest = MessageDigest.getInstance("SHA");
22. FileInputStream fis = new FileInputStream(file);
23. int len;
24. byte[] buffer = new byte[1024];
25. while((len=fis.read(buffer))!=-1){
26. messageDigest.update(buffer, 0, len);
27. }
28. fis.close();
29.
30. byte[] digest = messageDigest.digest();
31. //對計算結果進行16進制編碼
32. return Hex.encode(digest);
33. }
34.
35. private static String getSHA(String str) throws NoSuchAlgorithmException {
36. MessageDigest messageDigest = MessageDigest.getInstance("SHA");
37. byte[] digest = messageDigest.digest(str.getBytes());
38. return Hex.encode(digest);
39. }
40.
41. }
~~~
官網上公布的Tomact的SHA值如下圖所示:

我們自己算出來的SHA值如下圖所示。

對比發現,計算出來的跟官網上公布的是一致的。