簡(jiǎn)介
全稱(chēng)為“Message Digest Algorithm 5”,中文名“消息摘要算法第五版”
MD5 屬于單向加密算法,是不可逆的加密方式,也就是說(shuō),采用了 MD5 加密方式加密之后,就不能對(duì)加密的結(jié)果進(jìn)行解密,得到原有的字符串,這是不可以的。
特點(diǎn)
- 壓縮性:任意長(zhǎng)度的數(shù)據(jù),算出的MD5值長(zhǎng)度都是固定的。
- 容易計(jì)算:從原數(shù)據(jù)計(jì)算出MD5值很容易。
- 抗修改性:對(duì)原數(shù)據(jù)進(jìn)行任何改動(dòng),哪怕只修改1個(gè)字節(jié),所得到的MD5值都有很大區(qū)別。
- 弱抗碰撞:已知原數(shù)據(jù)和其MD5值,想找到一個(gè)具有相同MD5值的數(shù)據(jù)(即偽造數(shù)據(jù))是非常困難的。
- 強(qiáng)抗碰撞:想找到兩個(gè)不同的數(shù)據(jù),使它們具有相同的MD5值,是非常困難的。
因?yàn)檫@些特點(diǎn),md5也常用來(lái)做一致性校驗(yàn)
加密原理簡(jiǎn)介
MD5 以 512 位分組來(lái)處理輸入的信息,且每一分組又被劃分為 16 個(gè) 32 位子分組,經(jīng)過(guò)了一系列的處理后,算法的輸出由四個(gè) 32 位分組組成,將這四個(gè) 32 位分組級(jí)聯(lián)后將生成一個(gè) 128 位散列值。然后每四位組成一個(gè)十六進(jìn)制數(shù),所以md5的結(jié)果是32位的。傳言中的16位是將32位去掉了前8后8
過(guò)程
填充
在 MD5 算法中,首先需要對(duì)信息進(jìn)行填充,使其位長(zhǎng)對(duì) 512 求余的結(jié)果等于 448,并且填充必須進(jìn)行,即使其位長(zhǎng)對(duì) 512 求余的結(jié)果等于 448。因此,信息的位長(zhǎng)(Bits Length)將被擴(kuò)展至 N * 512 + 448,N 為一個(gè)非負(fù)整數(shù),N 可以是零。
填充的方法如下:
- 在信息的后面填充一個(gè) 1 和無(wú)數(shù)個(gè) 0,直到滿(mǎn)足上面的條件時(shí)才停止用 0 對(duì)信息的填充。
- 在這個(gè)結(jié)果后面附加一個(gè)以 64 位二進(jìn)制表示的填充前信息長(zhǎng)度(單位為Bit),如果二 進(jìn)制表示的填充前信息長(zhǎng)度超過(guò) 64 位,則取低 64 位。
經(jīng)過(guò)這兩步的處理,信息的位長(zhǎng) = N * 512 + 448 + 64 = (N + 1)* 512,即長(zhǎng)度恰好是 512 的整數(shù)倍。這樣做的原因是為滿(mǎn)足后面處理中對(duì)信息長(zhǎng)度的要求。
初始化變量
初始的 128 位值為初試鏈接變量,這些參數(shù)用于第一輪的運(yùn)算,以大端字節(jié)序來(lái)表示,他們分別為: A = 0x01234567,B = 0x89ABCDEF,C = 0xFEDCBA98,D = 0x76543210。
(每一個(gè)變量給出的數(shù)值是高字節(jié)存于內(nèi)存低地址,低字節(jié)存于內(nèi)存高地址,即大端字節(jié)序。在程序中變量 A、B、C、D 的值分別為0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476)
處理分組數(shù)據(jù)
每一分組的算法流程如下:
第一分組需要將上面四個(gè)鏈接變量復(fù)制到另外四個(gè)變量中:A 到 a,B 到 b,C 到 c,D 到 d。從第二分組開(kāi)始的變量為上一分組的運(yùn)算結(jié)果,即 A = a, B = b, C = c, D = d。
主循環(huán)有四輪,每輪循環(huán)都很相似。第一輪進(jìn)行 16 次操作。每次操作對(duì) a、b、c 和 d 中的其中三個(gè)作一次非線(xiàn)性函數(shù)運(yùn)算,然后將所得結(jié)果加上第四個(gè)變量,文本的一個(gè)子分組和一個(gè)常數(shù)。再將所得結(jié)果向左環(huán)移一個(gè)不定的數(shù),并加上 a、b、c 或 d 中之一。最后用該結(jié)果取代 a、b、c 或 d 中之一。
輸出
最后的輸出是 a、b、c 和 d 的級(jí)聯(lián)。
java demo
MessageDigest md = MessageDigest.getInstance("MD5");
md.update("kkk".getBytes());
System.out.println( md.digest());
輸出的是16說(shuō)明是16個(gè)字節(jié),128個(gè)位,直接打印成string的時(shí)候是亂碼,說(shuō)明不是常規(guī)的基本字符,所以一般轉(zhuǎn)成16進(jìn)制的
MessageDigest md = MessageDigest.getInstance("MD5");
md.update("kkk".getBytes());
System.out.println(new BigInteger(1, md.digest()).toString(16));
這樣產(chǎn)生的便是一個(gè)16進(jìn)制的字符串模式
MessageDigest md = MessageDigest.getInstance("MD5");
md.update("kkk".getBytes());
byte[] digest=md.digest();
StringBuffer buffer = new StringBuffer();
for (byte oneB : digest) {
String str = Integer.toHexString(oneB & 0xff);
if (str.length() == 1) {
str="0"+str;
}
buffer.append(str);
}
System.out.println(buffer.toString());