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 * Returns 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 * Returns 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 * 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}