包含md5java代碼及注釋的詞條

md5 算法程序+詳細注釋,高分求教!

MD5加密算法簡介

十余年專注成都網(wǎng)站制作,成都定制網(wǎng)站,個人網(wǎng)站制作服務(wù),為大家分享網(wǎng)站制作知識、方案,網(wǎng)站設(shè)計流程、步驟,成功服務(wù)上千家企業(yè)。為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計及定制高端網(wǎng)站建設(shè)服務(wù),專注于成都定制網(wǎng)站,高端網(wǎng)頁制作,對陽光房等多個領(lǐng)域,擁有豐富的網(wǎng)站建設(shè)經(jīng)驗。

一、綜述

MD5的全稱是message-digest algorithm 5(信息-摘要算法),在90年代初由mit laboratory for computer science和rsa data security inc的ronald l. rivest開發(fā)出來,經(jīng)md2、md3和md4發(fā)展而來。它的作用是讓大容量信息在用數(shù)字簽名軟件簽署私人密匙前被"壓縮"成一種保密的格式(就是把一 個任意長度的字節(jié)串變換成一定長的大整數(shù))。不管是md2、md4還是md5,它們都需要獲得一個隨機長度的信息并產(chǎn)生一個128位的信息摘要。雖然這些 算法的結(jié)構(gòu)或多或少有些相似,但md2的設(shè)計與md4和md5完全不同,那是因為md2是為8位機器做過設(shè)計優(yōu)化的,而md4和md5卻是面向32位的電 腦。這三個算法的描述和c語言源代碼在internet rfcs 1321中有詳細的描述(),這是一份最權(quán)威的文檔,由ronald l. rivest在1992年8月向ieft提交。

rivest在1989年開發(fā)出md2算法。在這個算法中,首先對信 息進行數(shù)據(jù)補位,使信息的字節(jié)長度是16的倍數(shù)。然后,以一個16位的檢驗和追加到信息末尾。并且根據(jù)這個新產(chǎn)生的信息計算出散列值。后來,rogier 和chauvaud發(fā)現(xiàn)如果忽略了檢驗和將產(chǎn)生md2沖突。md2算法的加密后結(jié)果是唯一的--既沒有重復(fù)。

為了加強算法的安全性, rivest在1990年又開發(fā)出md4算法。md4算法同樣需要填補信息以確保信息的字節(jié)長度加上448后能被512整除(信息字節(jié)長度mod 512 = 448)。然后,一個以64位二進制表示的信息的最初長度被添加進來。信息被處理成512位damg?rd/merkle迭代結(jié)構(gòu)的區(qū)塊,而且每個區(qū)塊要 通過三個不同步驟的處理。den boer和bosselaers以及其他人很快的發(fā)現(xiàn)了攻擊md4版本中第一步和第三步的漏洞。dobbertin向大家演示了如何利用一部普通的個人電 腦在幾分鐘內(nèi)找到md4完整版本中的沖突(這個沖突實際上是一種漏洞,它將導(dǎo)致對不同的內(nèi)容進行加密卻可能得到相同的加密后結(jié)果)。毫無疑問,md4就此 被淘汰掉了。

盡管md4算法在安全上有個這么大的漏洞,但它對在其后才被開發(fā)出來的好幾種信息安全加密算法的出現(xiàn)卻有著不可忽視的引導(dǎo)作用。除了md5以外,其中比較有名的還有sha-1、ripe-md以及haval等。

一年以后,即1991年,rivest開發(fā)出技術(shù)上更為趨近成熟的md5算法。它在md4的基礎(chǔ)上增加了"安全-帶子"(safety-belts)的 概念。雖然md5比md4稍微慢一些,但卻更為安全。這個算法很明顯的由四個和md4設(shè)計有少許不同的步驟組成。在md5算法中,信息-摘要的大小和填充 的必要條件與md4完全相同。den boer和bosselaers曾發(fā)現(xiàn)md5算法中的假沖突(pseudo-collisions),但除此之外就沒有其他被發(fā)現(xiàn)的加密后結(jié)果了。

van oorschot和wiener曾經(jīng)考慮過一個在散列中暴力搜尋沖突的函數(shù)(brute-force hash function),而且他們猜測一個被設(shè)計專門用來搜索md5沖突的機器(這臺機器在1994年的制造成本大約是一百萬美元)可以平均每24天就找到一 個沖突。但單從1991年到2001年這10年間,竟沒有出現(xiàn)替代md5算法的md6或被叫做其他什么名字的新算法這一點,我們就可以看出這個瑕疵并沒有 太多的影響md5的安全性。上面所有這些都不足以成為md5的在實際應(yīng)用中的問題。并且,由于md5算法的使用不需要支付任何版權(quán)費用的,所以在一般的情 況下(非絕密應(yīng)用領(lǐng)域。但即便是應(yīng)用在絕密領(lǐng)域內(nèi),md5也不失為一種非常優(yōu)秀的中間技術(shù)),md5怎么都應(yīng)該算得上是非常安全的了。

二、算法的應(yīng)用

md5的典型應(yīng)用是對一段信息(message)產(chǎn)生信息摘要(message-digest),以防止被篡改。比如,在unix下有很多軟件在下載的時候都有一個文件名相同,文件擴展名為.md5的文件,在這個文件中通常只有一行文本,大致結(jié)構(gòu)如:

md5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461

這就是tanajiya.tar.gz文件的數(shù)字簽名。md5將整個文件當(dāng)作一個大文本信息,通過其不可逆的字符串變換算法,產(chǎn)生了這個唯一的md5信 息摘要。如果在以后傳播這個文件的過程中,無論文件的內(nèi)容發(fā)生了任何形式的改變(包括人為修改或者下載過程中線路不穩(wěn)定引起的傳輸錯誤等),只要你對這個 文件重新計算md5時就會發(fā)現(xiàn)信息摘要不相同,由此可以確定你得到的只是一個不正確的文件。如果再有一個第三方的認證機構(gòu),用md5還可以防止文件作者的 "抵賴",這就是所謂的數(shù)字簽名應(yīng)用。

md5還廣泛用于加密和解密技術(shù)上。比如在unix系統(tǒng)中用戶的密碼就是以md5(或其它類似的算 法)經(jīng)加密后存儲在文件系統(tǒng)中。當(dāng)用戶登錄的時候,系統(tǒng)把用戶輸入的密碼計算成md5值,然后再去和保存在文件系統(tǒng)中的md5值進行比較,進而確定輸入的 密碼是否正確。通過這樣的步驟,系統(tǒng)在并不知道用戶密碼的明碼的情況下就可以確定用戶登錄系統(tǒng)的合法性。這不但可以避免用戶的密碼被具有系統(tǒng)管理員權(quán)限的 用戶知道,而且還在一定程度上增加了密碼被破解的難度。

正是因為這個原因,現(xiàn)在被黑客使用最多的一種破譯密碼的方法就是一種被稱為"跑字 典"的方法。有兩種方法得到字典,一種是日常搜集的用做密碼的字符串表,另一種是用排列組合方法生成的,先用md5程序計算出這些字典項的md5值,然后 再用目標的md5值在這個字典中檢索。我們假設(shè)密碼的最大長度為8位字節(jié)(8 bytes),同時密碼只能是字母和數(shù)字,共26+26+10=62個字符,排列組合出的字典的項數(shù)則是p(62,1)+p(62,2)….+p (62,8),那也已經(jīng)是一個很天文的數(shù)字了,存儲這個字典就需要tb級的磁盤陣列,而且這種方法還有一個前提,就是能獲得目標賬戶的密碼md5值的情況 下才可以。這種加密技術(shù)被廣泛的應(yīng)用于unix系統(tǒng)中,這也是為什么unix系統(tǒng)比一般操作系統(tǒng)更為堅固一個重要原因。

三、算法描述

對md5算法簡要的敘述可以為:md5以512位分組來處理輸入的信息,且每一分組又被劃分為16個32位子分組,經(jīng)過了一系列的處理后,算法的輸出由四個32位分組組成,將這四個32位分組級聯(lián)后將生成一個128位散列值。

在md5算法中,首先需要對信息進行填充,使其字節(jié)長度對512求余的結(jié)果等于448。因此,信息的字節(jié)長度(bits length)將被擴展至n*512+448,即n*64+56個字節(jié)(bytes),n為一個正整數(shù)。填充的方法如下,在信息的后面填充一個1和無數(shù)個 0,直到滿足上面的條件時才停止用0對信息的填充。然后,在在這個結(jié)果后面附加一個以64位二進制表示的填充前信息長度。經(jīng)過這兩步的處理,現(xiàn)在的信息字 節(jié)長度=n*512+448+64=(n+1)*512,即長度恰好是512的整數(shù)倍。這樣做的原因是為滿足后面處理中對信息長度的要求。

md5中有四個32位被稱作鏈接變量(chaining variable)的整數(shù)參數(shù),他們分別為:a=0x01234567,b=0x89abcdef,c=0xfedcba98,d=0x76543210。

當(dāng)設(shè)置好這四個鏈接變量后,就開始進入算法的四輪循環(huán)運算。循環(huán)的次數(shù)是信息中512位信息分組的數(shù)目。

將上面四個鏈接變量復(fù)制到另外四個變量中:a到a,b到b,c到c,d到d。

主循環(huán)有四輪(md4只有三輪),每輪循環(huán)都很相似。第一輪進行16次操作。每次操作對a、b、c和d中的其中三個作一次非線性函數(shù)運算,然后將所得結(jié) 果加上第四個變量,文本的一個子分組和一個常數(shù)。再將所得結(jié)果向右環(huán)移一個不定的數(shù),并加上a、b、c或d中之一。最后用該結(jié)果取代a、b、c或d中之 一。

以一下是每次操作中用到的四個非線性函數(shù)(每輪一個)。

f(x,y,z) =(xy)|((~x)z)

g(x,y,z) =(xz)|(y(~z))

h(x,y,z) =x^y^z

i(x,y,z)=y^(x|(~z))

(是與,|是或,~是非,^是異或)

這四個函數(shù)的說明:如果x、y和z的對應(yīng)位是獨立和均勻的,那么結(jié)果的每一位也應(yīng)是獨立和均勻的。

f是一個逐位運算的函數(shù)。即,如果x,那么y,否則z。函數(shù)h是逐位奇偶操作符。

假設(shè)mj表示消息的第j個子分組(從0到15),

ff(a,b,c,d,mj,s,ti) 表示 a=b+((a+(f(b,c,d)+mj+ti)

gg(a,b,c,d,mj,s,ti) 表示 a=b+((a+(g(b,c,d)+mj+ti)

hh(a,b,c,d,mj,s,ti) 表示 a=b+((a+(h(b,c,d)+mj+ti)

ii(a,b,c,d,mj,s,ti) 表示 a=b+((a+(i(b,c,d)+mj+ti)

這四輪(64步)是:

第一輪

ff(a,b,c,d,m0,7,0xd76aa478)

ff(d,a,b,c,m1,12,0xe8c7b756)

ff(c,d,a,b,m2,17,0x242070db)

ff(b,c,d,a,m3,22,0xc1bdceee)

ff(a,b,c,d,m4,7,0xf57c0faf)

ff(d,a,b,c,m5,12,0x4787c62a)

ff(c,d,a,b,m6,17,0xa8304613)

ff(b,c,d,a,m7,22,0xfd469501)

ff(a,b,c,d,m8,7,0x698098d8)

ff(d,a,b,c,m9,12,0x8b44f7af)

ff(c,d,a,b,m10,17,0xffff5bb1)

ff(b,c,d,a,m11,22,0x895cd7be)

ff(a,b,c,d,m12,7,0x6b901122)

ff(d,a,b,c,m13,12,0xfd987193)

ff(c,d,a,b,m14,17,0xa679438e)

ff(b,c,d,a,m15,22,0x49b40821)

第二輪

gg(a,b,c,d,m1,5,0xf61e2562)

gg(d,a,b,c,m6,9,0xc040b340)

gg(c,d,a,b,m11,14,0x265e5a51)

gg(b,c,d,a,m0,20,0xe9b6c7aa)

gg(a,b,c,d,m5,5,0xd62f105d)

gg(d,a,b,c,m10,9,0x02441453)

gg(c,d,a,b,m15,14,0xd8a1e681)

gg(b,c,d,a,m4,20,0xe7d3fbc8)

gg(a,b,c,d,m9,5,0x21e1cde6)

gg(d,a,b,c,m14,9,0xc33707d6)

gg(c,d,a,b,m3,14,0xf4d50d87)

gg(b,c,d,a,m8,20,0x455a14ed)

gg(a,b,c,d,m13,5,0xa9e3e905)

gg(d,a,b,c,m2,9,0xfcefa3f8)

gg(c,d,a,b,m7,14,0x676f02d9)

gg(b,c,d,a,m12,20,0x8d2a4c8a)

第三輪

hh(a,b,c,d,m5,4,0xfffa3942)

hh(d,a,b,c,m8,11,0x8771f681)

hh(c,d,a,b,m11,16,0x6d9d6122)

hh(b,c,d,a,m14,23,0xfde5380c)

hh(a,b,c,d,m1,4,0xa4beea44)

hh(d,a,b,c,m4,11,0x4bdecfa9)

hh(c,d,a,b,m7,16,0xf6bb4b60)

hh(b,c,d,a,m10,23,0xbebfbc70)

hh(a,b,c,d,m13,4,0x289b7ec6)

hh(d,a,b,c,m0,11,0xeaa127fa)

hh(c,d,a,b,m3,16,0xd4ef3085)

hh(b,c,d,a,m6,23,0x04881d05)

hh(a,b,c,d,m9,4,0xd9d4d039)

hh(d,a,b,c,m12,11,0xe6db99e5)

hh(c,d,a,b,m15,16,0x1fa27cf8)

hh(b,c,d,a,m2,23,0xc4ac5665)

第四輪

ii(a,b,c,d,m0,6,0xf4292244)

ii(d,a,b,c,m7,10,0x432aff97)

ii(c,d,a,b,m14,15,0xab9423a7)

ii(b,c,d,a,m5,21,0xfc93a039)

ii(a,b,c,d,m12,6,0x655b59c3)

ii(d,a,b,c,m3,10,0x8f0ccc92)

ii(c,d,a,b,m10,15,0xffeff47d)

ii(b,c,d,a,m1,21,0x85845dd1)

ii(a,b,c,d,m8,6,0x6fa87e4f)

ii(d,a,b,c,m15,10,0xfe2ce6e0)

ii(c,d,a,b,m6,15,0xa3014314)

ii(b,c,d,a,m13,21,0x4e0811a1)

ii(a,b,c,d,m4,6,0xf7537e82)

ii(d,a,b,c,m11,10,0xbd3af235)

ii(c,d,a,b,m2,15,0x2ad7d2bb)

ii(b,c,d,a,m9,21,0xeb86d391)

常數(shù)ti可以如下選擇:

在第i步中,ti是4294967296*abs(sin(i))的整數(shù)部分,i的單位是弧度。(4294967296等于2的32次方)

所有這些完成之后,將a、b、c、d分別加上a、b、c、d。然后用下一分組數(shù)據(jù)繼續(xù)運行算法,最后的輸出是a、b、c和d的級聯(lián)。

當(dāng)你按照我上面所說的方法實現(xiàn)md5算法以后,你可以用以下幾個信息對你做出來的程序作一個簡單的測試,看看程序有沒有錯誤。

md5 ("") = d41d8cd98f00b204e9800998ecf8427e

md5 ("a") = 0cc175b9c0f1b6a831c399e269772661

md5 ("abc") = 900150983cd24fb0d6963f7d28e17f72

md5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0

md5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b

md5 ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f

md5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a

如果你用上面的信息分別對你做的md5算法實例做測試,最后得出的結(jié)論和標準答案完全一樣,那我就要在這里象你道一聲祝賀了。要知道,我的程序在第一次編譯成功的時候是沒有得出和上面相同的結(jié)果的。

四、MD5的安全性

md5相對md4所作的改進:

1. 增加了第四輪;

2. 每一步均有唯一的加法常數(shù);

3. 為減弱第二輪中函數(shù)g的對稱性從(xy)|(xz)|(yz)變?yōu)?xz)|(y(~z));

4. 第一步加上了上一步的結(jié)果,這將引起更快的雪崩效應(yīng);

5. 改變了第二輪和第三輪中訪問消息子分組的次序,使其更不相似;

6. 近似優(yōu)化了每一輪中的循環(huán)左移位移量以實現(xiàn)更快的雪崩效應(yīng)。各輪的位移量互不相同。

java的md5的加密算法代碼

import java.lang.reflect.*;

/*******************************************************************************

* keyBean 類實現(xiàn)了RSA Data Security, Inc.在提交給IETF 的RFC1321中的keyBean message-digest

* 算法。

******************************************************************************/

public class keyBean {

/*

* 下面這些S11-S44實際上是一個4*4的矩陣,在原始的C實現(xiàn)中是用#define 實現(xiàn)的, 這里把它們實現(xiàn)成為static

* final是表示了只讀,切能在同一個進程空間內(nèi)的多個 Instance間共享

*/

static final int S11 = 7;

static final int S12 = 12;

static final int S13 = 17;

static final int S14 = 22;

static final int S21 = 5;

static final int S22 = 9;

static final int S23 = 14;

static final int S24 = 20;

static final int S31 = 4;

static final int S32 = 11;

static final int S33 = 16;

static final int S34 = 23;

static final int S41 = 6;

static final int S42 = 10;

static final int S43 = 15;

static final int S44 = 21;

static final byte[] PADDING = { -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0 };

/*

* 下面的三個成員是keyBean計算過程中用到的3個核心數(shù)據(jù),在原始的C實現(xiàn)中 被定義到keyBean_CTX結(jié)構(gòu)中

*/

private long[] state = new long[4]; // state (ABCD)

private long[] count = new long[2]; // number of bits, modulo 2^64 (lsb

// first)

private byte[] buffer = new byte[64]; // input buffer

/*

* digestHexStr是keyBean的唯一一個公共成員,是最新一次計算結(jié)果的 16進制ASCII表示.

*/

public String digestHexStr;

/*

* digest,是最新一次計算結(jié)果的2進制內(nèi)部表示,表示128bit的keyBean值.

*/

private byte[] digest = new byte[16];

/*

* getkeyBeanofStr是類keyBean最主要的公共方法,入口參數(shù)是你想要進行keyBean變換的字符串

* 返回的是變換完的結(jié)果,這個結(jié)果是從公共成員digestHexStr取得的.

*/

public String getkeyBeanofStr(String inbuf) {

keyBeanInit();

keyBeanUpdate(inbuf.getBytes(), inbuf.length());

keyBeanFinal();

digestHexStr = "";

for (int i = 0; i 16; i++) {

digestHexStr += byteHEX(digest[i]);

}

return digestHexStr;

}

// 這是keyBean這個類的標準構(gòu)造函數(shù),JavaBean要求有一個public的并且沒有參數(shù)的構(gòu)造函數(shù)

public keyBean() {

keyBeanInit();

return;

}

/* keyBeanInit是一個初始化函數(shù),初始化核心變量,裝入標準的幻數(shù) */

private void keyBeanInit() {

count[0] = 0L;

count[1] = 0L;

// /* Load magic initialization constants.

state[0] = 0x67452301L;

state[1] = 0xefcdab89L;

state[2] = 0x98badcfeL;

state[3] = 0x10325476L;

return;

}

/*

* F, G, H ,I 是4個基本的keyBean函數(shù),在原始的keyBean的C實現(xiàn)中,由于它們是

* 簡單的位運算,可能出于效率的考慮把它們實現(xiàn)成了宏,在java中,我們把它們 實現(xiàn)成了private方法,名字保持了原來C中的。

*/

private long F(long x, long y, long z) {

return (x y) | ((~x) z);

}

private long G(long x, long y, long z) {

return (x z) | (y (~z));

}

private long H(long x, long y, long z) {

return x ^ y ^ z;

}

private long I(long x, long y, long z) {

return y ^ (x | (~z));

}

/*

* FF,GG,HH和II將調(diào)用F,G,H,I進行近一步變換 FF, GG, HH, and II transformations for

* rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent

* recomputation.

*/

private long FF(long a, long b, long c, long d, long x, long s, long ac) {

a += F(b, c, d) + x + ac;

a = ((int) a s) | ((int) a (32 - s));

a += b;

return a;

}

private long GG(long a, long b, long c, long d, long x, long s, long ac) {

a += G(b, c, d) + x + ac;

a = ((int) a s) | ((int) a (32 - s));

a += b;

return a;

}

private long HH(long a, long b, long c, long d, long x, long s, long ac) {

a += H(b, c, d) + x + ac;

a = ((int) a s) | ((int) a (32 - s));

a += b;

return a;

}

private long II(long a, long b, long c, long d, long x, long s, long ac) {

a += I(b, c, d) + x + ac;

a = ((int) a s) | ((int) a (32 - s));

a += b;

return a;

}

/*

* keyBeanUpdate是keyBean的主計算過程,inbuf是要變換的字節(jié)串,inputlen是長度,這個

* 函數(shù)由getkeyBeanofStr調(diào)用,調(diào)用之前需要調(diào)用keyBeaninit,因此把它設(shè)計成private的

*/

private void keyBeanUpdate(byte[] inbuf, int inputLen) {

int i, index, partLen;

byte[] block = new byte[64];

index = (int) (count[0] 3) 0x3F;

// /* Update number of bits */

if ((count[0] += (inputLen 3)) (inputLen 3))

count[1]++;

count[1] += (inputLen 29);

partLen = 64 - index;

// Transform as many times as possible.

if (inputLen = partLen) {

keyBeanMemcpy(buffer, inbuf, index, 0, partLen);

keyBeanTransform(buffer);

for (i = partLen; i + 63 inputLen; i += 64) {

keyBeanMemcpy(block, inbuf, 0, i, 64);

keyBeanTransform(block);

}

index = 0;

} else

i = 0;

// /* Buffer remaining input */

keyBeanMemcpy(buffer, inbuf, index, i, inputLen - i);

}

/*

* keyBeanFinal整理和填寫輸出結(jié)果

*/

private void keyBeanFinal() {

byte[] bits = new byte[8];

int index, padLen;

// /* Save number of bits */

Encode(bits, count, 8);

// /* Pad out to 56 mod 64.

index = (int) (count[0] 3) 0x3f;

padLen = (index 56) ? (56 - index) : (120 - index);

keyBeanUpdate(PADDING, padLen);

// /* Append length (before padding) */

keyBeanUpdate(bits, 8);

// /* Store state in digest */

Encode(digest, state, 16);

}

/*

* keyBeanMemcpy是一個內(nèi)部使用的byte數(shù)組的塊拷貝函數(shù),從input的inpos開始把len長度的

* 字節(jié)拷貝到output的outpos位置開始

*/

private void keyBeanMemcpy(byte[] output, byte[] input, int outpos,

int inpos, int len) {

int i;

for (i = 0; i len; i++)

output[outpos + i] = input[inpos + i];

}

/*

* keyBeanTransform是keyBean核心變換程序,有keyBeanUpdate調(diào)用,block是分塊的原始字節(jié)

*/

private void keyBeanTransform(byte block[]) {

long a = state[0], b = state[1], c = state[2], d = state[3];

long[] x = new long[16];

Decode(x, block, 64);

/* Round 1 */

a = FF(a, b, c, d, x[0], S11, 0xd76aa478L); /* 1 */

d = FF(d, a, b, c, x[1], S12, 0xe8c7b756L); /* 2 */

c = FF(c, d, a, b, x[2], S13, 0x242070dbL); /* 3 */

b = FF(b, c, d, a, x[3], S14, 0xc1bdceeeL); /* 4 */

a = FF(a, b, c, d, x[4], S11, 0xf57c0fafL); /* 5 */

d = FF(d, a, b, c, x[5], S12, 0x4787c62aL); /* 6 */

c = FF(c, d, a, b, x[6], S13, 0xa8304613L); /* 7 */

b = FF(b, c, d, a, x[7], S14, 0xfd469501L); /* 8 */

a = FF(a, b, c, d, x[8], S11, 0x698098d8L); /* 9 */

d = FF(d, a, b, c, x[9], S12, 0x8b44f7afL); /* 10 */

c = FF(c, d, a, b, x[10], S13, 0xffff5bb1L); /* 11 */

b = FF(b, c, d, a, x[11], S14, 0x895cd7beL); /* 12 */

a = FF(a, b, c, d, x[12], S11, 0x6b901122L); /* 13 */

d = FF(d, a, b, c, x[13], S12, 0xfd987193L); /* 14 */

c = FF(c, d, a, b, x[14], S13, 0xa679438eL); /* 15 */

b = FF(b, c, d, a, x[15], S14, 0x49b40821L); /* 16 */

/* Round 2 */

a = GG(a, b, c, d, x[1], S21, 0xf61e2562L); /* 17 */

d = GG(d, a, b, c, x[6], S22, 0xc040b340L); /* 18 */

c = GG(c, d, a, b, x[11], S23, 0x265e5a51L); /* 19 */

b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aaL); /* 20 */

a = GG(a, b, c, d, x[5], S21, 0xd62f105dL); /* 21 */

d = GG(d, a, b, c, x[10], S22, 0x2441453L); /* 22 */

c = GG(c, d, a, b, x[15], S23, 0xd8a1e681L); /* 23 */

b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8L); /* 24 */

a = GG(a, b, c, d, x[9], S21, 0x21e1cde6L); /* 25 */

d = GG(d, a, b, c, x[14], S22, 0xc33707d6L); /* 26 */

c = GG(c, d, a, b, x[3], S23, 0xf4d50d87L); /* 27 */

b = GG(b, c, d, a, x[8], S24, 0x455a14edL); /* 28 */

a = GG(a, b, c, d, x[13], S21, 0xa9e3e905L); /* 29 */

d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8L); /* 30 */

c = GG(c, d, a, b, x[7], S23, 0x676f02d9L); /* 31 */

b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8aL); /* 32 */

/* Round 3 */

a = HH(a, b, c, d, x[5], S31, 0xfffa3942L); /* 33 */

d = HH(d, a, b, c, x[8], S32, 0x8771f681L); /* 34 */

c = HH(c, d, a, b, x[11], S33, 0x6d9d6122L); /* 35 */

b = HH(b, c, d, a, x[14], S34, 0xfde5380cL); /* 36 */

a = HH(a, b, c, d, x[1], S31, 0xa4beea44L); /* 37 */

d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9L); /* 38 */

c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60L); /* 39 */

b = HH(b, c, d, a, x[10], S34, 0xbebfbc70L); /* 40 */

a = HH(a, b, c, d, x[13], S31, 0x289b7ec6L); /* 41 */

d = HH(d, a, b, c, x[0], S32, 0xeaa127faL); /* 42 */

c = HH(c, d, a, b, x[3], S33, 0xd4ef3085L); /* 43 */

b = HH(b, c, d, a, x[6], S34, 0x4881d05L); /* 44 */

a = HH(a, b, c, d, x[9], S31, 0xd9d4d039L); /* 45 */

d = HH(d, a, b, c, x[12], S32, 0xe6db99e5L); /* 46 */

c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8L); /* 47 */

b = HH(b, c, d, a, x[2], S34, 0xc4ac5665L); /* 48 */

/* Round 4 */

a = II(a, b, c, d, x[0], S41, 0xf4292244L); /* 49 */

d = II(d, a, b, c, x[7], S42, 0x432aff97L); /* 50 */

c = II(c, d, a, b, x[14], S43, 0xab9423a7L); /* 51 */

b = II(b, c, d, a, x[5], S44, 0xfc93a039L); /* 52 */

a = II(a, b, c, d, x[12], S41, 0x655b59c3L); /* 53 */

d = II(d, a, b, c, x[3], S42, 0x8f0ccc92L); /* 54 */

c = II(c, d, a, b, x[10], S43, 0xffeff47dL); /* 55 */

b = II(b, c, d, a, x[1], S44, 0x85845dd1L); /* 56 */

a = II(a, b, c, d, x[8], S41, 0x6fa87e4fL); /* 57 */

d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0L); /* 58 */

c = II(c, d, a, b, x[6], S43, 0xa3014314L); /* 59 */

b = II(b, c, d, a, x[13], S44, 0x4e0811a1L); /* 60 */

a = II(a, b, c, d, x[4], S41, 0xf7537e82L); /* 61 */

d = II(d, a, b, c, x[11], S42, 0xbd3af235L); /* 62 */

c = II(c, d, a, b, x[2], S43, 0x2ad7d2bbL); /* 63 */

b = II(b, c, d, a, x[9], S44, 0xeb86d391L); /* 64 */

state[0] += a;

state[1] += b;

state[2] += c;

state[3] += d;

}

/*

* Encode把long數(shù)組按順序拆成byte數(shù)組,因為java的long類型是64bit的, 只拆低32bit,以適應(yīng)原始C實現(xiàn)的用途

*/

private void Encode(byte[] output, long[] input, int len) {

int i, j;

for (i = 0, j = 0; j len; i++, j += 4) {

output[j] = (byte) (input[i] 0xffL);

output[j + 1] = (byte) ((input[i] 8) 0xffL);

output[j + 2] = (byte) ((input[i] 16) 0xffL);

output[j + 3] = (byte) ((input[i] 24) 0xffL);

}

}

/*

* Decode把byte數(shù)組按順序合成成long數(shù)組,因為java的long類型是64bit的,

* 只合成低32bit,高32bit清零,以適應(yīng)原始C實現(xiàn)的用途

*/

private void Decode(long[] output, byte[] input, int len) {

int i, j;

for (i = 0, j = 0; j len; i++, j += 4)

output[i] = b2iu(input[j]) | (b2iu(input[j + 1]) 8)

| (b2iu(input[j + 2]) 16) | (b2iu(input[j + 3]) 24);

return;

}

/*

* b2iu是我寫的一個把byte按照不考慮正負號的原則的”升位”程序,因為java沒有unsigned運算

*/

public static long b2iu(byte b) {

return b 0 ? b 0x7F + 128 : b;

}

/*

* byteHEX(),用來把一個byte類型的數(shù)轉(zhuǎn)換成十六進制的ASCII表示,

* 因為java中的byte的toString無法實現(xiàn)這一點,我們又沒有C語言中的 sprintf(outbuf,"%02X",ib)

*/

public static String byteHEX(byte ib) {

char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',

'B', 'C', 'D', 'E', 'F' };

char[] ob = new char[2];

ob[0] = Digit[(ib 4) 0X0F];

ob[1] = Digit[ib 0X0F];

String s = new String(ob);

return s;

}

public static void main(String args[]) {

keyBean m = new keyBean();

if (Array.getLength(args) == 0) { // 如果沒有參數(shù),執(zhí)行標準的Test Suite

System.out.println("keyBean Test suite:");

System.out.println("keyBean(\"):" + m.getkeyBeanofStr(""));

System.out.println("keyBean(\"a\"):" + m.getkeyBeanofStr("a"));

System.out.println("keyBean(\"abc\"):" + m.getkeyBeanofStr("abc"));

System.out.println("keyBean(\"message digest\"):"

+ m.getkeyBeanofStr("message digest"));

System.out.println("keyBean(\"abcdefghijklmnopqrstuvwxyz\"):"

+ m.getkeyBeanofStr("abcdefghijklmnopqrstuvwxyz"));

System.out

.println("keyBean(\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"):"

+ m

.getkeyBeanofStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"));

} else

System.out.println("keyBean(" + args[0] + ")="

+ m.getkeyBeanofStr(args[0]));

}

}

java MD5加密,解釋解釋!

給你解釋一下for里面這段代碼

byte byte0 = md[i];//取得md數(shù)組中第i個元素

str[k++] = hexDigits[byte0 4 0xf ];取得byte0的前四位,然后找到轉(zhuǎn)化成16進制字符,如果byte0為10001000(二進制)那么前四位就是1000,十進制就是8,而 hexDigits[8]就=‘8’

str[k++] = hexDigits[byte0 0xf ]; //同理取得byte0的后四位,轉(zhuǎn)化成16進制字符。

MD5 java

/**

* 采用MD5加密算法,將任意長度字符串加密

*

* @param String

* @return String

* @throws Exception

*/

public static String encryptByMD5(String str) throws Exception{

MessageDigest md = MessageDigest.getInstance("MD5");

byte[] bts = md.digest(str.getBytes());

//采用Base64算法,將加密后的字節(jié)變成字符串

BASE64Encoder encoder = new BASE64Encoder();

return encoder.encode(bts);

}

簡單版的

分享標題:包含md5java代碼及注釋的詞條
地址分享:http://muchs.cn/article18/ddcogdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、網(wǎng)站排名、網(wǎng)站導(dǎo)航、微信小程序移動網(wǎng)站建設(shè)、

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)