java 版MD5通用算法, 原始密鑰沒有修改.

java 版MD5通用算法, 原始密鑰沒有修改, 加密後的值與網上其它通用算法完全一樣.

測試main在代碼最後面, 隨送一些加密的對照數據, 方便覈對算法的正確性.

package com.test;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

/**
 * 國際通用MD5算法<br>
 * 原始通用密鑰參數(注意不要改動此參數)<br>
 * state[0] = 0x67452301;<br> 
 * state[1] = 0xefcdab89;<br>
 * state[2] = 0x98badcfe;<br>
 * state[3] = 0x10325476;<br>
 * 加密樣本:<br>
 * MD5 ("") = d41d8cd98f00b204e9800998ecf8427e<br>
 * MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661<br>
 * MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72<br>
 * MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0<br>
 * MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b<br>
 * MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =d174ab98d277d9f5a5611c2c9f419d9f	<br>
 * MD5 ("中文") = a7bac2239fcdcb3a067903d8077c4a07<br>
 * @author guishuanglin 2006-11-3
 */
public class Md5 {
	private static final int BUFFER_SIZE = 1024;

	private static final int S11 = 7;
	private static final int S12 = 12;
	private static final int S13 = 17;
	private static final int S14 = 22;
	private static final int S21 = 5;
	private static final int S22 = 9;
	private static final int S23 = 14;
	private static final int S24 = 20;
	private static final int S31 = 4;
	private static final int S32 = 11;
	private static final int S33 = 16;
	private static final int S34 = 23;
	private static final int S41 = 6;
	private static final int S42 = 10;
	private static final int S43 = 15;
	private static final int S44 = 21;

	private static byte padding[] = { (byte) 0x80, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
			(byte) 0 };

	private InputStream in = null;
	private boolean stringp = false;
	private int state[] = null;
	private long count = 0;
	private byte buffer[] = null;
	private byte digest[] = null;

	private static String stringify(byte buf[]) {
		StringBuffer sb = new StringBuffer(2 * buf.length);
		for (int i = 0; i < buf.length; i++) {
			int h = (buf[i] & 0xf0) >> 4;
			int l = (buf[i] & 0x0f);
			sb.append(new Character((char) ((h > 9) ? 'a' + h - 10 : '0' + h)));
			sb.append(new Character((char) ((l > 9) ? 'a' + l - 10 : '0' + l)));
		}
		return sb.toString();
	}

	private final int F(int x, int y, int z) {
		return ((x & y) | ((~x) & z));
	}

	private final int G(int x, int y, int z) {
		return ((x & z) | (y & (~z)));
	}

	private final int H(int x, int y, int z) {
		return (x ^ y ^ z);
	}

	private final int I(int x, int y, int z) {
		return (y ^ (x | (~z)));
	}

	private final int rotate_left(int x, int n) {
		return ((x << n) | (x >>> (32 - n)));
	}

	private final int FF(int a, int b, int c, int d, int x, int s, int ac) {
		a += (F(b, c, d) + x + ac);
		a = rotate_left(a, s);
		a += b;
		return a;
	}

	private final int GG(int a, int b, int c, int d, int x, int s, int ac) {
		a += (G(b, c, d) + x + ac);
		a = rotate_left(a, s);
		a += b;
		return a;
	}

	private final int HH(int a, int b, int c, int d, int x, int s, int ac) {
		a += (H(b, c, d) + x + ac);
		a = rotate_left(a, s);
		a += b;
		return a;
	}

	private final int II(int a, int b, int c, int d, int x, int s, int ac) {
		a += (I(b, c, d) + x + ac);
		a = rotate_left(a, s);
		a += b;
		return a;
	}

	private final void decode(int output[], byte input[], int off, int len) {
		int i = 0;
		int j = 0;
		for (; j < len; i++, j += 4) {
			output[i] = (((int) (input[off + j] & 0xff))
					| (((int) (input[off + j + 1] & 0xff)) << 8)
					| (((int) (input[off + j + 2] & 0xff)) << 16) | (((int) (input[off
					+ j + 3] & 0xff)) << 24));
		}
	}

	private final void transform(byte block[], int offset) {
		int a = state[0];
		int b = state[1];
		int c = state[2];
		int d = state[3];
		int x[] = new int[16];

		decode(x, block, offset, 64);
		/* Round 1 */
		a = FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
		d = FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
		c = FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
		b = FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
		a = FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
		d = FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
		c = FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
		b = FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
		a = FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
		d = FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
		c = FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
		b = FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
		a = FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
		d = FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
		c = FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
		b = FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
		/* Round 2 */
		a = GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
		d = GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
		c = GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
		b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
		a = GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
		d = GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
		c = GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
		b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
		a = GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
		d = GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
		c = GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
		b = GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
		a = GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
		d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
		c = GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
		b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */

		/* Round 3 */
		a = HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
		d = HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
		c = HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
		b = HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
		a = HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
		d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
		c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
		b = HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
		a = HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
		d = HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
		c = HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
		b = HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
		a = HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
		d = HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
		c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
		b = HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */

		/* Round 4 */
		a = II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
		d = II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
		c = II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
		b = II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
		a = II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
		d = II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
		c = II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
		b = II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
		a = II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
		d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
		c = II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
		b = II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
		a = II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
		d = II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
		c = II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
		b = II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */

		state[0] += a;
		state[1] += b;
		state[2] += c;
		state[3] += d;
	}

	private final void update(byte input[], int len) {
		int index = ((int) (count >> 3)) & 0x3f;
		count += (len << 3);
		int partLen = 64 - index;
		int i = 0;
		if (len >= partLen) {
			System.arraycopy(input, 0, buffer, index, partLen);
			transform(buffer, 0);
			for (i = partLen; i + 63 < len; i += 64)
				transform(input, i);
			index = 0;
		} else {
			i = 0;
		}
		System.arraycopy(input, i, buffer, index, len - i);
	}

	private byte[] end() {
		byte bits[] = new byte[8];
		for (int i = 0; i < 8; i++)
			bits[i] = (byte) ((count >>> (i * 8)) & 0xff);
		int index = ((int) (count >> 3)) & 0x3f;
		int padlen = (index < 56) ? (56 - index) : (120 - index);
		update(padding, padlen);
		update(bits, 8);
		return encode(state, 16);
	}

	// Encode the content.state array into 16 bytes array
	private byte[] encode(int input[], int len) {
		byte output[] = new byte[len];
		int i = 0;
		int j = 0;
		for (; j < len; i++, j += 4) {
			output[j] = (byte) ((input[i]) & 0xff);
			output[j + 1] = (byte) ((input[i] >> 8) & 0xff);
			output[j + 2] = (byte) ((input[i] >> 16) & 0xff);
			output[j + 3] = (byte) ((input[i] >> 24) & 0xff);
		}
		return output;
	}

	/**
	 * Get the digest for our input stream. This method constructs the input
	 * stream digest, and return it, as a a String, following the MD5 (rfc1321)
	 * algorithm,
	 * 
	 * @return An instance of String, giving the message digest.
	 * @exception IOException
	 *                Thrown if the digestifier was unable to read the input
	 *                stream.
	 */

	public byte[] getDigest() throws IOException {
		byte buffer[] = new byte[BUFFER_SIZE];
		int got = -1;

		if (digest != null)
			return digest;
		while ((got = in.read(buffer)) > 0)
			update(buffer, got);
		this.digest = end();
		return digest;
	}

	/**
	 * Get the digest, for this string digestifier. This method doesn't throw
	 * any IOException, since it knows that the underlying stream ws built from
	 * a String.
	 */

	public byte[] processString() {
		if (!stringp)
			throw new RuntimeException(this.getClass().getName()
					+ "[processString]" + " not a string.");
		try {
			return getDigest();
		} catch (IOException ex) {
		}
		throw new RuntimeException(this.getClass().getName()
				+ "[processString]" + ": implementation error.");
	}

	/**
	 * Get the digest, as a proper string.
	 */

	public String getStringDigest() {
		if (digest == null)
			throw new RuntimeException(this.getClass().getName()
					+ "[getStringDigest]" + ": called before processing.");
		return stringify(digest);
	}

	/**
	 * Construct a digestifier for the given string.
	 * 
	 * @param input
	 *            The string to be digestified.
	 * @param encoding
	 *            the encoding name used (such as UTF8)
	 */

	public Md5(String input, String enc) {
		this.init();
		byte bytes[] = null;
		try {
			bytes = input.getBytes(enc);
			this.in = new ByteArrayInputStream(bytes);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("no " + enc + " encoding!!!");
		}
	}

	/**
	 * Construct a digestifier for the given string.
	 * 
	 * @param input
	 *            The string to be digestified.
	 */

	public Md5(String input) {
		this(input, "UTF-8");
	}

	/**
	 * Construct a digestifier for the given input stream.
	 * 
	 * @param in
	 *            The input stream to be digestified.
	 */

	public Md5(InputStream input) {
		this.init();
		this.in = input;
	}
	
	public Md5(byte[] input) {
		this.init();
		this.in = new ByteArrayInputStream(input);
	}
	public Md5() {
	}

	/**
	 * 獲取經過MD5加密的字符串 <br>
	 * 2006-12-16 [email protected] <br>
	 * 會產生
	 * UnsupportedEncodingException <br>
	 * IOException
	 * @date 2008-12-4
	 * @param input,需要獲取MD5的源字符串.
	 * @param enc,默認語言編碼爲 "UTF-8"編碼.
	 * @return
	 */
	public String getMd5(String input) {
		return this.getMd5(input, "UTF-8");
	}
	
	/**
	 * 獲取經過MD5加密的字符串 <br>
	 * 2006-12-16 [email protected] <br>
	 * 會產生
	 * UnsupportedEncodingException <br>
	 * IOException
	 * @date 2008-12-4
	 * @param input,需要獲取MD5的源字符串.
	 * @param enc,編碼方式
	 * @return
	 */
	public String getMd5(String input, String enc) {
		this.init();
		byte bytes[] = null;
		try {
			bytes = input.getBytes(enc);
			this.in = new ByteArrayInputStream(bytes);
			this.getDigest();
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("no " + enc + " encoding!!!");
		}catch (IOException e) {
			e.printStackTrace();
		}
		return this.getStringDigest();
	}
	/**
	 * 會產生
	 * UnsupportedEncodingException
	 * IOException
	 * @date 2008-12-4
	 * @param input
	 * @param enc
	 * @return
	 */
	public String getMd5(InputStream input) {
		this.init();
		this.in =input;
		try {
			this.getDigest();
		}catch (IOException e) {
			e.printStackTrace();
		}
		return this.getStringDigest();
	}
	/**
	 * 會產生
	 * UnsupportedEncodingException
	 * IOException
	 * @date 2008-12-4
	 * @param input
	 * @param enc
	 * @return
	 */
	public String getMd5(byte[] input) {
		this.init();
		try {
			this.in = new ByteArrayInputStream(input);
			this.getDigest();
		}catch (IOException e) {
			e.printStackTrace();
		}
		return this.getStringDigest();
	}

	/**
	 * 獲取密鑰參數
	 * @date 2008-12-4
	 * @return
	 */
	public int[] getState() {
		return state;
	}
	/**
	 * 設置密鑰參數
	 * @date 2008-12-4
	 * @param state int[4]
	 */
	public void setState(int[] state) {
		if(state==null && state.length!=4){
			throw new RuntimeException("state length int[4]");
		}
		this.state = state;
	}
	
	/**
	 * 初始化參數
	 * @date 2008-12-4
	 */
	private void init() {
		//初始變量
		this.in = null;
		this.digest = null;
		this.stringp = true;
		this.state = new int[4];
		this.buffer = new byte[64];
		this.count = 0;

		// 原始通用密鑰參數(嚴禁改動此參數)
		if (this.digest == null) {
			state[0] = 0x67452301;
			state[1] = 0xefcdab89;
			state[2] = 0x98badcfe;
			state[3] = 0x10325476;
		}
		
		// 密鑰參數 ,可自己定義參數
		//state[0] = 0x45672301;
		//state[1] = 0xEFCDAB89;
		//state[2] = 0x98BADCFE;
		//state[3] = 0x10325476;
	}
	
	public static void main(String args[]) throws IOException {
		Md5 md5 = new Md5();
		System.out.println(md5.getMd5("1111"));
		if (args.length != 1) {
			System.out.println("not Md5 <file name>");
			System.exit(1);
		}
		//Md5 md5 = new Md5(new FileInputStream(new File(args[0])));
		//byte b[] = md5.getDigest();
		//System.out.println(stringify(b));
//		Md5 md5 = new Md5();
//		System.out.println(md5.getMd5("中文"));
	}
}

不可逆加密算法 md5的用途

1, 雖然md5已破解了, 但是在混合其它加密算法時, 還是很有用的. 常用做把庫中用戶密碼保存爲md5碼, 在登錄時校驗正確性.

2, 對整個文件加密, 常見的下載文件, 如果下載的文件不一樣, md5的值就不一樣, 說明不是原始文檔.

3, 公司重要的公開書信, 通知文件, 郵件加密, 可以通過微信, 短信通知md5密碼, 當接收者拿到公開文件之後, 校驗MD5值, 可以得知此通知文件是否有人中途篡改, 導致你拿到不是總部原始文件.

5, 覈對第三方推送的信息是否變化, 第三方公司可能每次都把全部信息給你, 比如所有用戶信息, 但是你不知道某條記錄修改過,

如果你每次接收信息時(字段拼接成String串再用md5計算密碼), 保存前一次的md5碼, 等下一次來信息時就比較md5碼, 就知道是否改動過.更新過.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章