欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-19 13:31:40
...

消息摘要算法

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 慕课网