MD5 - Java加密与安全
生活随笔
收集整理的這篇文章主要介紹了
MD5 - Java加密与安全
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
JAVA的MD5MD5是一種摘要算法,他又稱哈希算法,數(shù)字指紋1. 摘要算法目的是計(jì)算任意長(zhǎng)度數(shù)據(jù)的摘要2. 而它的輸出,也就是他的摘要,是一個(gè)固定的長(zhǎng)度,相同的數(shù)據(jù)我們始終得到相同的輸出3. 而不同的輸入數(shù)據(jù)我們會(huì)盡量得到不同的輸出摘要算法的目的就是為了驗(yàn)證原始數(shù)據(jù)是否被篡改
如果我們的輸入是任意長(zhǎng)度的數(shù)據(jù),比如一個(gè)byte數(shù)組,我們輸出是一個(gè)固定長(zhǎng)度的byte數(shù)組,我們就可以把它稱之為摘要算法,例如我們對(duì)hello字符串做一個(gè)摘要,如果他讀到的是0x5e9182這個(gè)數(shù),我們對(duì)hello,java這個(gè)字符串做一個(gè)摘要算法,那么他就會(huì)得到一個(gè)不同的摘要輸出,我們對(duì)hello,bob做一個(gè)摘要輸出,他就會(huì)得到一個(gè)不同的摘要輸出
Java的Object.hashCode方法就是一個(gè)摘要算法,他的輸入是一個(gè)任意的數(shù)據(jù),而他的輸出是一個(gè)任意長(zhǎng)度的數(shù)據(jù)實(shí)際上它是一個(gè)int類型,4個(gè)長(zhǎng)度的byte類型數(shù)組,相同的輸入必須要得到相同的輸出,這也是為什么我們復(fù)寫(xiě)equals方法的時(shí)候,我們必須正確的復(fù)寫(xiě)hashCode方法
我們?cè)賮?lái)看一下什么是碰撞?碰撞是指兩個(gè)不同的輸入得到相同的輸出,例如我們對(duì)abc和xyz都做哈希算法,我們可能會(huì)得到相同的輸出,這個(gè)時(shí)候我們就說(shuō)發(fā)生了碰撞,碰撞能不能避免呢,碰撞是不能避免的,這是因?yàn)檩敵龅淖止?jié)長(zhǎng)度是固定的,而輸入的長(zhǎng)度是不固定的,所以哈希算法就是把一個(gè)無(wú)限的輸入集合,到一個(gè)有限的輸出集合,16個(gè)0到16個(gè)1一共只有65536個(gè)輸出,我們把無(wú)限的輸入到65536個(gè)輸出,那么肯定會(huì)有不同的輸出到相同的輸出的情況,也就是碰撞
我們?cè)賮?lái)看一下哈希算法的安全性:1. 首先一個(gè)好的哈希算法碰撞率要低2. 我們不能夠猜測(cè)輸出,我們來(lái)對(duì)比右邊的兩種哈希算法,如果java001的哈希算法是123456,而java002的哈希算法是123457那么我們就可以推算出java003的哈希算法是123458,這樣的哈希算法是不安全的哈希算法,一個(gè)安全的哈希算法對(duì)于任意的會(huì)造成輸出的完全不同,因此安全的哈希算法很難從結(jié)果找出思路,只能通過(guò)暴力窮舉
我們?cè)賮?lái)看一下常見(jiàn)的摘要算法:1.有MD5,SHA-1,SHA-256,RipeMD-160,他們的輸出長(zhǎng)度是128bits,160bits,256bits,160bits,對(duì)應(yīng)到字節(jié)數(shù),MD5是16個(gè)字節(jié),SHA-1是20個(gè)字節(jié),SHA-256是32個(gè)字節(jié),RipeMD-160也是20個(gè)字節(jié)
在JAVA中使用MD5非常的簡(jiǎn)單,首先我們導(dǎo)入java.security.MessageDigest這個(gè)類,然后我們通過(guò)MessageDigest的方法,傳入MD5獲取MessageDigest這個(gè)類,然后我們反復(fù)調(diào)用update方法,最后我們用digest()方法,獲得16個(gè)字節(jié)長(zhǎng)度的byte數(shù)組,這個(gè)byte數(shù)組就是我們輸入數(shù)據(jù)的最后輸出
?
輸入的數(shù)據(jù)是可以分片輸入的,我們可以一次性輸入helloworld,也可以把helloworld兩個(gè)單詞拆開(kāi),分別做update,得到的結(jié)果是一樣的 MD5可以用來(lái)驗(yàn)證文件的完整性,我們?cè)诰W(wǎng)上下載文件的時(shí)候,例如我們?cè)贛YSQL的網(wǎng)站下載MYSQL Community Server,MYSQL的網(wǎng)站會(huì)給出一個(gè)MD5值,我們下載完文件以后,通過(guò)計(jì)算MD5,和網(wǎng)站給出的MD5對(duì)比,就可以知道在下載的過(guò)程中,文件有沒(méi)有被損壞 MD5還可以存儲(chǔ)用戶的口令,如果我們有一個(gè)數(shù)據(jù)表,存放了username和password,我們的系統(tǒng)不存儲(chǔ)原始口令,而是存儲(chǔ)原始口令的MD5,這樣我們就不會(huì)在數(shù)據(jù)庫(kù)中以明文的方式存儲(chǔ)口令,那我們?nèi)绾闻袛嘤脩舻目诹钍欠裾_呢系統(tǒng)計(jì)算用戶原始口令的MD5,并且與數(shù)據(jù)庫(kù)存儲(chǔ)的MD5對(duì)比,如果相同,說(shuō)明口令正確,如果不同就說(shuō)明口令錯(cuò)誤 用MD5注意要避免彩虹表攻擊,什么是彩虹表呢,彩虹表是預(yù)先計(jì)算好的,常用口令和MD5對(duì)照表,如果用戶使用了常用口令,那么黑客可以通過(guò)彩虹表,進(jìn)行MD5就可以查出用戶的原始口令,例如Bob,Alice,tim,我們存儲(chǔ)的是MD5,但是黑客通過(guò)彩虹表可以輕松的反查MD5的原始口令,分別是hello123,12345678,passwd0rd這樣簡(jiǎn)單的原始口令,所以要抵御彩虹表的攻擊,我們不能直接原始口令的MD5,而是要對(duì)這個(gè)口令隨機(jī)增加一個(gè)隨機(jī)數(shù),這個(gè)隨機(jī)數(shù)通常稱為salt,經(jīng)過(guò)salt和原始口令一塊計(jì)算的MD5,就很難通過(guò)MD5再反查出來(lái)了 package com.learn.securl;import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;/*** 我們先看一下如何使用MD5* @author Leon.Sun**/ public class MD5Demo {public static byte[] toMD5(byte[] input) {MessageDigest md = null;try {/*** 傳入字符串MD5* 獲得一個(gè)MessageDigest的實(shí)例*/md = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException e) {e.printStackTrace();}/*** 緊接著傳入輸入的byte*/md.update(input);/*** 最后我們用digest方法返回MD5*/return md.digest();}/*** 然后我們使用一個(gè)main方法來(lái)使用MD5* @throws Exception */public static void main(String[] args) throws Exception {/*** 這里我們定義了一個(gè)字符串s*/String s = "MD5摘要算法測(cè)試";/*** 通過(guò)getBytes把做一個(gè)字符串變成一個(gè)字節(jié)數(shù)組* 注意MD5的輸入是字節(jié)而不是字符串* 所以我們把一個(gè)字符串變成一個(gè)字節(jié)數(shù)組*/byte[] r = toMD5(s.getBytes("UTF-8"));/*** 最后我們要打印一個(gè)byte數(shù)組* 如果我們直接打印byte數(shù)組* 得到的是一個(gè)byte數(shù)組的地址* 我們可以通過(guò)String.format傳一個(gè)百分號(hào)032x* 然后把一個(gè)byte數(shù)組變成一個(gè)BigInteger,* 就可以使用16進(jìn)制的形式打印數(shù)組* c038cfbd1a587fcf4cbfe7d5a9094dca* 我們看到MD5最后的結(jié)果是這樣16進(jìn)制表示的字節(jié)數(shù)組* */System.out.println(String.format("%032x", new BigInteger(1,r)));} } package com.learn.securl;import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;public class MD5SaltDemo {public static byte[] toMD5(byte[] input) {MessageDigest md = null;try {md = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException e) {e.printStackTrace();}md.update(input);return md.digest();}public static void main(String[] args) throws Exception {/*** 假設(shè)我們的輸入是我們用戶的password*/String passwd = "helloworld";/*** 同時(shí)我們?yōu)榱嗽鰪?qiáng)我們MD5的安全性* 我們引入了一個(gè)隨機(jī)的Salt*/String salt = "Random salt";/*** 然后把這兩個(gè)字符串拼在一塊* 得到byte數(shù)組* 然后再計(jì)算MD5* 57de63c427b44d289128c3a8a496fb75* 我們可以看到通過(guò)引入一個(gè)隨機(jī)數(shù)salt,* 我們可以把一個(gè)不安全的口令,* 變?yōu)橄鄬?duì)安全的MD5* */byte[] r = MD5SaltDemo.toMD5((salt+passwd).getBytes("UTF-8"));System.out.println(String.format("%032x", new BigInteger(1,r)));}} 最后我們總結(jié)一下:1. MD5是一種常用的哈希算法,他的輸出是固定長(zhǎng)度的,128bits,也就是16個(gè)字節(jié)2. MD5常用于驗(yàn)證數(shù)據(jù)的完整性3. 當(dāng)我們使用MD5存儲(chǔ)口令的時(shí)候,要考慮到彩虹表的攻擊?
總結(jié)
以上是生活随笔為你收集整理的MD5 - Java加密与安全的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Base64编码 - Java加密与安全
- 下一篇: SHA1 - Java加密与安全