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 javax.crypto.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 re-use
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 {@code 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 when 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 {@code 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 when 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 {@code 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 when 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 {@code 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 when 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 {@code 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 when 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 {@code 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 when 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 {@code 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 when 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 when 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 * <p>
215 * The InputStream must not be null and will not be closed.
216 * </p>
217 * @return HmacMD5 MAC for the given key and value.
218 * @throws IOException If an I/O error occurs.
219 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
220 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmac(InputStream)}.
221 */
222 @Deprecated
223 public static byte[] hmacMd5(final byte[] key, final InputStream valueToDigest) throws IOException {
224 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
225 }
226
227 /**
228 * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
229 *
230 * @param key The key for the keyed digest (must not be null).
231 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
232 * @return HmacMD5 MAC for the given key and value.
233 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
234 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, String).hmac(String)}.
235 */
236 @Deprecated
237 public static byte[] hmacMd5(final String key, final String valueToDigest) {
238 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
239 }
240
241 /**
242 * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
243 *
244 * @param key The key for the keyed digest (must not be null).
245 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
246 * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase).
247 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
248 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(byte[])}.
249 */
250 @Deprecated
251 public static String hmacMd5Hex(final byte[] key, final byte[] valueToDigest) {
252 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
253 }
254
255 /**
256 * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
257 *
258 * @param key The key for the keyed digest (must not be null).
259 * @param valueToDigest The value (data) which should to digest
260 * <p>
261 * The InputStream must not be null and will not be closed.
262 * </p>
263 * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase).
264 * @throws IOException If an I/O error occurs.
265 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
266 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(InputStream)}.
267 */
268 @Deprecated
269 public static String hmacMd5Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
270 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
271 }
272
273 /**
274 * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
275 *
276 * @param key The key for the keyed digest (must not be null).
277 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
278 * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase).
279 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
280 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, String).hmacHex(String)}.
281 */
282 @Deprecated
283 public static String hmacMd5Hex(final String key, final String valueToDigest) {
284 return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
285 }
286
287 /**
288 * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
289 *
290 * @param key The key for the keyed digest (must not be null).
291 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
292 * @return HmacSHA1 MAC for the given key and value.
293 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
294 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmac(byte[])}.
295 */
296 @Deprecated
297 public static byte[] hmacSha1(final byte[] key, final byte[] valueToDigest) {
298 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
299 }
300
301 /**
302 * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
303 *
304 * @param key The key for the keyed digest (must not be null).
305 * @param valueToDigest The value (data) which should to digest
306 * <p>
307 * The InputStream must not be null and will not be closed.
308 * </p>
309 * @return HmacSHA1 MAC for the given key and value.
310 * @throws IOException If an I/O error occurs.
311 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
312 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmac(InputStream)}.
313 */
314 @Deprecated
315 public static byte[] hmacSha1(final byte[] key, final InputStream valueToDigest) throws IOException {
316 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
317 }
318
319 /**
320 * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
321 *
322 * @param key The key for the keyed digest (must not be null).
323 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
324 * @return HmacSHA1 MAC for the given key and value.
325 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
326 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmac(String)}.
327 */
328 @Deprecated
329 public static byte[] hmacSha1(final String key, final String valueToDigest) {
330 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
331 }
332
333 /**
334 * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
335 *
336 * @param key The key for the keyed digest (must not be null).
337 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
338 * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase).
339 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
340 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(byte[])}
341 */
342 @Deprecated
343 public static String hmacSha1Hex(final byte[] key, final byte[] valueToDigest) {
344 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
345 }
346
347 /**
348 * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
349 *
350 * @param key The key for the keyed digest (must not be null).
351 * @param valueToDigest The value (data) which should to digest.
352 * <p>
353 * The InputStream must not be null and will not be closed.
354 * </p>
355 * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase).
356 * @throws IOException If an I/O error occurs.
357 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
358 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(InputStream)}.
359 */
360 @Deprecated
361 public static String hmacSha1Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
362 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
363 }
364
365 /**
366 * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
367 *
368 * @param key The key for the keyed digest (must not be null).
369 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
370 * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase).
371 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
372 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmacHex(String)}.
373 */
374 @Deprecated
375 public static String hmacSha1Hex(final String key, final String valueToDigest) {
376 return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
377 }
378
379 /**
380 * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
381 *
382 * @param key The key for the keyed digest (must not be null).
383 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
384 * @return HmacSHA256 MAC for the given key and value.
385 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
386 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(byte[])}.
387 */
388 @Deprecated
389 public static byte[] hmacSha256(final byte[] key, final byte[] valueToDigest) {
390 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
391 }
392
393 /**
394 * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
395 *
396 * @param key The key for the keyed digest (must not be null).
397 * @param valueToDigest The value (data) which should to digest.
398 * <p>
399 * The InputStream must not be null and will not be closed.
400 * </p>
401 * @return HmacSHA256 MAC for the given key and value.
402 * @throws IOException If an I/O error occurs.
403 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
404 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(InputStream)}.
405 */
406 @Deprecated
407 public static byte[] hmacSha256(final byte[] key, final InputStream valueToDigest) throws IOException {
408 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
409 }
410
411 /**
412 * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
413 *
414 * @param key The key for the keyed digest (must not be null).
415 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
416 * @return HmacSHA256 MAC for the given key and value.
417 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
418 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmac(String)}.
419 */
420 @Deprecated
421 public static byte[] hmacSha256(final String key, final String valueToDigest) {
422 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
423 }
424
425 /**
426 * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
427 *
428 * @param key The key for the keyed digest (must not be null).
429 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
430 * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase).
431 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
432 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(byte[])}.
433 */
434 @Deprecated
435 public static String hmacSha256Hex(final byte[] key, final byte[] valueToDigest) {
436 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
437 }
438
439 /**
440 * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
441 *
442 * @param key The key for the keyed digest (must not be null).
443 * @param valueToDigest The value (data) which should to digest.
444 * <p>
445 * The InputStream must not be null and will not be closed.
446 * </p>
447 * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase).
448 * @throws IOException If an I/O error occurs.
449 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
450 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(InputStream)}.
451 */
452 @Deprecated
453 public static String hmacSha256Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
454 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
455 }
456
457 /**
458 * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
459 *
460 * @param key The key for the keyed digest (must not be null).
461 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
462 * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase).
463 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
464 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmacHex(String)}.
465 */
466 @Deprecated
467 public static String hmacSha256Hex(final String key, final String valueToDigest) {
468 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
469 }
470
471 /**
472 * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
473 *
474 * @param key The key for the keyed digest (must not be null).
475 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
476 * @return HmacSHA384 MAC for the given key and value.
477 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
478 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(byte[])}.
479 */
480 @Deprecated
481 public static byte[] hmacSha384(final byte[] key, final byte[] valueToDigest) {
482 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
483 }
484
485 /**
486 * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
487 *
488 * @param key The key for the keyed digest (must not be null).
489 * @param valueToDigest The value (data) which should to digest.
490 * <p>
491 * The InputStream must not be null and will not be closed.
492 * </p>
493 * @return HmacSHA384 MAC for the given key and value.
494 * @throws IOException If an I/O error occurs.
495 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
496 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(InputStream)}.
497 */
498 @Deprecated
499 public static byte[] hmacSha384(final byte[] key, final InputStream valueToDigest) throws IOException {
500 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
501 }
502
503 /**
504 * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
505 *
506 * @param key The key for the keyed digest (must not be null).
507 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
508 * @return HmacSHA384 MAC for the given key and value.
509 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
510 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmac(String)}.
511 */
512 @Deprecated
513 public static byte[] hmacSha384(final String key, final String valueToDigest) {
514 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
515 }
516 // hmacSha384
517
518 /**
519 * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
520 *
521 * @param key The key for the keyed digest (must not be null).
522 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
523 * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase).
524 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
525 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(byte[])}.
526 */
527 @Deprecated
528 public static String hmacSha384Hex(final byte[] key, final byte[] valueToDigest) {
529 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
530 }
531
532 /**
533 * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
534 *
535 * @param key The key for the keyed digest (must not be null).
536 * @param valueToDigest The value (data) which should to digest.
537 * <p>
538 * The InputStream must not be null and will not be closed.
539 * </p>
540 * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase).
541 * @throws IOException If an I/O error occurs.
542 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
543 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(InputStream)}.
544 */
545 @Deprecated
546 public static String hmacSha384Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
547 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
548 }
549
550 /**
551 * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
552 *
553 * @param key The key for the keyed digest (must not be null).
554 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
555 * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase).
556 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
557 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmacHex(String)}.
558 */
559 @Deprecated
560 public static String hmacSha384Hex(final String key, final String valueToDigest) {
561 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
562 }
563
564 /**
565 * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
566 *
567 * @param key The key for the keyed digest (must not be null).
568 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
569 * @return HmacSHA512 MAC for the given key and value.
570 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
571 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(byte[])}.
572 */
573 @Deprecated
574 public static byte[] hmacSha512(final byte[] key, final byte[] valueToDigest) {
575 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
576 }
577
578 /**
579 * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
580 *
581 * @param key The key for the keyed digest (must not be null).
582 * @param valueToDigest The value (data) which should to digest.
583 * <p>
584 * The InputStream must not be null and will not be closed.
585 * </p>
586 * @return HmacSHA512 MAC for the given key and value.
587 * @throws IOException If an I/O error occurs.
588 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
589 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(InputStream)}.
590 */
591 @Deprecated
592 public static byte[] hmacSha512(final byte[] key, final InputStream valueToDigest) throws IOException {
593 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
594 }
595
596 /**
597 * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
598 *
599 * @param key The key for the keyed digest (must not be null).
600 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
601 * @return HmacSHA512 MAC for the given key and value.
602 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
603 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmac(String)}.
604 */
605 @Deprecated
606 public static byte[] hmacSha512(final String key, final String valueToDigest) {
607 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
608 }
609 // hmacSha512
610
611 /**
612 * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
613 *
614 * @param key The key for the keyed digest (must not be null).
615 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
616 * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase).
617 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
618 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(byte[])}.
619 */
620 @Deprecated
621 public static String hmacSha512Hex(final byte[] key, final byte[] valueToDigest) {
622 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
623 }
624
625 /**
626 * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
627 *
628 * @param key The key for the keyed digest (must not be null).
629 * @param valueToDigest The value (data) which should to digest.
630 * <p>
631 * The InputStream must not be null and will not be closed.
632 * </p>
633 * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase).
634 * @throws IOException If an I/O error occurs.
635 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
636 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(InputStream)}.
637 */
638 @Deprecated
639 public static String hmacSha512Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
640 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
641 }
642
643 /**
644 * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
645 *
646 * @param key The key for the keyed digest (must not be null).
647 * @param valueToDigest The value (data) which should to digest (maybe empty or null).
648 * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase).
649 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
650 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmacHex(String)}.
651 */
652 @Deprecated
653 public static String hmacSha512Hex(final String key, final String valueToDigest) {
654 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
655 }
656
657 /**
658 * Tests whether this algorithm is available
659 *
660 * @param hmacAlgorithms the HmacAlgorithms to check.
661 * @return whether this algorithm is available.
662 * @since 1.11
663 */
664 public static boolean isAvailable(final HmacAlgorithms hmacAlgorithms) {
665 return isAvailable(hmacAlgorithms.getName());
666 }
667
668 /**
669 * Tests whether this algorithm is available
670 *
671 * @param name the name to check.
672 * @return whether this algorithm is available.
673 * @since 1.11
674 */
675 public static boolean isAvailable(final String name) {
676 try {
677 Mac.getInstance(name);
678 return true;
679 } catch (final NoSuchAlgorithmException e) {
680 return false;
681 }
682 }
683
684 /**
685 * Resets and then updates the given {@link Mac} with the value.
686 *
687 * @param mac the initialized {@link Mac} to update.
688 * @param valueToDigest the value to update the {@link Mac} with (maybe null or empty).
689 * @return the updated {@link Mac}.
690 * @throws IllegalStateException if the Mac was not initialized.
691 */
692 public static Mac updateHmac(final Mac mac, final byte[] valueToDigest) {
693 mac.reset();
694 mac.update(valueToDigest);
695 return mac;
696 }
697
698 /**
699 * Resets and then updates the given {@link Mac} with the value.
700 *
701 * @param mac the initialized {@link Mac} to update.
702 * @param valueToDigest the value to update the {@link Mac} with.
703 * <p>
704 * The InputStream must not be null and will not be closed.
705 * </p>
706 * @return the updated {@link Mac}.
707 * @throws IOException If an I/O error occurs.
708 * @throws IllegalStateException If the Mac was not initialized.
709 */
710 public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException {
711 mac.reset();
712 final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
713 int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
714 while (read > -1) {
715 mac.update(buffer, 0, read);
716 read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
717 }
718 return mac;
719 }
720
721 /**
722 * Resets and then updates the given {@link Mac} with the value.
723 *
724 * @param mac the initialized {@link Mac} to update.
725 * @param valueToDigest the value to update the {@link Mac} with (maybe null or empty).
726 * @return the updated {@link Mac}.
727 * @throws IllegalStateException if the Mac was not initialized.
728 */
729 public static Mac updateHmac(final Mac mac, final String valueToDigest) {
730 mac.reset();
731 mac.update(StringUtils.getBytesUtf8(valueToDigest));
732 return mac;
733 }
734
735 private final Mac mac;
736
737 /**
738 * Preserves binary compatibility only. As for previous versions does not provide useful behavior.
739 *
740 * @deprecated Since 1.11; only useful to preserve binary compatibility.
741 */
742 @Deprecated
743 public HmacUtils() {
744 this(null);
745 }
746
747 /**
748 * Creates an instance using the provided algorithm type.
749 *
750 * @param algorithm to use.
751 * @param key the key to use.
752 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
753 * @since 1.11
754 */
755 public HmacUtils(final HmacAlgorithms algorithm, final byte[] key) {
756 this(algorithm.getName(), key);
757 }
758
759 /**
760 * Creates an instance using the provided algorithm type.
761 *
762 * @param algorithm to use.
763 * @param key the key to use.
764 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
765 * @since 1.11
766 */
767 public HmacUtils(final HmacAlgorithms algorithm, final String key) {
768 this(algorithm.getName(), StringUtils.getBytesUtf8(key));
769 }
770
771 private HmacUtils(final Mac mac) {
772 this.mac = mac;
773 }
774
775 /**
776 * Creates an instance using the provided algorithm type.
777 *
778 * @param algorithm to use.
779 * @param key the key to use.
780 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
781 * @since 1.11
782 */
783 public HmacUtils(final String algorithm, final byte[] key) {
784 this(getInitializedMac(algorithm, key));
785 }
786
787 /**
788 * Creates an instance using the provided algorithm type.
789 *
790 * @param algorithm to use.
791 * @param key the key to use.
792 * @throws IllegalArgumentException when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
793 * @since 1.11
794 */
795 public HmacUtils(final String algorithm, final String key) {
796 this(algorithm, StringUtils.getBytesUtf8(key));
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 byte[] valueToDigest) {
807 return mac.doFinal(valueToDigest);
808 }
809
810 /**
811 * Returns the digest for the input data.
812 *
813 * @param valueToDigest the input to use.
814 * @return the digest as a byte[].
815 * @since 1.11
816 */
817 public byte[] hmac(final ByteBuffer valueToDigest) {
818 mac.update(valueToDigest);
819 return mac.doFinal();
820 }
821
822 /**
823 * Returns the digest for the file.
824 *
825 * @param valueToDigest the file to use.
826 * @return the digest.
827 * @throws IOException If an I/O error occurs.
828 * @since 1.11
829 */
830 public byte[] hmac(final File valueToDigest) throws IOException {
831 return hmac(valueToDigest.toPath());
832 }
833
834 /**
835 * Returns the digest for the stream.
836 *
837 * @param valueToDigest the data to use.
838 * <p>
839 * The InputStream must not be null and will not be closed.
840 * </p>
841 * @return the digest.
842 * @throws IOException If an I/O error occurs.
843 * @since 1.11
844 */
845 public byte[] hmac(final InputStream valueToDigest) throws IOException {
846 final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
847 int read;
848 while ((read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH)) > -1) {
849 mac.update(buffer, 0, read);
850 }
851 return mac.doFinal();
852 }
853
854 /**
855 * Returns the digest for the file.
856 *
857 * @param valueToDigest the path to use.
858 * @return the digest.
859 * @throws IOException If an I/O error occurs.
860 * @since 1.19.0
861 */
862 public byte[] hmac(final Path valueToDigest) throws IOException {
863 try (BufferedInputStream stream = new BufferedInputStream(Files.newInputStream(valueToDigest))) {
864 return hmac(stream);
865 }
866 }
867
868 /**
869 * Returns the digest for the input data.
870 *
871 * @param valueToDigest the input to use, treated as UTF-8.
872 * @return the digest as a byte[].
873 * @since 1.11
874 */
875 public byte[] hmac(final String valueToDigest) {
876 return mac.doFinal(StringUtils.getBytesUtf8(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 byte[] valueToDigest) {
887 return Hex.encodeHexString(hmac(valueToDigest));
888 }
889
890 /**
891 * Returns the digest for the input data.
892 *
893 * @param valueToDigest the input to use.
894 * @return the digest as a hexadecimal String.
895 * @since 1.11
896 */
897 public String hmacHex(final ByteBuffer valueToDigest) {
898 return Hex.encodeHexString(hmac(valueToDigest));
899 }
900
901 /**
902 * Returns the digest for the file.
903 *
904 * @param valueToDigest the file to use.
905 * @return the digest as a hexadecimal String.
906 * @throws IOException If an I/O error occurs.
907 * @since 1.11
908 */
909 public String hmacHex(final File valueToDigest) throws IOException {
910 return Hex.encodeHexString(hmac(valueToDigest));
911 }
912
913 /**
914 * Returns the digest for the stream.
915 *
916 * @param valueToDigest the data to use.
917 * <p>
918 * The InputStream must not be null and will not be closed.
919 * </p>
920 * @return the digest as a hexadecimal String.
921 * @throws IOException If an I/O error occurs.
922 * @since 1.11
923 */
924 public String hmacHex(final InputStream valueToDigest) throws IOException {
925 return Hex.encodeHexString(hmac(valueToDigest));
926 }
927
928 /**
929 * Returns the digest for the path.
930 *
931 * @param valueToDigest the path to use.
932 * @return the digest as a hexadecimal String.
933 * @throws IOException If an I/O error occurs.
934 * @since 1.19.0
935 */
936 public String hmacHex(final Path valueToDigest) throws IOException {
937 return Hex.encodeHexString(hmac(valueToDigest));
938 }
939
940 /**
941 * Returns the digest for the input data.
942 *
943 * @param valueToDigest the input to use, treated as UTF-8.
944 * @return the digest as a hexadecimal String.
945 * @since 1.11
946 */
947 public String hmacHex(final String valueToDigest) {
948 return Hex.encodeHexString(hmac(valueToDigest));
949 }
950 }