Java MD5/SHA/MAC消息摘要算法

消息摘要算法

MD(Message Digest)

SHA(Secure Hash Algorithm)

MAC(Message Authentication Code)

其他如:RipeMD, Tiger, Whirlpool, GOST3411等,均由Bouncy Castle實現。

消息摘要算法–MD(Message Digest)

作用:驗證數據的完整性

是數字簽名核心算法

MD5

MD家族(128位摘要信息)-MD2,MD4

算法 摘要長度 實現方法
MD2 128 JDK
MD4 128 Bouncy Castle
MD5 128 JDK

代碼實現

package md.test;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD2Digest;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * Message Digest
 * @author Capricorncd
 * https://github.com/capricorncd
 *
 */
public class TestMessageDigest {

	private static final String MD2 = "MD2";
	private static final String MD4 = "MD4";
	private static final String MD5 = "MD5";

	public static void main(String[] args) {
		String src = "I love the world.";

		jdkMD(src, MD2);
		jdkMD(src, MD4);
		jdkMD(src, MD5);

		bcMD(src, MD2, new MD2Digest());
		bcMD(src, MD4, new MD4Digest());
		bcMD(src, MD5, new MD5Digest());

		bouncyCastleMD(src, MD2);
		bouncyCastleMD(src, MD4);
		bouncyCastleMD(src, MD5);

		ccMD(src, MD2);
		ccMD(src, MD4);
		ccMD(src, MD5);
	}

	/**
	 * JDK MD
	 * @param src source
	 * @param mdType MD2,MD5
	 * @return String result
	 */
	public static String jdkMD(String src, String mdType) {
		String result = null;
		try {
			MessageDigest md = MessageDigest.getInstance(mdType);
			byte[] mdBytes = md.digest(src.getBytes());
			// toHex
			result = Hex.encodeHexString(mdBytes);
		} catch (NoSuchAlgorithmException e) {
			// e.printStackTrace();
			result = e.getMessage();
		}
		println(mdType + ":", result, "by JDK");
		return result;
	}

	/**
	 * bouncy castle MD
	 * @param src source
	 * @param mdType message digest type
	 * @param digest org.bouncycastle.crypto.Digest
	 * @return String result
	 */
	public static<T extends Digest> String bcMD(String src, String mdType, T digest) {
		byte[] srcBytes = src.getBytes();
		digest.update(srcBytes, 0, srcBytes.length);
		byte[] resBytes = new byte[digest.getDigestSize()];
		digest.doFinal(resBytes, 0);
		String result = org.bouncycastle.util.encoders.Hex.toHexString(resBytes);
		println(mdType + ":", result, "by Bouncycastle");
		return result;
	}

	/**
	 * bouncy castle provider MD
	 * @param src source
	 * @param mdType message digest type
	 * @return String result
	 */
	public static String bouncyCastleMD(String src, String mdType) {
		String result = null;
		Security.addProvider(new BouncyCastleProvider());
		try {
			MessageDigest md = MessageDigest.getInstance(mdType);
			byte[] mdBytes = md.digest(src.getBytes());
			result = Hex.encodeHexString(mdBytes);
		} catch (NoSuchAlgorithmException e) {
			// e.printStackTrace();
			result = e.getMessage();
		}
		println(mdType + ":", result, "by BouncyCastleProvider");
		return result;
	}

	/**
	 * org.apache.commons.codec.digest.DigestUtils
	 * @param src source
	 * @param mdType message digest type
	 * @return String result
	 */
	public static String ccMD(String src, String mdType) {
		String result = null;
		switch(mdType) {
		case MD2:
			result = DigestUtils.md2Hex(src.getBytes());
			break;
		case MD4:
			result = "The MD4 method is not implemented.";
			break;
		case MD5:
			result = DigestUtils.md5Hex(src.getBytes());
			break;
		}
		println(mdType + ":", result, "by org.apache.commons.codec.digest.DigestUtils");
		return result;
	}

	/**
	 * System.out.println
	 * @param args
	 */
	public static void println(Object ...args) {
		for (Object o : args) {
			System.out.print(o + " ");
		}		
		System.out.print("\n");
	}
}

運行結果:

MD2: b749ef6943db8fa96fa688a1077224a3 by JDK
MD4: MD4 MessageDigest not available by JDK
MD5: 2947f614c460347649185e62ee914eac by JDK
MD2: b749ef6943db8fa96fa688a1077224a3 by Bouncycastle
MD4: 9df4c1b595403939d490ad7c66cf7710 by Bouncycastle
MD5: 2947f614c460347649185e62ee914eac by Bouncycastle
MD2: b749ef6943db8fa96fa688a1077224a3 by BouncyCastleProvider
MD4: 9df4c1b595403939d490ad7c66cf7710 by BouncyCastleProvider
MD5: 2947f614c460347649185e62ee914eac by BouncyCastleProvider
MD2: b749ef6943db8fa96fa688a1077224a3 by org.apache.commons.codec.digest.DigestUtils
MD4: The MD4 method is not implemented. by org.apache.commons.codec.digest.DigestUtils
MD5: 2947f614c460347649185e62ee914eac by org.apache.commons.codec.digest.DigestUtils

消息摘要算法–應用

註冊、登錄密碼處理

消息摘要算法–SHA

SHA(Secure Hash Algorithm) 安全散列算法的簡稱。

固定長度摘要信息

SHA-1, SHA-2(SHA-224, SHA-256, SHA-384, SHA-512)

算法 摘要長度 實現方法
SHA-1 160 JDK
SHA-224 224 Bouncy Castle/JDK1.8
SHA-256 256 JDK
SHA-384 384 JDK
SHA-512 512 JDK

代碼實現

package md.test;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;

/**
 * Secure Hash Algorithm
 * @author Capricorncd
 * https://github.com/capricorncd
 */
public class TestSHA {

	private static final String SHA = "SHA";
	private static final String SHA_224 = "SHA-224";
	private static final String SHA_256 = "SHA-256";
	private static final String SHA_384 = "SHA-384";
	private static final String SHA_512 = "SHA-512";

	public static void main(String[] args) {
		String src = "Test Secure Hash Algorithm.";
		// JDK
		jdkSHA(src, SHA);
		jdkSHA(src, SHA_224);
		jdkSHA(src, SHA_256);
		jdkSHA(src, SHA_384);
		jdkSHA(src, SHA_512);
		// Bouncy Castle
		println("");
		bcSHA(src, SHA, new SHA1Digest());
		bcSHA(src, SHA_224, new SHA224Digest());
		bcSHA(src, SHA_256, new SHA256Digest());
		bcSHA(src, SHA_384, new SHA384Digest());
		bcSHA(src, SHA_512, new SHA512Digest());
		// org.apache.commons.codec.digest.DigestUtils
		println("");
		ccSHA(src, SHA);
		ccSHA(src, SHA_224);
		ccSHA(src, SHA_256);
		ccSHA(src, SHA_384);
		ccSHA(src, SHA_512);
	}

	/**
	 * JDK SHA
	 * @param src source
	 * @param algorithm algorithm type
	 */
	public static void jdkSHA(String src, String algorithm) {
		String result = null;
		try {
			MessageDigest md = MessageDigest.getInstance(algorithm);
			byte[] mdBytes = md.digest(src.getBytes());
			result = Hex.encodeHexString(mdBytes);
		} catch (NoSuchAlgorithmException e) {
			// e.printStackTrace();
			result = e.getMessage();
		}
		println(algorithm + ":", result, "by JDK");
	}

	/**
	 * Bouncy Castle SHA
	 * @param <T> Digest
	 * @param src source
	 * @param algorithm
	 * @param digest Digest
	 */
	public static<T extends Digest> void bcSHA(String src, String algorithm, T digest) {
		// input bytes
		byte[] srcBytes = src.getBytes();
		digest.update(srcBytes, 0, srcBytes.length);
		// result bytes
		byte[] resBytes = new byte[digest.getDigestSize()];
		digest.doFinal(resBytes, 0);
		// to Hex
		String result = org.bouncycastle.util.encoders.Hex.toHexString(resBytes);
		println(algorithm + ":", result, "by Bouncy Castle");
	}

	/**
	 * org.apache.commons.codec.digest.DigestUtils
	 * @param src
	 * @param algorithm
	 */
	public static void ccSHA(String src, String algorithm) {
		String result = null;
		try {
			switch(algorithm) {
			case SHA:
				result = DigestUtils.sha1Hex(src);
				break;
			case SHA_224:
				result = DigestUtils.sha3_224Hex(src);
				break;
			case SHA_256:
				result = DigestUtils.sha256Hex(src);
				break;
			case SHA_384:
				result = DigestUtils.sha384Hex(src);
				break;
			case SHA_512:
				result = DigestUtils.sha512Hex(src);
				break;
			}
		} catch (Exception e) {
			result = e.getMessage();
		}
		println(algorithm + ":", result, "by org.apache.commons.codec.digest.DigestUtils");
	}

	/**
	 * System.out.println
	 * @param args
	 */
	public static void println(Object ...args) {
		for (Object o : args) {
			System.out.print(o + " ");
		}		
		System.out.print("\n");
	}
}

運行結果:

SHA: 1ec4fe70c8223dbf362dd02481d2abe032aeaa23 by JDK
SHA-224: 7ce9d2ecd24444271fd823c8ded2931fa35ae70c747350004bce6291 by JDK
SHA-256: fc0de412e726341a95ae30b8ede3dfbb502fa50f9532439e45ca86cdfa725489 by JDK
SHA-384: 75cd6f06373ff58d7f50d02a68116108d1c56761e401f20dda6a3fa863b477bb2ce2030d8c760bf9da228d4623262273 by JDK
SHA-512: 9e9b3e31616ac90d2ec9981a2ba05c2045af58af9c279aa5d9fc45248982fe4eafaeccc12270310c2819b5b8b7541f5d9ba884bfac1b3c3fdfe8c42adb283643 by JDK

SHA: 1ec4fe70c8223dbf362dd02481d2abe032aeaa23 by Bouncy Castle
SHA-224: 7ce9d2ecd24444271fd823c8ded2931fa35ae70c747350004bce6291 by Bouncy Castle
SHA-256: fc0de412e726341a95ae30b8ede3dfbb502fa50f9532439e45ca86cdfa725489 by Bouncy Castle
SHA-384: 75cd6f06373ff58d7f50d02a68116108d1c56761e401f20dda6a3fa863b477bb2ce2030d8c760bf9da228d4623262273 by Bouncy Castle
SHA-512: 9e9b3e31616ac90d2ec9981a2ba05c2045af58af9c279aa5d9fc45248982fe4eafaeccc12270310c2819b5b8b7541f5d9ba884bfac1b3c3fdfe8c42adb283643 by Bouncy Castle

SHA: 1ec4fe70c8223dbf362dd02481d2abe032aeaa23 by org.apache.commons.codec.digest.DigestUtils
SHA-224: java.security.NoSuchAlgorithmException: SHA3-224 MessageDigest not available by org.apache.commons.codec.digest.DigestUtils
SHA-256: fc0de412e726341a95ae30b8ede3dfbb502fa50f9532439e45ca86cdfa725489 by org.apache.commons.codec.digest.DigestUtils
SHA-384: 75cd6f06373ff58d7f50d02a68116108d1c56761e401f20dda6a3fa863b477bb2ce2030d8c760bf9da228d4623262273 by org.apache.commons.codec.digest.DigestUtils
SHA-512: 9e9b3e31616ac90d2ec9981a2ba05c2045af58af9c279aa5d9fc45248982fe4eafaeccc12270310c2819b5b8b7541f5d9ba884bfac1b3c3fdfe8c42adb283643 by org.apache.commons.codec.digest.DigestUtils

SHA-應用

加入約定key,增加時間戳,排序

https://*?msg=f58d7f50d02a...16&timestamp=1590324555411
msg: 原始消息+key+時間戳

消息摘要算法–MAC

MAC(Message Authentication Code)

HMAC(keyed-Hash Message Authentication Code),含有密鑰的散列函數算法

融合MD、SHA

  • MD系列:HmacMD2、HmacMD4、HmacMD5

  • SHA系列:HmacSHA1、HmacSHA224、HmacSHA256、HmacSHA384、HmacSHA512

應用:SecureCRT

算法 摘要長度 實現方法
HmacMD2 128 Bouncy Castle
HmacMD4 128 Bouncy Castle
HmacMD5 128 JDK
HmacSHA1 160 JDK
HmacSHA224 224 Bouncy Castle/JDK1.8
HmacSHA256 256 JDK
HmacSHA384 384 JDK
HmacSHA512 512 JDK

代碼實現

package md.test;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD2Digest;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

/**
 * keyed-Hash Message Authentication Code
 * @author Capricorncd
 * https://github.com/capricorncd
 */
public class TestMAC {

	private static final String HMAC_MD2 = "HmacMD2";
	private static final String HMAC_MD4 = "HmacMD4";
	private static final String HMAC_MD5 = "HmacMD5";

	private static final String HMAC_SHA = "HmacSHA1";
	private static final String HMAC_SHA_224 = "HmacSHA224";
	private static final String HMAC_SHA_256 = "HmacSHA256";
	private static final String HMAC_SHA_384 = "HmacSHA384";
	private static final String HMAC_SHA_512 = "HmacSHA512";

	public static void main(String[] args) {
		String src = "keyed-Hash Message Authentication Code";
		// secret key, length = 10.
		String secretKey = "aaaaaaaaaa";
		byte[] secretKeyBytes = org.bouncycastle.util.encoders.Hex.decode(secretKey);

		jdkHmac(src, HMAC_MD2, secretKeyBytes);
		jdkHmac(src, HMAC_MD4, secretKeyBytes);
		jdkHmac(src, HMAC_MD5, secretKeyBytes);

		println();
		bcHmac(src, HMAC_MD2, new MD2Digest(), secretKeyBytes);
		bcHmac(src, HMAC_MD4, new MD4Digest(), secretKeyBytes);
		bcHmac(src, HMAC_MD5, new MD5Digest(), secretKeyBytes);

		println();
		jdkHmac(src, HMAC_SHA, secretKeyBytes);
		jdkHmac(src, HMAC_SHA_224, secretKeyBytes);
		jdkHmac(src, HMAC_SHA_256, secretKeyBytes);
		jdkHmac(src, HMAC_SHA_384, secretKeyBytes);
		jdkHmac(src, HMAC_SHA_512, secretKeyBytes);

		println();
		bcHmac(src, HMAC_SHA, new SHA1Digest(), secretKeyBytes);
		bcHmac(src, HMAC_SHA_224, new SHA224Digest(), secretKeyBytes);
		bcHmac(src, HMAC_SHA_256, new SHA256Digest(), secretKeyBytes);
		bcHmac(src, HMAC_SHA_384, new SHA384Digest(), secretKeyBytes);
		bcHmac(src, HMAC_SHA_512, new SHA512Digest(), secretKeyBytes);
	}

	/**
	 * JDK HMAC
	 * @param src source
	 * @param algorithm
	 * @param secretKeyBytes secret key bytes
	 */
	public static void jdkHmac(String src, String algorithm, byte[] secretKeyBytes) {
		String result = null;
		try {
			// restore secret key
			SecretKey restoreSecretKey = new SecretKeySpec(secretKeyBytes, algorithm);
			// instance MAC
			Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm());
			// initial MAC
			mac.init(restoreSecretKey);
			// run
			byte[] resultBytes = mac.doFinal(src.getBytes());
			result = Hex.encodeHexString(resultBytes);
		} catch (Exception e) {
			// e.printStackTrace();
			result = e.getMessage();
		}
		println(algorithm + ":", result, "by JDK");
	}

	/**
	 * JDK HMAC
	 * Automatically generate a secret key
	 * @param src
	 * @param algorithm
	 */
	public static void jdkHmac(String src, String algorithm) {
		try {
			// Automatically generate a secret key
			// initial KeyGenerator
			KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
			// create secret key
			SecretKey secretKey = keyGenerator.generateKey();
			// get secret key
			byte[] secretKeyBytes = secretKey.getEncoded();

			jdkHmac(src, algorithm, secretKeyBytes);
		} catch (Exception e) {
			// e.printStackTrace();
			println(algorithm + ":", e.getMessage(), "by JDK");
		}

	}

	/**
	 * bouncy castle HMAC
	 * @param <T> Digest
	 * @param src source
	 * @param algorithm
	 * @param digest Digest
	 * @param secretKeyBytes secret key bytes
	 */
	public static <T extends Digest> void bcHmac(String src, String algorithm, T digest, byte[] secretKeyBytes) {
		HMac hmac = new HMac(digest);
		// byte[] secretKeyBytes = org.bouncycastle.util.encoders.Hex.decode("aaaaaaaaaa");
		hmac.init(new KeyParameter(secretKeyBytes));

		byte[] srcBytes = src.getBytes();
		hmac.update(srcBytes, 0, srcBytes.length);

		byte[] resultBytes = new byte[hmac.getMacSize()];
		hmac.doFinal(resultBytes, 0);

		String result = org.bouncycastle.util.encoders.Hex.toHexString(resultBytes);
		println(algorithm + ":", result, "by Bouncy Castle.");
	}

	/**
	 * System.out.println
	 *
	 * @param args
	 */
	public static void println(Object... args) {
		for (Object o : args) {
			System.out.print(o + " ");
		}
		System.out.print("\n");
	}
}

運行結果:

HmacMD2: Algorithm HmacMD2 not available by JDK
HmacMD4: Algorithm HmacMD4 not available by JDK
HmacMD5: 60abad09ecbc7f234c3066b76209d657 by JDK

HmacMD2: cc2e396c39d58f3d6415eebfbf928744 by Bouncy Castle.
HmacMD4: 199828516cc1f41baa9536e095e73483 by Bouncy Castle.
HmacMD5: 60abad09ecbc7f234c3066b76209d657 by Bouncy Castle.

HmacSHA1: ee77ed44862c69ff1b93d81a2cab40b714aeac39 by JDK
HmacSHA224: 261be450a5b2f6e9dad0df89e14710c4a412ef89d4c9b8db76173c19 by JDK
HmacSHA256: a6c974f0b1025844d8266e3ab8f0402c8467c5878dcd9982216c46b6fd90d067 by JDK
HmacSHA384: 43a6703c1fa097ec80a1aec85b6f38eef34059c3b90dddce27c7fde3d5e7d716050a86aa09275b52c9378eb819774a32 by JDK
HmacSHA512: da98cf562dfaa094624ee28464dd0c4e0ade2a07fc28bb5b5aadeb0cef59e43ec9a3eeef51cf33a6e30c1611e1dc912fac3f1108db15a72e390e47579e4dad23 by JDK

HmacSHA1: ee77ed44862c69ff1b93d81a2cab40b714aeac39 by Bouncy Castle.
HmacSHA224: 261be450a5b2f6e9dad0df89e14710c4a412ef89d4c9b8db76173c19 by Bouncy Castle.
HmacSHA256: a6c974f0b1025844d8266e3ab8f0402c8467c5878dcd9982216c46b6fd90d067 by Bouncy Castle.
HmacSHA384: 43a6703c1fa097ec80a1aec85b6f38eef34059c3b90dddce27c7fde3d5e7d716050a86aa09275b52c9378eb819774a32 by Bouncy Castle.
HmacSHA512: da98cf562dfaa094624ee28464dd0c4e0ade2a07fc28bb5b5aadeb0cef59e43ec9a3eeef51cf33a6e30c1611e1dc912fac3f1108db15a72e390e47579e4dad23 by Bouncy Castle.

from 慕課網

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