“MD5”加密算法全解析
1.長度固定:
不管多長的字符串,加密後長度都是一樣長
作用:方便平時信息的統計和管理2.易計算:
字符串和文件加密的過程是容易的.
作用: 開發者很容易理解和做出加密工具3.細微性
一個文件,不管多大,小到幾k,大到幾G,你只要改變裏面某個字符,那麼都會導致MD5值改變.
作用:很多軟件和應用在網站提供下載資源,其中包含了對文件的MD5碼,用戶下載後只需要用工具測一下下載好的文件,通過對比就知道該文件是否有過更改變動.4.不可逆性
你明明知道密文和加密方式,你卻無法反向計算出原密碼.
作用:基於這個特點,很多安全的加密方式都是用到.大大提高了數據的安全性關於撞庫破解:
這是概率極低的破解方法,原理就是:
1.建立一個大型的數據庫,把日常的各個語句,通過MD5加密成爲密文,不斷的積累大量的句子,放在一個龐大的數據庫裏.
2.比如一個人拿到了別人的密文,想去查詢真實的密碼,就需要那這個密文去到提供這個數據庫的公司網站去查詢.
這就是撞庫的概念.
1.獲取信息摘要對象:md5
通過信息摘要單例的構造函數獲取:
MessageDigest md5 = MessageDigest.getInstance("MD5");
- 1
- 2
2.信息摘要對象是對字節數組進行摘要的,所以先獲取字符串的字節數組.
byte[] bytes = str.getBytes();
- 1
- 2
3.信息摘要對象對字節數組進行摘要,得到摘要字節數組:
byte[] digest = md5.digest(bytes);
- 1
- 2
4.把摘要數組中的每一個字節轉換成16進制,並拼在一起就得到了MD5值.
(PS,有些轉換過來得到的是前面有6個f的情況,如:ffffff82,這是因爲前面有6組4個1,所以提前把這6組1111先變成0就好了,然後再轉16進制就沒有f了)
(其實也可以在後面續把f去掉)1.因爲是文件不是方法,所以不是像剛纔那樣通過摘要獲取字符串.
2.使用到另一個方法即可:就是信息摘要對象更新:md5.update(byte[] input)方法,用法是通過讀取流,不斷的更新從流中讀到的”信息數組”.
3.然後通過”信息摘要對象”獲取摘要,不用參數:md5.digest(),此時返回的數組就已經是包含內容的摘要數組了
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
0x:代表16進制;
一個f代表:4個1,即(1111);
所以0xffffffff代表:8組4個1
- 1
- 2
所以剛纔的0xffffff82就是前面6組都是1,後面兩組是
- 1
- 2
所以先與上0x000000ff,即
大家好,我們現在來講解關於加密方面的知識,說到加密我認爲不得不提MD5,因爲這是一種特殊的加密方式,它到底特殊在哪,現在我們就開始學習它
全稱:message-digest algorithm 5
翻譯過來就是:信息 摘要 算法 5
1.特點
2.後續講解
3.關於MD5加鹽:
比如我的銀行密碼是”12345”
1.得到的MD5是:827ccb0eea8a706c4c34a16891f84e7b
2.一個人截取到這個密文,那麼通過撞庫肯定容易撞出12345.
3.我們要做的就是加鹽,銀行密碼還是”12345”,然後我把銀行密碼加上我特定的字符串才計算MD5
所以密碼還是那個密碼,但是變成求”12345密碼加密987”的MD5值,然後再得到MD5,那麼這個MD5起碼可以確認那個數據庫不會有.
說了那麼多我們開始我們的MD5工具的製作
我們一般加密都是加密字符串或者文件,所以我們的工具就有加密字符串和文件的兩種方法,兩個方法同名,通過重載完成
1.加密字符串
邏輯思維:
2.加密文件
方法傳入的是文件對象 : file
以下是詳細代碼:
public class MD5Tool {
public static void main(String[] args) throws Exception {
/*--------------字符串--------------*/
String str = "12345";
String md1 = getMD5(str);
System.out.println(md1);//827ccb0eea8a706c4c34a16891f84e7b
/*--------------文件--------------*/
File file = new File("D:\\1.mp3");
String md2 = getMD5(file);
System.out.println(md2);//9068aaead9a5b75e6a54395d8183ec9
}
/**
* 邏輯:
*
* 1.獲取md5對象,通過"信息摘要"獲取實例構造("MD5").
* 2.md5對象對("字符串的"字節形式"-得到的數組)進行摘要",那麼會返回一個"摘要的字節數組"
* 3.摘要字節數組中的"每個二進制值"字節形式,"轉成十六進制形式",然後再把這些值給拼接起來,就是MD5值了
* (PS:爲了便於閱讀,把多餘的fff去掉,並且單個字符前加個0)
*
*/
public static String getMD5(String str) throws Exception {
String MD5 = "";
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bytes = str.getBytes();
byte[] digest = md5.digest(bytes);
for (int i = 0; i < digest.length; i++) {
//摘要字節數組中各個字節的"十六進制"形式.
int j = digest[i];
j = j & 0x000000ff;
String s1 = Integer.toHexString(j);
if (s1.length() == 1) {
s1 = "0" + s1;
}
MD5 += s1;
}
return MD5;
}
//重載,所以用戶傳入"字符串"或者"文件"都可以解決.
/**
* 處理邏輯:
* 1.現在傳入的是"文件",不是字符串
* 2.所以信息摘要對象.進行摘要得到數組不能像上面獲得:md5.digest(bytes),因爲不是str.getBytes得到bytes
* 3.其實還是通過mdt.digest();獲取到字節數組,但是前期必須要有一個方法必須是md5.update(),即"信息摘要對象"要先更新
* 4."信息摘要更新"裏面有(byte[] input),說明是讀取流獲取到的數組,所以我們就用這個方法.
* 5.所以最終的邏輯就是:
*
* 1.獲取文件的讀取流
* 2.不停的讀取流中的"內容"放入字符串,放一部分就"更新"一部分.直到全部完畢
* 3.然後調用md5.digest();就會得到有內容的字節數組,剩下的就和上邊一樣了.
*/
public static String getMD5(File file) throws Exception {
String MD5 = "";
MessageDigest md5 = MessageDigest.getInstance("MD5");
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte[1024 * 5];
int len = -1;
while ((len=fis.read(bytes))!=-1) {
//一部分一部分更新
md5.update(bytes, 0, len);
}
byte[] digest = md5.digest();
for (int i = 0; i <digest.length; i++) {
int n = digest[i] & 0x000000ff;
String s = Integer.toHexString(n);
MD5 += s;
}
return MD5;
}
}
拓展
0xfffffff代表的含義:
1111 - 1111 - 1111 - 1111 - 1111 - 1111 - 1111 - 1111
1111 - 1111 - 1111 - 1111 - 1111 - 1111 - 0111 - 0010
0000 - 0000 - 0000 - 0000 - 0000 - 0000 - 1111 - 1111
- 就得到了82了
上面的方法也可以寫成:
for (int i = 0; i < digest.length; i++) {
//摘要字節數組中各個字節的"十六進制"形式.
String s1 = Integer.toHexString( digest[i]);
//如果是8個長度的,把前面的6個f去掉,只獲取後面的
if (s1.length() == 8) {
s1 = s1.substring(6);
}
if (s1.length() == 1) {
s1 = "0" + s1;
}
MD5 += s1;
}