001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.codec.digest; 019 020import java.io.BufferedInputStream; 021import java.io.File; 022import java.io.IOException; 023import java.io.InputStream; 024import java.nio.ByteBuffer; 025import java.nio.file.Files; 026import java.nio.file.Path; 027import java.security.InvalidKeyException; 028import java.security.Key; 029import java.security.NoSuchAlgorithmException; 030 031import javax.crypto.Mac; 032import javax.crypto.spec.SecretKeySpec; 033 034import org.apache.commons.codec.binary.Hex; 035import org.apache.commons.codec.binary.StringUtils; 036 037/** 038 * Simplifies common {@link Mac} tasks. This class is immutable and thread-safe. However the Mac may not be. 039 * <p> 040 * <strong>Note: Not all JCE implementations support all algorithms. If not supported, an IllegalArgumentException is thrown.</strong> 041 * </p> 042 * <p> 043 * Sample usage: 044 * </p> 045 * 046 * <pre> 047 * import static HmacAlgorithms.*; 048 * byte[] key = {1,2,3,4}; // don't use this actual key! 049 * String valueToDigest = "The quick brown fox jumps over the lazy dog"; 050 * byte[] hmac = new HmacUtils(HMAC_SHA_224, key).hmac(valueToDigest); 051 * // Mac reuse 052 * HmacUtils hm1 = new HmacUtils("HmacAlgoName", key); // use a valid name here! 053 * String hexPom = hm1.hmacHex(new File("pom.xml")); 054 * String hexNot = hm1.hmacHex(new File("NOTICE.txt")); 055 * </pre> 056 * 057 * @since 1.10 058 */ 059public final class HmacUtils { 060 061 private static final int STREAM_BUFFER_LENGTH = 1024; 062 063 /** 064 * Gets an initialized {@link Mac} for the HmacMD5 algorithm. 065 * <p> 066 * Every implementation of the Java platform is required to support this standard Mac algorithm. 067 * </p> 068 * 069 * @param key The key for the keyed digest (must not be null). 070 * @return A Mac instance initialized with the given key. 071 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 072 * @see Mac#getInstance(String) 073 * @see Mac#init(Key) 074 * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_MD5, byte[])}. 075 */ 076 @Deprecated 077 public static Mac getHmacMd5(final byte[] key) { 078 return getInitializedMac(HmacAlgorithms.HMAC_MD5, key); 079 } 080 081 /** 082 * Gets an initialized {@link Mac} for the HmacSHA1 algorithm. 083 * <p> 084 * Every implementation of the Java platform is required to support this standard Mac algorithm. 085 * </p> 086 * 087 * @param key The key for the keyed digest (must not be null). 088 * @return A Mac instance initialized with the given key. 089 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 090 * @see Mac#getInstance(String) 091 * @see Mac#init(Key) 092 * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_1, byte[])}. 093 */ 094 @Deprecated 095 public static Mac getHmacSha1(final byte[] key) { 096 return getInitializedMac(HmacAlgorithms.HMAC_SHA_1, key); 097 } 098 099 /** 100 * Gets 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 * Gets 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 * Gets 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 * Gets 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 * Gets 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 Thrown 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 Thrown 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 Thrown 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 Thrown 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 * The InputStream must not be null and will not be closed. 434 * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase). 435 * @throws IOException Thrown if an I/O error occurs. 436 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 437 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(InputStream)}. 438 */ 439 @Deprecated 440 public static String hmacSha256Hex(final byte[] key, final InputStream valueToDigest) throws IOException { 441 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest); 442 } 443 444 /** 445 * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value. 446 * 447 * @param key The key for the keyed digest (must not be null). 448 * @param valueToDigest The value (data) which should to digest (maybe empty or null). 449 * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase). 450 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 451 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmacHex(String)}. 452 */ 453 @Deprecated 454 public static String hmacSha256Hex(final String key, final String valueToDigest) { 455 return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest); 456 } 457 458 /** 459 * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value. 460 * 461 * @param key The key for the keyed digest (must not be null). 462 * @param valueToDigest The value (data) which should to digest (maybe empty or null). 463 * @return HmacSHA384 MAC for the given key and value. 464 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 465 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(byte[])}. 466 */ 467 @Deprecated 468 public static byte[] hmacSha384(final byte[] key, final byte[] valueToDigest) { 469 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest); 470 } 471 472 /** 473 * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value. 474 * 475 * @param key The key for the keyed digest (must not be null). 476 * @param valueToDigest The value (data) which should to digest. 477 * The InputStream must not be null and will not be closed. 478 * @return HmacSHA384 MAC for the given key and value. 479 * @throws IOException Thrown if an I/O error occurs. 480 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 481 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(InputStream)}. 482 */ 483 @Deprecated 484 public static byte[] hmacSha384(final byte[] key, final InputStream valueToDigest) throws IOException { 485 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest); 486 } 487 488 /** 489 * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value. 490 * 491 * @param key The key for the keyed digest (must not be null). 492 * @param valueToDigest The value (data) which should to digest (maybe empty or null). 493 * @return HmacSHA384 MAC for the given key and value. 494 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 495 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmac(String)}. 496 */ 497 @Deprecated 498 public static byte[] hmacSha384(final String key, final String valueToDigest) { 499 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest); 500 } 501 // hmacSha384 502 503 /** 504 * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) 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 as hexadecimal string (lowercase). 509 * @throws IllegalArgumentException Thrown if 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, byte[]).hmacHex(byte[])}. 511 */ 512 @Deprecated 513 public static String hmacSha384Hex(final byte[] key, final byte[] valueToDigest) { 514 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest); 515 } 516 517 /** 518 * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value. 519 * 520 * @param key The key for the keyed digest (must not be null). 521 * @param valueToDigest The value (data) which should to digest. 522 * The InputStream must not be null and will not be closed. 523 * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase). 524 * @throws IOException Thrown if an I/O error occurs. 525 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 526 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(InputStream)}. 527 */ 528 @Deprecated 529 public static String hmacSha384Hex(final byte[] key, final InputStream valueToDigest) throws IOException { 530 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest); 531 } 532 533 /** 534 * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value. 535 * 536 * @param key The key for the keyed digest (must not be null). 537 * @param valueToDigest The value (data) which should to digest (maybe empty or null). 538 * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase). 539 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 540 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmacHex(String)}. 541 */ 542 @Deprecated 543 public static String hmacSha384Hex(final String key, final String valueToDigest) { 544 return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest); 545 } 546 547 /** 548 * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value. 549 * 550 * @param key The key for the keyed digest (must not be null). 551 * @param valueToDigest The value (data) which should to digest (maybe empty or null). 552 * @return HmacSHA512 MAC for the given key and value. 553 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 554 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(byte[])}. 555 */ 556 @Deprecated 557 public static byte[] hmacSha512(final byte[] key, final byte[] valueToDigest) { 558 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest); 559 } 560 561 /** 562 * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value. 563 * 564 * @param key The key for the keyed digest (must not be null). 565 * @param valueToDigest The value (data) which should to digest. 566 * The InputStream must not be null and will not be closed. 567 * @return HmacSHA512 MAC for the given key and value. 568 * @throws IOException Thrown if an I/O error occurs. 569 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 570 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(InputStream)}. 571 */ 572 @Deprecated 573 public static byte[] hmacSha512(final byte[] key, final InputStream valueToDigest) throws IOException { 574 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest); 575 } 576 577 /** 578 * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value. 579 * 580 * @param key The key for the keyed digest (must not be null). 581 * @param valueToDigest The value (data) which should to digest (maybe empty or null). 582 * @return HmacSHA512 MAC for the given key and value. 583 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 584 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmac(String)}. 585 */ 586 @Deprecated 587 public static byte[] hmacSha512(final String key, final String valueToDigest) { 588 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest); 589 } 590 // hmacSha512 591 592 /** 593 * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value. 594 * 595 * @param key The key for the keyed digest (must not be null). 596 * @param valueToDigest The value (data) which should to digest (maybe empty or null). 597 * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase). 598 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 599 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(byte[])}. 600 */ 601 @Deprecated 602 public static String hmacSha512Hex(final byte[] key, final byte[] valueToDigest) { 603 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest); 604 } 605 606 /** 607 * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value. 608 * 609 * @param key The key for the keyed digest (must not be null). 610 * @param valueToDigest The value (data) which should to digest. 611 * The InputStream must not be null and will not be closed. 612 * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase). 613 * @throws IOException Thrown if an I/O error occurs. 614 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 615 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(InputStream)}. 616 */ 617 @Deprecated 618 public static String hmacSha512Hex(final byte[] key, final InputStream valueToDigest) throws IOException { 619 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest); 620 } 621 622 /** 623 * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value. 624 * 625 * @param key The key for the keyed digest (must not be null). 626 * @param valueToDigest The value (data) which should to digest (maybe empty or null). 627 * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase). 628 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 629 * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmacHex(String)}. 630 */ 631 @Deprecated 632 public static String hmacSha512Hex(final String key, final String valueToDigest) { 633 return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest); 634 } 635 636 /** 637 * Tests whether this algorithm is available. 638 * 639 * @param hmacAlgorithms The HmacAlgorithms to check. 640 * @return whether this algorithm is available. 641 * @since 1.11 642 */ 643 public static boolean isAvailable(final HmacAlgorithms hmacAlgorithms) { 644 return isAvailable(hmacAlgorithms.getName()); 645 } 646 647 /** 648 * Tests whether this algorithm is available. 649 * 650 * @param name The name to check. 651 * @return whether this algorithm is available. 652 * @since 1.11 653 */ 654 public static boolean isAvailable(final String name) { 655 try { 656 Mac.getInstance(name); 657 return true; 658 } catch (final NoSuchAlgorithmException e) { 659 return false; 660 } 661 } 662 663 /** 664 * Resets and then updates the given {@link Mac} with the value. 665 * 666 * @param mac The initialized {@link Mac} to update. 667 * @param valueToDigest The value to update the {@link Mac} with (maybe null or empty). 668 * @return The updated {@link Mac}. 669 * @throws IllegalStateException Thrown if the Mac was not initialized. 670 */ 671 public static Mac updateHmac(final Mac mac, final byte[] valueToDigest) { 672 mac.reset(); 673 mac.update(valueToDigest); 674 return mac; 675 } 676 677 /** 678 * Resets and then updates the given {@link Mac} with the value. 679 * 680 * @param mac The initialized {@link Mac} to update. 681 * @param valueToDigest The value to update the {@link Mac} with. 682 * The InputStream must not be null and will not be closed. 683 * @return The updated {@link Mac}. 684 * @throws IOException Thrown if an I/O error occurs. 685 * @throws IllegalStateException Thrown if the Mac was not initialized. 686 */ 687 public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException { 688 mac.reset(); 689 final byte[] buffer = new byte[STREAM_BUFFER_LENGTH]; 690 int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH); 691 while (read > -1) { 692 mac.update(buffer, 0, read); 693 read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH); 694 } 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 (maybe null or empty). 703 * @return The updated {@link Mac}. 704 * @throws IllegalStateException Thrown if the Mac was not initialized. 705 */ 706 public static Mac updateHmac(final Mac mac, final String valueToDigest) { 707 mac.reset(); 708 mac.update(StringUtils.getBytesUtf8(valueToDigest)); 709 return mac; 710 } 711 712 private final Mac mac; 713 714 /** 715 * Preserves binary compatibility only. As for previous versions does not provide useful behavior. 716 * 717 * @deprecated Since 1.11; only useful to preserve binary compatibility. 718 */ 719 @Deprecated 720 public HmacUtils() { 721 this(null); 722 } 723 724 /** 725 * Creates an instance using the provided algorithm type. 726 * 727 * @param algorithm to use. 728 * @param key The key to use. 729 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 730 * @since 1.11 731 */ 732 public HmacUtils(final HmacAlgorithms algorithm, final byte[] key) { 733 this(algorithm.getName(), key); 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 String key) { 745 this(algorithm.getName(), StringUtils.getBytesUtf8(key)); 746 } 747 748 private HmacUtils(final Mac mac) { 749 this.mac = mac; 750 } 751 752 /** 753 * Creates an instance using the provided algorithm type. 754 * 755 * @param algorithm to use. 756 * @param key The key to use. 757 * @throws IllegalArgumentException Thrown if a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid. 758 * @since 1.11 759 */ 760 public HmacUtils(final String algorithm, final byte[] key) { 761 this(getInitializedMac(algorithm, key)); 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 String key) { 773 this(algorithm, StringUtils.getBytesUtf8(key)); 774 } 775 776 /** 777 * Returns the digest for the input data. 778 * 779 * @param valueToDigest The input to use. 780 * @return The digest as a byte[]. 781 * @since 1.11 782 */ 783 public byte[] hmac(final byte[] valueToDigest) { 784 return mac.doFinal(valueToDigest); 785 } 786 787 /** 788 * Returns the digest for the input data. 789 * 790 * @param valueToDigest The input to use. 791 * @return The digest as a byte[]. 792 * @since 1.11 793 */ 794 public byte[] hmac(final ByteBuffer valueToDigest) { 795 mac.update(valueToDigest); 796 return mac.doFinal(); 797 } 798 799 /** 800 * Returns the digest for the file. 801 * 802 * @param valueToDigest The file to use. 803 * @return The digest. 804 * @throws IOException Thrown if an I/O error occurs. 805 * @since 1.11 806 */ 807 public byte[] hmac(final File valueToDigest) throws IOException { 808 return hmac(valueToDigest.toPath()); 809 } 810 811 /** 812 * Returns the digest for the stream. 813 * 814 * @param valueToDigest The data to use. 815 * The InputStream must not be null and will not be closed. 816 * @return The digest. 817 * @throws IOException Thrown if an I/O error occurs. 818 * @since 1.11 819 */ 820 public byte[] hmac(final InputStream valueToDigest) throws IOException { 821 final byte[] buffer = new byte[STREAM_BUFFER_LENGTH]; 822 int read; 823 while ((read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH)) > -1) { 824 mac.update(buffer, 0, read); 825 } 826 return mac.doFinal(); 827 } 828 829 /** 830 * Returns the digest for the file. 831 * 832 * @param valueToDigest The path to use. 833 * @return The digest. 834 * @throws IOException Thrown if an I/O error occurs. 835 * @since 1.19.0 836 */ 837 public byte[] hmac(final Path valueToDigest) throws IOException { 838 try (BufferedInputStream stream = new BufferedInputStream(Files.newInputStream(valueToDigest))) { 839 return hmac(stream); 840 } 841 } 842 843 /** 844 * Returns the digest for the input data. 845 * 846 * @param valueToDigest The input to use, treated as UTF-8. 847 * @return The digest as a byte[]. 848 * @since 1.11 849 */ 850 public byte[] hmac(final String valueToDigest) { 851 return mac.doFinal(StringUtils.getBytesUtf8(valueToDigest)); 852 } 853 854 /** 855 * Returns the digest for the input data. 856 * 857 * @param valueToDigest The input to use. 858 * @return The digest as a hexadecimal String. 859 * @since 1.11 860 */ 861 public String hmacHex(final byte[] valueToDigest) { 862 return Hex.encodeHexString(hmac(valueToDigest)); 863 } 864 865 /** 866 * Returns the digest for the input data. 867 * 868 * @param valueToDigest The input to use. 869 * @return The digest as a hexadecimal String. 870 * @since 1.11 871 */ 872 public String hmacHex(final ByteBuffer valueToDigest) { 873 return Hex.encodeHexString(hmac(valueToDigest)); 874 } 875 876 /** 877 * Returns the digest for the file. 878 * 879 * @param valueToDigest The file to use. 880 * @return The digest as a hexadecimal String. 881 * @throws IOException Thrown if an I/O error occurs. 882 * @since 1.11 883 */ 884 public String hmacHex(final File valueToDigest) throws IOException { 885 return Hex.encodeHexString(hmac(valueToDigest)); 886 } 887 888 /** 889 * Returns the digest for the stream. 890 * 891 * @param valueToDigest The data to use. 892 * The InputStream must not be null and will not be closed. 893 * @return The digest as a hexadecimal String. 894 * @throws IOException Thrown if an I/O error occurs. 895 * @since 1.11 896 */ 897 public String hmacHex(final InputStream valueToDigest) throws IOException { 898 return Hex.encodeHexString(hmac(valueToDigest)); 899 } 900 901 /** 902 * Returns the digest for the path. 903 * 904 * @param valueToDigest The path to use. 905 * @return The digest as a hexadecimal String. 906 * @throws IOException Thrown if an I/O error occurs. 907 * @since 1.19.0 908 */ 909 public String hmacHex(final Path valueToDigest) throws IOException { 910 return Hex.encodeHexString(hmac(valueToDigest)); 911 } 912 913 /** 914 * Returns the digest for the input data. 915 * 916 * @param valueToDigest The input to use, treated as UTF-8. 917 * @return The digest as a hexadecimal String. 918 * @since 1.11 919 */ 920 public String hmacHex(final String valueToDigest) { 921 return Hex.encodeHexString(hmac(valueToDigest)); 922 } 923}