001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2016, 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 java.security.InvalidKeyException;
022import java.security.NoSuchAlgorithmException;
023import java.security.Provider;
024import javax.crypto.Mac;
025import javax.crypto.SecretKey;
026import javax.crypto.spec.SecretKeySpec;
027
028import com.nimbusds.jose.JOSEException;
029import net.jcip.annotations.ThreadSafe;
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 * @version 2015-04-23
039 */
040@ThreadSafe
041public class HMAC {
042
043
044        public static Mac getInitMac(final SecretKey secretKey,
045                                     final Provider provider)
046                throws JOSEException {
047
048                Mac mac;
049
050                try {
051                        if (provider != null) {
052                                mac = Mac.getInstance(secretKey.getAlgorithm(), provider);
053                        } else {
054                                mac = Mac.getInstance(secretKey.getAlgorithm());
055                        }
056
057                        mac.init(secretKey);
058
059                } catch (NoSuchAlgorithmException e) {
060
061                        throw new JOSEException("Unsupported HMAC algorithm: " + e.getMessage(), e);
062
063                } catch (InvalidKeyException e) {
064
065                        throw new JOSEException("Invalid HMAC key: " + e.getMessage(), e);
066                }
067
068                return mac;
069        }
070
071
072        /**
073         * Computes a Hash-based Message Authentication Code (HMAC) for the
074         * specified secret and message.
075         *
076         * @param alg      The Java Cryptography Architecture (JCA) HMAC
077         *                 algorithm name. Must not be {@code null}.
078         * @param secret   The secret. Must not be {@code null}.
079         * @param message  The message. Must not be {@code null}.
080         * @param provider The JCA provider, or {@code null} to use the default
081         *                 one.
082         *
083         * @return A MAC service instance.
084         *
085         * @throws JOSEException If the algorithm is not supported or the
086         *                       MAC secret key is invalid.
087         */
088        public static byte[] compute(final String alg,
089                                     final byte[] secret,
090                                     final byte[] message,
091                                     final Provider provider)
092                throws JOSEException {
093
094                return compute(new SecretKeySpec(secret, alg), message, provider);
095        }
096
097
098        /**
099         * Computes a Hash-based Message Authentication Code (HMAC) for the
100         * specified secret key and message.
101         *
102         * @param secretKey The secret key, with the appropriate HMAC
103         *                  algorithm. Must not be {@code null}.
104         * @param message   The message. Must not be {@code null}.
105         * @param provider  The JCA provider, or {@code null} to use the
106         *                  default one.
107         *
108         * @return A MAC service instance.
109         *
110         * @throws JOSEException If the algorithm is not supported or the MAC 
111         *                       secret key is invalid.
112         */
113        public static byte[] compute(final SecretKey secretKey,
114                                     final byte[] message,
115                                     final Provider provider)
116                throws JOSEException {
117
118                Mac mac = getInitMac(secretKey, provider);
119                mac.update(message);
120                return mac.doFinal();
121        }
122}