1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.codec.digest;
19
20 import java.io.BufferedInputStream;
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.nio.ByteBuffer;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.security.InvalidKeyException;
28 import java.security.Key;
29 import java.security.NoSuchAlgorithmException;
30
31 import javax.crypto.Mac;
32 import javax.crypto.spec.SecretKeySpec;
33
34 import org.apache.commons.codec.binary.Hex;
35 import org.apache.commons.codec.binary.StringUtils;
36
37 /**
38 * Simplifies common {@link Mac} tasks. This class is immutable and thread-safe. However the Mac may not be.
39 * <p>
40 * <strong>Note: Not all JCE implementations support all algorithms. If not supported, an IllegalArgumentException is thrown.</strong>
41 * </p>
42 * <p>
43 * Sample usage:
44 * </p>
45 *
46 * <pre>
47 * import static HmacAlgorithms.*;
48 * byte[] key = {1,2,3,4}; // don't use this actual key!
49 * String valueToDigest = "The quick brown fox jumps over the lazy dog";
50 * byte[] hmac = new HmacUtils(HMAC_SHA_224, key).hmac(valueToDigest);
51 * // Mac reuse
52 * HmacUtils hm1 = new HmacUtils("HmacAlgoName", key); // use a valid name here!
53 * String hexPom = hm1.hmacHex(new File("pom.xml"));
54 * String hexNot = hm1.hmacHex(new File("NOTICE.txt"));
55 * </pre>
56 *
57 * @since 1.10
58 */
59 public final class HmacUtils {
60
61 private static final int STREAM_BUFFER_LENGTH = 1024;
62
63 /**
64 * Returns an initialized {@link Mac} for the HmacMD5 algorithm.
65 * <p>
66 * Every implementation of the Java platform is required to support this standard Mac algorithm.
67 * </p>
68 *
69 * @param key The key for the keyed digest (must not be null).
70 * @return A Mac instance initialized with the given key.
71 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
72 * @see Mac#getInstance(String)
73 * @see Mac#init(Key)
74 * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_MD5, byte[])}.
75 */
76 @Deprecated
77 public static Mac getHmacMd5(final byte[] key) {
78 return getInitializedMac(HmacAlgorithms.HMAC_MD5, key);
79 }
80
81 /**
82 * Returns an initialized {@link Mac} for the HmacSHA1 algorithm.
83 * <p>
84 * Every implementation of the Java platform is required to support this standard Mac algorithm.
85 * </p>
86 *
87 * @param key The key for the keyed digest (must not be null).
88 * @return A Mac instance initialized with the given key.
89 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
90 * @see Mac#getInstance(String)
91 * @see Mac#init(Key)
92 * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_1, byte[])}.
93 */
94 @Deprecated
95 public static Mac getHmacSha1(final byte[] key) {
96 return getInitializedMac(HmacAlgorithms.HMAC_SHA_1, key);
97 }
98
99 /**
100 * Returns an initialized {@link Mac} for the HmacSHA256 algorithm.
101 * <p>
102 * Every implementation of the Java platform is required to support this standard Mac algorithm.
103 * </p>
104 *
105 * @param key The key for the keyed digest (must not be null).
106 * @return A Mac instance initialized with the given key.
107 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
108 * @see Mac#getInstance(String)
109 * @see Mac#init(Key)
110 * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_256, byte[])}.
111 */
112 @Deprecated
113 public static Mac getHmacSha256(final byte[] key) {
114 return getInitializedMac(HmacAlgorithms.HMAC_SHA_256, key);
115 }
116
117 /**
118 * Returns an initialized {@link Mac} for the HmacSHA384 algorithm.
119 * <p>
120 * Every implementation of the Java platform is <em>not</em> required to support this Mac algorithm.
121 * </p>
122 *
123 * @param key The key for the keyed digest (must not be null).
124 * @return A Mac instance initialized with the given key.
125 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
126 * @see Mac#getInstance(String)
127 * @see Mac#init(Key)
128 * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_384, byte[])}.
129 */
130 @Deprecated
131 public static Mac getHmacSha384(final byte[] key) {
132 return getInitializedMac(HmacAlgorithms.HMAC_SHA_384, key);
133 }
134
135 /**
136 * Returns an initialized {@link Mac} for the HmacSHA512 algorithm.
137 * <p>
138 * Every implementation of the Java platform is <em>not</em> required to support this Mac algorithm.
139 * </p>
140 *
141 * @param key The key for the keyed digest (must not be null).
142 * @return A Mac instance initialized with the given key.
143 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
144 * @see Mac#getInstance(String)
145 * @see Mac#init(Key)
146 * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_512, byte[])}.
147 */
148 @Deprecated
149 public static Mac getHmacSha512(final byte[] key) {
150 return getInitializedMac(HmacAlgorithms.HMAC_SHA_512, key);
151 }
152
153 /**
154 * Returns an initialized {@link Mac} for the given {@code algorithm}.
155 *
156 * @param algorithm The name of the algorithm requested. See
157 * <a href= "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA" >Appendix A in the Java
158 * Cryptography Architecture Reference Guide</a> for information about standard algorithm names.
159 * @param key The key for the keyed digest (must not be null).
160 * @return A Mac instance initialized with the given key.
161 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
162 * @see Mac#getInstance(String)
163 * @see Mac#init(Key)
164 */
165 public static Mac getInitializedMac(final HmacAlgorithms algorithm, final byte[] key) {
166 return getInitializedMac(algorithm.getName(), key);
167 }
168
169 /**
170 * Returns an initialized {@link Mac} for the given {@code algorithm}.
171 *
172 * @param algorithm The name of the algorithm requested. See
173 * <a href= "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA" >Appendix A in the Java
174 * Cryptography Architecture Reference Guide</a> for information about standard algorithm names.
175 * @param key The key for the keyed digest (must not be null).
176 * @return A Mac instance initialized with the given key.
177 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
178 * @see Mac#getInstance(String)
179 * @see Mac#init(Key)
180 */
181 public static Mac getInitializedMac(final String algorithm, final byte[] key) {
182 if (key == null) {
183 throw new IllegalArgumentException("Null key");
184 }
185 try {
186 final SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
187 final Mac mac = Mac.getInstance(algorithm);
188 mac.init(keySpec);
189 return mac;
190 } catch (final NoSuchAlgorithmException | InvalidKeyException e) {
191 throw new IllegalArgumentException(e);
192 }
193 }
194
195 /**
196 * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
197 *
198 * @param key The key for the keyed digest (must not be null).
199 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
200 * @return HmacMD5 MAC for the given key and value.
201 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
202 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmac(byte[])}.
203 */
204 @Deprecated
205 public static byte[] hmacMd5(final byte[] key, final byte[] valueToDigest) {
206 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
207 }
208
209 /**
210 * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
211 *
212 * @param key The key for the keyed digest (must not be null).
213 * @param valueToDigest The value (data) which should to digest.
214 * The InputStream must not be null and will not be closed.
215 * @return HmacMD5 MAC for the given key and value.
216 * @throws IOException If an I/O error occurs.
217 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
218 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmac(InputStream)}.
219 */
220 @Deprecated
221 public static byte[] hmacMd5(final byte[] key, final InputStream valueToDigest) throws IOException {
222 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
223 }
224
225 /**
226 * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
227 *
228 * @param key The key for the keyed digest (must not be null).
229 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
230 * @return HmacMD5 MAC for the given key and value.
231 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
232 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, String).hmac(String)}.
233 */
234 @Deprecated
235 public static byte[] hmacMd5(final String key, final String valueToDigest) {
236 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
237 }
238
239 /**
240 * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
241 *
242 * @param key The key for the keyed digest (must not be null).
243 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
244 * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase).
245 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
246 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(byte[])}.
247 */
248 @Deprecated
249 public static String hmacMd5Hex(final byte[] key, final byte[] valueToDigest) {
250 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
251 }
252
253 /**
254 * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
255 *
256 * @param key The key for the keyed digest (must not be null).
257 * @param valueToDigest The value (data) which should to digest.
258 * The InputStream must not be null and will not be closed.
259 * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase).
260 * @throws IOException Thrown if an I/O error occurs.
261 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
262 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(InputStream)}.
263 */
264 @Deprecated
265 public static String hmacMd5Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
266 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
267 }
268
269 /**
270 * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
271 *
272 * @param key The key for the keyed digest (must not be null).
273 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
274 * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase).
275 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
276 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, String).hmacHex(String)}.
277 */
278 @Deprecated
279 public static String hmacMd5Hex(final String key, final String valueToDigest) {
280 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
281 }
282
283 /**
284 * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
285 *
286 * @param key The key for the keyed digest (must not be null).
287 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
288 * @return HmacSHA1 MAC for the given key and value.
289 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
290 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmac(byte[])}.
291 */
292 @Deprecated
293 public static byte[] hmacSha1(final byte[] key, final byte[] valueToDigest) {
294 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
295 }
296
297 /**
298 * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
299 *
300 * @param key The key for the keyed digest (must not be null).
301 * @param valueToDigest The value (data) which should to digest.
302 * The InputStream must not be null and will not be closed.
303 * @return HmacSHA1 MAC for the given key and value.
304 * @throws IOException If an I/O error occurs.
305 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
306 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmac(InputStream)}.
307 */
308 @Deprecated
309 public static byte[] hmacSha1(final byte[] key, final InputStream valueToDigest) throws IOException {
310 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
311 }
312
313 /**
314 * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
315 *
316 * @param key The key for the keyed digest (must not be null).
317 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
318 * @return HmacSHA1 MAC for the given key and value.
319 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
320 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmac(String)}.
321 */
322 @Deprecated
323 public static byte[] hmacSha1(final String key, final String valueToDigest) {
324 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
325 }
326
327 /**
328 * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
329 *
330 * @param key The key for the keyed digest (must not be null).
331 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
332 * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase).
333 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
334 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(byte[])}
335 */
336 @Deprecated
337 public static String hmacSha1Hex(final byte[] key, final byte[] valueToDigest) {
338 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
339 }
340
341 /**
342 * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
343 *
344 * @param key The key for the keyed digest (must not be null).
345 * @param valueToDigest The value (data) which should to digest.
346 * The InputStream must not be null and will not be closed.
347 * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase).
348 * @throws IOException If an I/O error occurs.
349 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
350 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(InputStream)}.
351 */
352 @Deprecated
353 public static String hmacSha1Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
354 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
355 }
356
357 /**
358 * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
359 *
360 * @param key The key for the keyed digest (must not be null).
361 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
362 * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase).
363 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
364 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmacHex(String)}.
365 */
366 @Deprecated
367 public static String hmacSha1Hex(final String key, final String valueToDigest) {
368 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
369 }
370
371 /**
372 * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
373 *
374 * @param key The key for the keyed digest (must not be null).
375 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
376 * @return HmacSHA256 MAC for the given key and value.
377 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
378 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(byte[])}.
379 */
380 @Deprecated
381 public static byte[] hmacSha256(final byte[] key, final byte[] valueToDigest) {
382 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
383 }
384
385 /**
386 * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
387 *
388 * @param key The key for the keyed digest (must not be null).
389 * @param valueToDigest The value (data) which should to digest. The InputStream must not be null and will not be closed.
390 * @return HmacSHA256 MAC for the given key and value.
391 * @throws IOException If an I/O error occurs.
392 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
393 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(InputStream)}.
394 */
395 @Deprecated
396 public static byte[] hmacSha256(final byte[] key, final InputStream valueToDigest) throws IOException {
397 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
398 }
399
400 /**
401 * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
402 *
403 * @param key The key for the keyed digest (must not be null).
404 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
405 * @return HmacSHA256 MAC for the given key and value.
406 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
407 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmac(String)}.
408 */
409 @Deprecated
410 public static byte[] hmacSha256(final String key, final String valueToDigest) {
411 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
412 }
413
414 /**
415 * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
416 *
417 * @param key The key for the keyed digest (must not be null).
418 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
419 * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase).
420 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
421 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(byte[])}.
422 */
423 @Deprecated
424 public static String hmacSha256Hex(final byte[] key, final byte[] valueToDigest) {
425 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
426 }
427
428 /**
429 * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
430 *
431 * @param key The key for the keyed digest (must not be null).
432 * @param valueToDigest The value (data) which should to digest.
433 * <p>
434 * The InputStream must not be null and will not be closed.
435 * </p>
436 * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase).
437 * @throws IOException If an I/O error occurs.
438 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
439 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(InputStream)}.
440 */
441 @Deprecated
442 public static String hmacSha256Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
443 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
444 }
445
446 /**
447 * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
448 *
449 * @param key The key for the keyed digest (must not be null).
450 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
451 * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase).
452 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
453 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmacHex(String)}.
454 */
455 @Deprecated
456 public static String hmacSha256Hex(final String key, final String valueToDigest) {
457 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
458 }
459
460 /**
461 * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
462 *
463 * @param key The key for the keyed digest (must not be null).
464 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
465 * @return HmacSHA384 MAC for the given key and value.
466 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
467 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(byte[])}.
468 */
469 @Deprecated
470 public static byte[] hmacSha384(final byte[] key, final byte[] valueToDigest) {
471 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
472 }
473
474 /**
475 * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
476 *
477 * @param key The key for the keyed digest (must not be null).
478 * @param valueToDigest The value (data) which should to digest.
479 * <p>
480 * The InputStream must not be null and will not be closed.
481 * </p>
482 * @return HmacSHA384 MAC for the given key and value.
483 * @throws IOException If an I/O error occurs.
484 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
485 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(InputStream)}.
486 */
487 @Deprecated
488 public static byte[] hmacSha384(final byte[] key, final InputStream valueToDigest) throws IOException {
489 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
490 }
491
492 /**
493 * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
494 *
495 * @param key The key for the keyed digest (must not be null).
496 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
497 * @return HmacSHA384 MAC for the given key and value.
498 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
499 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmac(String)}.
500 */
501 @Deprecated
502 public static byte[] hmacSha384(final String key, final String valueToDigest) {
503 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
504 }
505 // hmacSha384
506
507 /**
508 * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
509 *
510 * @param key The key for the keyed digest (must not be null).
511 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
512 * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase).
513 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
514 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(byte[])}.
515 */
516 @Deprecated
517 public static String hmacSha384Hex(final byte[] key, final byte[] valueToDigest) {
518 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
519 }
520
521 /**
522 * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
523 *
524 * @param key The key for the keyed digest (must not be null).
525 * @param valueToDigest The value (data) which should to digest.
526 * <p>
527 * The InputStream must not be null and will not be closed.
528 * </p>
529 * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase).
530 * @throws IOException If an I/O error occurs.
531 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
532 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(InputStream)}.
533 */
534 @Deprecated
535 public static String hmacSha384Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
536 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
537 }
538
539 /**
540 * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
541 *
542 * @param key The key for the keyed digest (must not be null).
543 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
544 * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase).
545 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
546 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmacHex(String)}.
547 */
548 @Deprecated
549 public static String hmacSha384Hex(final String key, final String valueToDigest) {
550 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
551 }
552
553 /**
554 * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
555 *
556 * @param key The key for the keyed digest (must not be null).
557 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
558 * @return HmacSHA512 MAC for the given key and value.
559 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
560 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(byte[])}.
561 */
562 @Deprecated
563 public static byte[] hmacSha512(final byte[] key, final byte[] valueToDigest) {
564 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
565 }
566
567 /**
568 * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
569 *
570 * @param key The key for the keyed digest (must not be null).
571 * @param valueToDigest The value (data) which should to digest.
572 * <p>
573 * The InputStream must not be null and will not be closed.
574 * </p>
575 * @return HmacSHA512 MAC for the given key and value.
576 * @throws IOException If an I/O error occurs.
577 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
578 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(InputStream)}.
579 */
580 @Deprecated
581 public static byte[] hmacSha512(final byte[] key, final InputStream valueToDigest) throws IOException {
582 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
583 }
584
585 /**
586 * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
587 *
588 * @param key The key for the keyed digest (must not be null).
589 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
590 * @return HmacSHA512 MAC for the given key and value.
591 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
592 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmac(String)}.
593 */
594 @Deprecated
595 public static byte[] hmacSha512(final String key, final String valueToDigest) {
596 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
597 }
598 // hmacSha512
599
600 /**
601 * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
602 *
603 * @param key The key for the keyed digest (must not be null).
604 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
605 * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase).
606 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
607 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(byte[])}.
608 */
609 @Deprecated
610 public static String hmacSha512Hex(final byte[] key, final byte[] valueToDigest) {
611 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
612 }
613
614 /**
615 * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
616 *
617 * @param key The key for the keyed digest (must not be null).
618 * @param valueToDigest The value (data) which should to digest.
619 * <p>
620 * The InputStream must not be null and will not be closed.
621 * </p>
622 * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase).
623 * @throws IOException If an I/O error occurs.
624 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
625 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(InputStream)}.
626 */
627 @Deprecated
628 public static String hmacSha512Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
629 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
630 }
631
632 /**
633 * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
634 *
635 * @param key The key for the keyed digest (must not be null).
636 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
637 * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase).
638 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
639 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmacHex(String)}.
640 */
641 @Deprecated
642 public static String hmacSha512Hex(final String key, final String valueToDigest) {
643 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
644 }
645
646 /**
647 * Tests whether this algorithm is available
648 *
649 * @param hmacAlgorithms The HmacAlgorithms to check.
650 * @return whether this algorithm is available.
651 * @since 1.11
652 */
653 public static boolean isAvailable(final HmacAlgorithms hmacAlgorithms) {
654 return isAvailable(hmacAlgorithms.getName());
655 }
656
657 /**
658 * Tests whether this algorithm is available
659 *
660 * @param name The name to check.
661 * @return whether this algorithm is available.
662 * @since 1.11
663 */
664 public static boolean isAvailable(final String name) {
665 try {
666 Mac.getInstance(name);
667 return true;
668 } catch (final NoSuchAlgorithmException e) {
669 return false;
670 }
671 }
672
673 /**
674 * Resets and then updates the given {@link Mac} with the value.
675 *
676 * @param mac The initialized {@link Mac} to update.
677 * @param valueToDigest The value to update the {@link Mac} with (maybe null or empty).
678 * @return The updated {@link Mac}.
679 * @throws IllegalStateException if the Mac was not initialized.
680 */
681 public static Mac updateHmac(final Mac mac, final byte[] valueToDigest) {
682 mac.reset();
683 mac.update(valueToDigest);
684 return mac;
685 }
686
687 /**
688 * Resets and then updates the given {@link Mac} with the value.
689 *
690 * @param mac The initialized {@link Mac} to update.
691 * @param valueToDigest The value to update the {@link Mac} with.
692 * <p>
693 * The InputStream must not be null and will not be closed.
694 * </p>
695 * @return The updated {@link Mac}.
696 * @throws IOException If an I/O error occurs.
697 * @throws IllegalStateException If the Mac was not initialized.
698 */
699 public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException {
700 mac.reset();
701 final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
702 int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
703 while (read > -1) {
704 mac.update(buffer, 0, read);
705 read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
706 }
707 return mac;
708 }
709
710 /**
711 * Resets and then updates the given {@link Mac} with the value.
712 *
713 * @param mac The initialized {@link Mac} to update.
714 * @param valueToDigest The value to update the {@link Mac} with (maybe null or empty).
715 * @return The updated {@link Mac}.
716 * @throws IllegalStateException if the Mac was not initialized.
717 */
718 public static Mac updateHmac(final Mac mac, final String valueToDigest) {
719 mac.reset();
720 mac.update(StringUtils.getBytesUtf8(valueToDigest));
721 return mac;
722 }
723
724 private final Mac mac;
725
726 /**
727 * Preserves binary compatibility only. As for previous versions does not provide useful behavior.
728 *
729 * @deprecated Since 1.11; only useful to preserve binary compatibility.
730 */
731 @Deprecated
732 public HmacUtils() {
733 this(null);
734 }
735
736 /**
737 * Creates an instance using the provided algorithm type.
738 *
739 * @param algorithm to use.
740 * @param key The key to use.
741 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
742 * @since 1.11
743 */
744 public HmacUtils(final HmacAlgorithms algorithm, final byte[] key) {
745 this(algorithm.getName(), key);
746 }
747
748 /**
749 * Creates an instance using the provided algorithm type.
750 *
751 * @param algorithm to use.
752 * @param key The key to use.
753 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
754 * @since 1.11
755 */
756 public HmacUtils(final HmacAlgorithms algorithm, final String key) {
757 this(algorithm.getName(), StringUtils.getBytesUtf8(key));
758 }
759
760 private HmacUtils(final Mac mac) {
761 this.mac = mac;
762 }
763
764 /**
765 * Creates an instance using the provided algorithm type.
766 *
767 * @param algorithm to use.
768 * @param key The key to use.
769 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
770 * @since 1.11
771 */
772 public HmacUtils(final String algorithm, final byte[] key) {
773 this(getInitializedMac(algorithm, key));
774 }
775
776 /**
777 * Creates an instance using the provided algorithm type.
778 *
779 * @param algorithm to use.
780 * @param key The key to use.
781 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
782 * @since 1.11
783 */
784 public HmacUtils(final String algorithm, final String key) {
785 this(algorithm, StringUtils.getBytesUtf8(key));
786 }
787
788 /**
789 * Returns the digest for the input data.
790 *
791 * @param valueToDigest The input to use.
792 * @return The digest as a byte[].
793 * @since 1.11
794 */
795 public byte[] hmac(final byte[] valueToDigest) {
796 return mac.doFinal(valueToDigest);
797 }
798
799 /**
800 * Returns the digest for the input data.
801 *
802 * @param valueToDigest The input to use.
803 * @return The digest as a byte[].
804 * @since 1.11
805 */
806 public byte[] hmac(final ByteBuffer valueToDigest) {
807 mac.update(valueToDigest);
808 return mac.doFinal();
809 }
810
811 /**
812 * Returns the digest for the file.
813 *
814 * @param valueToDigest The file to use.
815 * @return The digest.
816 * @throws IOException If an I/O error occurs.
817 * @since 1.11
818 */
819 public byte[] hmac(final File valueToDigest) throws IOException {
820 return hmac(valueToDigest.toPath());
821 }
822
823 /**
824 * Returns the digest for the stream.
825 *
826 * @param valueToDigest The data to use.
827 * <p>
828 * The InputStream must not be null and will not be closed.
829 * </p>
830 * @return The digest.
831 * @throws IOException If an I/O error occurs.
832 * @since 1.11
833 */
834 public byte[] hmac(final InputStream valueToDigest) throws IOException {
835 final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
836 int read;
837 while ((read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH)) > -1) {
838 mac.update(buffer, 0, read);
839 }
840 return mac.doFinal();
841 }
842
843 /**
844 * Returns the digest for the file.
845 *
846 * @param valueToDigest The path to use.
847 * @return The digest.
848 * @throws IOException If an I/O error occurs.
849 * @since 1.19.0
850 */
851 public byte[] hmac(final Path valueToDigest) throws IOException {
852 try (BufferedInputStream stream = new BufferedInputStream(Files.newInputStream(valueToDigest))) {
853 return hmac(stream);
854 }
855 }
856
857 /**
858 * Returns the digest for the input data.
859 *
860 * @param valueToDigest The input to use, treated as UTF-8.
861 * @return The digest as a byte[].
862 * @since 1.11
863 */
864 public byte[] hmac(final String valueToDigest) {
865 return mac.doFinal(StringUtils.getBytesUtf8(valueToDigest));
866 }
867
868 /**
869 * Returns the digest for the input data.
870 *
871 * @param valueToDigest The input to use.
872 * @return The digest as a hexadecimal String.
873 * @since 1.11
874 */
875 public String hmacHex(final byte[] valueToDigest) {
876 return Hex.encodeHexString(hmac(valueToDigest));
877 }
878
879 /**
880 * Returns the digest for the input data.
881 *
882 * @param valueToDigest The input to use.
883 * @return The digest as a hexadecimal String.
884 * @since 1.11
885 */
886 public String hmacHex(final ByteBuffer valueToDigest) {
887 return Hex.encodeHexString(hmac(valueToDigest));
888 }
889
890 /**
891 * Returns the digest for the file.
892 *
893 * @param valueToDigest The file to use.
894 * @return The digest as a hexadecimal String.
895 * @throws IOException If an I/O error occurs.
896 * @since 1.11
897 */
898 public String hmacHex(final File valueToDigest) throws IOException {
899 return Hex.encodeHexString(hmac(valueToDigest));
900 }
901
902 /**
903 * Returns the digest for the stream.
904 *
905 * @param valueToDigest The data to use.
906 * <p>
907 * The InputStream must not be null and will not be closed.
908 * </p>
909 * @return The digest as a hexadecimal String.
910 * @throws IOException If an I/O error occurs.
911 * @since 1.11
912 */
913 public String hmacHex(final InputStream valueToDigest) throws IOException {
914 return Hex.encodeHexString(hmac(valueToDigest));
915 }
916
917 /**
918 * Returns the digest for the path.
919 *
920 * @param valueToDigest The path to use.
921 * @return The digest as a hexadecimal String.
922 * @throws IOException If an I/O error occurs.
923 * @since 1.19.0
924 */
925 public String hmacHex(final Path valueToDigest) throws IOException {
926 return Hex.encodeHexString(hmac(valueToDigest));
927 }
928
929 /**
930 * Returns the digest for the input data.
931 *
932 * @param valueToDigest The input to use, treated as UTF-8.
933 * @return The digest as a hexadecimal String.
934 * @since 1.11
935 */
936 public String hmacHex(final String valueToDigest) {
937 return Hex.encodeHexString(hmac(valueToDigest));
938 }
939 }