md5和SHA校验码
md5已經(jīng)不安全了,中國山東大學(xué)女學(xué)霸王小云破解了一系列密碼,當(dāng)真是巾幗不讓須眉.說是破解,其實(shí)就是給你一個(gè)md5碼,讓你求出這個(gè)md5碼所對(duì)應(yīng)的原始信息,顯然一個(gè)md5對(duì)應(yīng)無數(shù)種原始信息.而md5的特性就是難以還原初始信息,但是王小云可以迅速找到給定md5碼的可行解.md5的解空間雖然巨大,但是卻難以捕捉到解.
md5雖然已經(jīng)不安全了,但是仍然可以用于校驗(yàn).
md5不是編碼,編碼是能夠還原初始信息的,而md5只是固定的16byte,它只能從總體上反映初始信息的一些特征,卻無法完整的還原出來,因?yàn)槌跏夹畔⒌絤d5碼是一個(gè)多對(duì)一映射.
md5中大量使用小頭序,這點(diǎn)十分坑.還好java中有神奇?zhèn)ゴ蟮腂yteBuffer.ByteBuffer有四個(gè)索引:mark,limit,position,capacity.
mark表示標(biāo)記;limit表示position最大可以讀到哪里;position表示當(dāng)前位置;capacity表示最大容量.
ByteBuffer這個(gè)類支持"流式"編程,比如put(byte)函數(shù)返回值仍然是ByteBuffer,這樣就可以接著put了.
ByteBuffer這個(gè)類最重要的就是4個(gè)指針,玩轉(zhuǎn)了四個(gè)指針就學(xué)會(huì)了控制ByteBuffer,例如:
flip()將limit置為當(dāng)前position,將position置為0,準(zhǔn)備從頭讀取數(shù)據(jù),注意只能讀取0~limit這一部分?jǐn)?shù)據(jù);
rewind()將position置為0;
mark()標(biāo)記當(dāng)前position,可以使用reset()將position重置為mark時(shí)的位置.
compact()將當(dāng)前postion之前的字節(jié)清空.
clear()清空一切,將limit移動(dòng)到copacity處,準(zhǔn)備讀入數(shù)據(jù).
明白了如何操作這些指針,就明白了ByteBuffer.
當(dāng)不了解md5的時(shí)候,聽人們說md5的某些特性,覺得還是道聽途說,只有親自實(shí)現(xiàn)之后才能自己總結(jié)出md5有哪些特點(diǎn).
下面給出md5信息摘要算法
import static java.lang.Math.abs; import static java.lang.Math.floor; import static java.lang.Math.pow; import static java.lang.Math.sin;import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5 {// 移位的位數(shù),分成4種,每種4個(gè)數(shù),每種重復(fù)4次.不知道為啥是這些數(shù)字int[] s = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9,14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4,11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15,21, 6, 10, 15, 21, 6, 10, 15, 21};// 在init函數(shù)中初始化k[i]int k[] = new int[64];void init() {for (int i = 0; i < 64; i++) {long x = (long) floor(abs(sin(i + 1)) * pow(2, 32));k[i] = (int) (x & 0xffffffff);}}// 循環(huán)左移操作,比如4位的1011,循環(huán)左移一位相當(dāng)于0110|1int leftRotate(int x, int n) {return (x << n) | (x >>> (32 - n));}byte[] digest(byte[] srcData) throws IOException {// 原數(shù)據(jù)字節(jié)數(shù)+8byte的原始長度表示=l,l有點(diǎn)偏短,如果它不是64的倍數(shù),那么會(huì)舍棄一些,所以要加上一;如果它是64的倍數(shù),那么需要補(bǔ)上一個(gè)字節(jié),至少要添加一個(gè)chunk.// 一個(gè)chunk為64byte,其中最后一個(gè)chunk的前56byte為數(shù)據(jù)+補(bǔ)齊的數(shù)據(jù),最后8byte為long類型的數(shù)據(jù),表示原始數(shù)據(jù)長度.// 整個(gè)md5都是基于小頭序的int chunkCount = (srcData.length + 8) / 64 + 1;ByteBuffer buffer = ByteBuffer.allocate(chunkCount * 64).order(ByteOrder.LITTLE_ENDIAN);buffer.put(srcData).put((byte) 0x80).position(buffer.limit() - 8);buffer.putLong(8 * srcData.length).flip();//flip準(zhǔn)備讀取數(shù)據(jù)int a0 = 0x67452301, b0 = 0xefcdab89, c0 = 0x98badcfe, d0 = 0x10325476;while (buffer.hasRemaining()) {int m[] = new int[16];for (int i = 0; i < 16; i++) {m[i] = buffer.getInt();}int a = a0, b = b0, c = c0, d = d0;int f, g;for (int i = 0; i < 64; i++) {if (i < 16) {f = (b & c) | (~b & d);g = i;} else if (i < 32) {f = (d & b) | (~d & c);g = (5 * i + 1) % 16;} else if (i < 48) {f = b ^ c ^ d;g = (3 * i + 5) % 16;} else {f = c ^ (b | ~d);g = (7 * i) % 16;}int dd = d;d = c;c = b;b = b + leftRotate(a + f + k[i] + m[g], s[i]);a = dd;}a0 += a;b0 += b;c0 += c;d0 += d;}return ByteBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN).putInt(a0).putInt(b0).putInt(c0).putInt(d0).array();}static void show(byte[] b) {for (byte i : b) {System.out.printf("%02X", i);}System.out.println();}public static void main(String[] args)throws NoSuchAlgorithmException, IOException {byte[] b = "魏印福".getBytes();MessageDigest md5 = MessageDigest.getInstance("MD5");md5.update(b);byte[] res = md5.digest();show(res);MD5 m = new MD5();m.init();res = m.digest(b);show(res);} }?跟md5一樣,SHA也有好多版本,SHA1,SHA2,SHA3,其中SHA2,SHA3又分成了好多版本.SHA加密強(qiáng)度比md5更強(qiáng),它名叫Secure Hash Algorithm.md5校驗(yàn)碼位長相當(dāng)于4個(gè)int,SHA的位長相當(dāng)于5個(gè)int.二者都是以64Byte為一個(gè)chunk進(jìn)行處理.
下面給出java中如何使用庫函數(shù)自帶的SHA
public class SHA {static String tos(byte[] b) {String ans = "";for (int i = 0; i < b.length; i++) {ans += String.format("%02X", b[i]);}return ans;}public static void main(String[] args) throws Exception {byte[] data = "魏印福".getBytes();MessageDigest digest = MessageDigest.getInstance("SHA");byte[] ans = digest.digest(data);System.out.println(tos(ans));System.out.println(tos(MessageDigest.getInstance("SHA-1").digest(data)));} }?
總結(jié)
以上是生活随笔為你收集整理的md5和SHA校验码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java设计模式之七大结构型模式
- 下一篇: 做梦梦到摘葡萄是怎么回事儿