001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2023, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.jose.crypto.impl; 019 020 021import com.nimbusds.jose.JOSEException; 022import net.jcip.annotations.ThreadSafe; 023 024import javax.crypto.Mac; 025import javax.crypto.SecretKey; 026import javax.crypto.spec.SecretKeySpec; 027import java.security.InvalidKeyException; 028import java.security.NoSuchAlgorithmException; 029import java.security.Provider; 030 031 032/** 033 * Static methods for Hash-based Message Authentication Codes (HMAC). This 034 * class is thread-safe. 035 * 036 * @author Axel Nennker 037 * @author Vladimir Dzhuvinov 038 * @author Ulrich Winter 039 * @version 2023-09-14 040 */ 041@ThreadSafe 042public class HMAC { 043 044 045 /** 046 * Gets an initialised Message Authentication Code (MAC) service 047 * instance. 048 * 049 * @param secretKey The secret key, with the appropriate HMAC 050 * algorithm. Must not be {@code null}. 051 * @param provider The JCA provider, {@code null} to use the default. 052 * 053 * @return The MAC service instance. 054 * 055 * @throws JOSEException If the algorithm is not supported or the 056 * MAC secret key is invalid. 057 */ 058 public static Mac getInitMac(final SecretKey secretKey, final Provider provider) 059 throws JOSEException { 060 061 return getInitMac(secretKey.getAlgorithm(), secretKey, provider); 062 } 063 064 065 /** 066 * Gets an initialised Message Authentication Code (MAC) service 067 * instance. 068 * 069 * @param alg The Java Cryptography Architecture (JCA) HMAC 070 * algorithm name. Must not be {@code null}. 071 * @param secretKey The secret key. Its algorithm name is ignored. 072 * Must not be {@code null}. 073 * @param provider The JCA provider, {@code null} to use the default. 074 * 075 * @return The MAC service instance. 076 * 077 * @throws JOSEException If the algorithm is not supported or the 078 * MAC secret key is invalid. 079 */ 080 public static Mac getInitMac(final String alg, 081 final SecretKey secretKey, 082 final Provider provider) 083 throws JOSEException { 084 085 Mac mac; 086 try { 087 if (provider != null) { 088 mac = Mac.getInstance(alg, provider); 089 } else { 090 mac = Mac.getInstance(alg); 091 } 092 093 mac.init(secretKey); 094 095 } catch (NoSuchAlgorithmException e) { 096 throw new JOSEException("Unsupported HMAC algorithm: " + e.getMessage(), e); 097 } catch (InvalidKeyException e) { 098 throw new JOSEException("Invalid HMAC key: " + e.getMessage(), e); 099 } 100 101 return mac; 102 } 103 104 105 /** 106 * Computes a Hash-based Message Authentication Code (HMAC) for the 107 * specified secret and message. 108 * 109 * @param alg The Java Cryptography Architecture (JCA) HMAC 110 * algorithm name. Must not be {@code null}. 111 * @param secret The secret. Must not be {@code null}. 112 * @param message The message. Must not be {@code null}. 113 * @param provider The JCA provider, {@code null} to use the default. 114 * 115 * @return The computed HMAC. 116 * 117 * @throws JOSEException If the algorithm is not supported or the 118 * MAC secret key is invalid. 119 */ 120 @Deprecated 121 public static byte[] compute(final String alg, 122 final byte[] secret, 123 final byte[] message, 124 final Provider provider) 125 throws JOSEException { 126 127 return compute(alg, new SecretKeySpec(secret, alg), message, provider); 128 } 129 130 131 /** 132 * Computes a Hash-based Message Authentication Code (HMAC) for the 133 * specified secret key and message. 134 * 135 * @param alg The Java Cryptography Architecture (JCA) HMAC 136 * algorithm name. Must not be {@code null}. 137 * @param secretKey The secret key. Its algorithm name is ignored. 138 * Must not be {@code null}. 139 * @param message The message. Must not be {@code null}. 140 * @param provider The JCA provider, {@code null} to use the default. 141 * 142 * @return The computed HMAC. 143 * 144 * @throws JOSEException If the algorithm is not supported or the MAC 145 * secret key is invalid. 146 */ 147 public static byte[] compute(final String alg, 148 final SecretKey secretKey, 149 final byte[] message, 150 final Provider provider) 151 throws JOSEException { 152 153 Mac mac = getInitMac(alg, secretKey, provider); 154 mac.update(message); 155 return mac.doFinal(); 156 } 157 158 /** 159 * Computes a Hash-based Message Authentication Code (HMAC) for the 160 * specified secret key and message. 161 * 162 * @param secretKey The secret key, with the appropriate HMAC 163 * algorithm. Must not be {@code null}. 164 * @param message The message. Must not be {@code null}. 165 * @param provider The JCA provider, or {@code null} to use the 166 * default one. 167 * 168 * @return A MAC service instance. 169 * 170 * @throws JOSEException If the algorithm is not supported or the MAC 171 * secret key is invalid. 172 */ 173 public static byte[] compute(final SecretKey secretKey, 174 final byte[] message, 175 final Provider provider) 176 throws JOSEException { 177 178 return compute(secretKey.getAlgorithm(), secretKey, message, provider); 179 } 180}