001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2023, Connect2id Ltd. 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; 019 020 021import com.nimbusds.jose.JOSEException; 022import com.nimbusds.jose.JWSHeader; 023import com.nimbusds.jose.JWSSigner; 024import com.nimbusds.jose.KeyLengthException; 025import com.nimbusds.jose.crypto.impl.HMAC; 026import com.nimbusds.jose.crypto.impl.MACProvider; 027import com.nimbusds.jose.jwk.OctetSequenceKey; 028import com.nimbusds.jose.util.Base64URL; 029import com.nimbusds.jose.util.StandardCharset; 030import net.jcip.annotations.ThreadSafe; 031 032import javax.crypto.SecretKey; 033 034 035 036/** 037 * Message Authentication Code (MAC) signer of 038 * {@link com.nimbusds.jose.JWSObject JWS objects}. Expects a secret key. 039 * 040 * <p>See RFC 7518 041 * <a href="https://tools.ietf.org/html/rfc7518#section-3.2">section 3.2</a> 042 * for more information. 043 * 044 * <p>This class is thread-safe. 045 * 046 * <p>Supports the following algorithms: 047 * 048 * <ul> 049 * <li>{@link com.nimbusds.jose.JWSAlgorithm#HS256} 050 * <li>{@link com.nimbusds.jose.JWSAlgorithm#HS384} 051 * <li>{@link com.nimbusds.jose.JWSAlgorithm#HS512} 052 * </ul> 053 * 054 * <p>Tested with the AWS CloudHSM JCE provider. 055 * 056 * @author Vladimir Dzhuvinov 057 * @author Ulrich Winter 058 * @version 2024-10-28 059 */ 060@ThreadSafe 061public class MACSigner extends MACProvider implements JWSSigner { 062 063 064 /** 065 * Creates a new Message Authentication (MAC) signer. 066 * 067 * @param secret The secret. Must be at least 256 bits long and not 068 * {@code null}. 069 * 070 * @throws KeyLengthException If the secret length is shorter than the 071 * minimum 256-bit requirement. 072 */ 073 public MACSigner(final byte[] secret) 074 throws KeyLengthException { 075 076 super(secret); 077 } 078 079 080 /** 081 * Creates a new Message Authentication (MAC) signer. 082 * 083 * @param secretString The secret as a UTF-8 encoded string. Must be at 084 * least 256 bits long and not {@code null}. 085 * 086 * @throws KeyLengthException If the secret length is shorter than the 087 * minimum 256-bit requirement. 088 */ 089 public MACSigner(final String secretString) 090 throws KeyLengthException { 091 092 this(secretString.getBytes(StandardCharset.UTF_8)); 093 } 094 095 096 /** 097 * Creates a new Message Authentication (MAC) signer. 098 * 099 * @param secretKey The secret key. Must be at least 256 bits long and 100 * not {@code null}. 101 * 102 * @throws KeyLengthException If the secret length is shorter than the 103 * minimum 256-bit requirement. 104 */ 105 public MACSigner(final SecretKey secretKey) 106 throws KeyLengthException { 107 108 super(secretKey); 109 } 110 111 112 /** 113 * Creates a new Message Authentication (MAC) signer. 114 * 115 * @param jwk The secret as a JWK. Must be at least 256 bits long and 116 * not {@code null}. 117 * 118 * @throws KeyLengthException If the secret length is shorter than the 119 * minimum 256-bit requirement. 120 */ 121 public MACSigner(final OctetSequenceKey jwk) 122 throws KeyLengthException { 123 124 this(jwk.toByteArray()); 125 } 126 127 128 @Override 129 public Base64URL sign(final JWSHeader header, final byte[] signingInput) 130 throws JOSEException { 131 132 ensureSecretLengthSatisfiesAlgorithm(header.getAlgorithm()); 133 134 String jcaAlg = getJCAAlgorithmName(header.getAlgorithm()); 135 byte[] hmac = HMAC.compute(jcaAlg, getSecretKey(), signingInput, getJCAContext().getProvider()); 136 return Base64URL.encode(hmac); 137 } 138}