0
|
1
|
|
2 package com.trilead.ssh2.crypto.digest;
|
|
3
|
|
4 import java.security.InvalidKeyException;
|
|
5 import java.security.NoSuchAlgorithmException;
|
|
6
|
|
7 import javax.crypto.Mac;
|
|
8 import javax.crypto.ShortBufferException;
|
|
9 import javax.crypto.spec.SecretKeySpec;
|
|
10
|
|
11 /**
|
|
12 * MAC.
|
|
13 *
|
|
14 * @author Christian Plattner, plattner@trilead.com
|
|
15 * @version $Id: MAC.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $
|
|
16 */
|
|
17 public final class MAC {
|
|
18 /**
|
|
19 * From http://tools.ietf.org/html/rfc4253
|
|
20 */
|
|
21 private static final String HMAC_MD5 = "hmac-md5";
|
|
22
|
|
23 /**
|
|
24 * From http://tools.ietf.org/html/rfc4253
|
|
25 */
|
|
26 private static final String HMAC_MD5_96 = "hmac-md5-96";
|
|
27
|
|
28 /**
|
|
29 * From http://tools.ietf.org/html/rfc4253
|
|
30 */
|
|
31 private static final String HMAC_SHA1 = "hmac-sha1";
|
|
32
|
|
33 /**
|
|
34 * From http://tools.ietf.org/html/rfc4253
|
|
35 */
|
|
36 private static final String HMAC_SHA1_96 = "hmac-sha1-96";
|
|
37
|
|
38 /**
|
|
39 * From http://tools.ietf.org/html/rfc6668
|
|
40 */
|
|
41 private static final String HMAC_SHA2_256 = "hmac-sha2-256";
|
|
42
|
|
43 /**
|
|
44 * From http://tools.ietf.org/html/rfc6668
|
|
45 */
|
|
46 private static final String HMAC_SHA2_512 = "hmac-sha2-512";
|
|
47
|
|
48 Mac mac;
|
|
49 int outSize;
|
|
50 int macSize;
|
|
51 byte[] buffer;
|
|
52
|
|
53 /* Higher Priority First */
|
|
54 private static final String[] MAC_LIST = {
|
|
55 HMAC_SHA2_256, HMAC_SHA2_512,
|
|
56 HMAC_SHA1_96, HMAC_SHA1, HMAC_MD5_96, HMAC_MD5
|
|
57 };
|
|
58
|
|
59 public final static String[] getMacList() {
|
|
60 return MAC_LIST;
|
|
61 }
|
|
62
|
|
63 public final static void checkMacList(String[] macs) {
|
|
64 for (int i = 0; i < macs.length; i++)
|
|
65 getKeyLen(macs[i]);
|
|
66 }
|
|
67
|
|
68 public final static int getKeyLen(String type) {
|
|
69 if (HMAC_SHA1.equals(type) || HMAC_SHA1_96.equals(type))
|
|
70 return 20;
|
|
71
|
|
72 if (HMAC_MD5.equals(type) || HMAC_MD5_96.equals(type))
|
|
73 return 16;
|
|
74
|
|
75 if (HMAC_SHA2_256.equals(type))
|
|
76 return 32;
|
|
77
|
|
78 if (HMAC_SHA2_512.equals(type))
|
|
79 return 64;
|
|
80
|
|
81 throw new IllegalArgumentException("Unkown algorithm " + type);
|
|
82 }
|
|
83
|
|
84 public MAC(String type, byte[] key) {
|
|
85 try {
|
|
86 if (HMAC_SHA1.equals(type) || HMAC_SHA1_96.equals(type)) {
|
|
87 mac = Mac.getInstance("HmacSHA1");
|
|
88 }
|
|
89 else if (HMAC_MD5.equals(type) || HMAC_MD5_96.equals(type)) {
|
|
90 mac = Mac.getInstance("HmacMD5");
|
|
91 }
|
|
92 else if (HMAC_SHA2_256.equals(type)) {
|
|
93 mac = Mac.getInstance("HmacSHA256");
|
|
94 }
|
|
95 else if (HMAC_SHA2_512.equals(type)) {
|
|
96 mac = Mac.getInstance("HmacSHA512");
|
|
97 }
|
|
98 else
|
|
99 throw new IllegalArgumentException("Unkown algorithm " + type);
|
|
100 }
|
|
101 catch (NoSuchAlgorithmException e) {
|
|
102 throw new IllegalArgumentException("Unknown algorithm " + type, e);
|
|
103 }
|
|
104
|
|
105 macSize = mac.getMacLength();
|
|
106
|
|
107 if (type.endsWith("-96")) {
|
|
108 outSize = 12;
|
|
109 buffer = new byte[macSize];
|
|
110 }
|
|
111 else {
|
|
112 outSize = macSize;
|
|
113 buffer = null;
|
|
114 }
|
|
115
|
|
116 try {
|
|
117 mac.init(new SecretKeySpec(key, type));
|
|
118 }
|
|
119 catch (InvalidKeyException e) {
|
|
120 throw new IllegalArgumentException(e);
|
|
121 }
|
|
122 }
|
|
123
|
|
124 public final void initMac(int seq) {
|
|
125 mac.reset();
|
|
126 mac.update((byte)(seq >> 24));
|
|
127 mac.update((byte)(seq >> 16));
|
|
128 mac.update((byte)(seq >> 8));
|
|
129 mac.update((byte)(seq));
|
|
130 }
|
|
131
|
|
132 public final void update(byte[] packetdata, int off, int len) {
|
|
133 mac.update(packetdata, off, len);
|
|
134 }
|
|
135
|
|
136 public final void getMac(byte[] out, int off) {
|
|
137 try {
|
|
138 if (buffer != null) {
|
|
139 mac.doFinal(buffer, 0);
|
|
140 System.arraycopy(buffer, 0, out, off, out.length - off);
|
|
141 }
|
|
142 else {
|
|
143 mac.doFinal(out, off);
|
|
144 }
|
|
145 }
|
|
146 catch (ShortBufferException e) {
|
|
147 throw new IllegalStateException(e);
|
|
148 }
|
|
149 }
|
|
150
|
|
151 public final int size() {
|
|
152 return outSize;
|
|
153 }
|
|
154 }
|