# 消息摘要算法--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");
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

运行结果:

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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# MAC-应用

message-authentication-code