001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2016, 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 java.util.Set; 022import javax.crypto.SecretKey; 023 024import com.nimbusds.jose.CriticalHeaderParamsAware; 025import com.nimbusds.jose.JOSEException; 026import com.nimbusds.jose.JWSHeader; 027import com.nimbusds.jose.JWSVerifier; 028import com.nimbusds.jose.crypto.impl.CriticalHeaderParamsDeferral; 029import com.nimbusds.jose.crypto.impl.HMAC; 030import com.nimbusds.jose.crypto.impl.MACProvider; 031import com.nimbusds.jose.crypto.utils.ConstantTimeUtils; 032import com.nimbusds.jose.jwk.OctetSequenceKey; 033import com.nimbusds.jose.util.Base64URL; 034import com.nimbusds.jose.util.StandardCharset; 035import net.jcip.annotations.ThreadSafe; 036 037 038/** 039 * Message Authentication Code (MAC) verifier of 040 * {@link com.nimbusds.jose.JWSObject JWS objects}. Expects a secret key. 041 * 042 * <p>See RFC 7518 043 * <a href="https://tools.ietf.org/html/rfc7518#section-3.2">section 3.2</a> 044 * for more information. 045 * 046 * <p>This class is thread-safe. 047 * 048 * <p>Supports the following algorithms: 049 * 050 * <ul> 051 * <li>{@link com.nimbusds.jose.JWSAlgorithm#HS256} 052 * <li>{@link com.nimbusds.jose.JWSAlgorithm#HS384} 053 * <li>{@link com.nimbusds.jose.JWSAlgorithm#HS512} 054 * </ul> 055 * 056 * @author Vladimir Dzhuvinov 057 * @version 2016-06-26 058 */ 059@ThreadSafe 060public class MACVerifier extends MACProvider implements JWSVerifier, CriticalHeaderParamsAware { 061 062 063 /** 064 * The critical header policy. 065 */ 066 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 067 068 069 /** 070 * Creates a new Message Authentication (MAC) verifier. 071 * 072 * @param secret The secret. Must be at least 256 bits long and not 073 * {@code null}. 074 * 075 * @throws JOSEException If the secret length is shorter than the 076 * minimum 256-bit requirement. 077 */ 078 public MACVerifier(final byte[] secret) 079 throws JOSEException { 080 081 this(secret, null); 082 } 083 084 085 /** 086 * Creates a new Message Authentication (MAC) verifier. 087 * 088 * @param secretString The secret as a UTF-8 encoded string. Must be at 089 * least 256 bits long and not {@code null}. 090 * 091 * @throws JOSEException If the secret length is shorter than the 092 * minimum 256-bit requirement. 093 */ 094 public MACVerifier(final String secretString) 095 throws JOSEException { 096 097 this(secretString.getBytes(StandardCharset.UTF_8)); 098 } 099 100 101 /** 102 * Creates a new Message Authentication (MAC) verifier. 103 * 104 * @param secretKey The secret key. Must be at least 256 bits long and 105 * not {@code null}. 106 * 107 * @throws JOSEException If the secret length is shorter than the 108 * minimum 256-bit requirement. 109 */ 110 public MACVerifier(final SecretKey secretKey) 111 throws JOSEException { 112 113 this(secretKey.getEncoded()); 114 } 115 116 117 /** 118 * Creates a new Message Authentication (MAC) verifier. 119 * 120 * @param jwk The secret as a JWK. Must be at least 256 bits long and 121 * not {@code null}. 122 * 123 * @throws JOSEException If the secret length is shorter than the 124 * minimum 256-bit requirement. 125 */ 126 public MACVerifier(final OctetSequenceKey jwk) 127 throws JOSEException { 128 129 this(jwk.toByteArray()); 130 } 131 132 133 /** 134 * Creates a new Message Authentication (MAC) verifier. 135 * 136 * @param jwk The secret as a JWK. Must be at least 256 bits long and 137 * not {@code null}. 138 * @param defCritHeaders The names of the critical header parameters 139 * that are deferred to the application for 140 * processing, empty set or {@code null} if none. 141 * 142 * @throws JOSEException If the secret length is shorter than the 143 * minimum 256-bit requirement. 144 */ 145 public MACVerifier(final OctetSequenceKey jwk, 146 final Set<String> defCritHeaders) 147 throws JOSEException { 148 149 this(jwk.toByteArray(), defCritHeaders); 150 } 151 152 /** 153 * Creates a new Message Authentication (MAC) verifier. 154 * 155 * @param secret The secret. Must be at least 256 bits long 156 * and not {@code null}. 157 * @param defCritHeaders The names of the critical header parameters 158 * that are deferred to the application for 159 * processing, empty set or {@code null} if none. 160 * 161 * @throws JOSEException If the secret length is shorter than the 162 * minimum 256-bit requirement. 163 */ 164 public MACVerifier(final byte[] secret, 165 final Set<String> defCritHeaders) 166 throws JOSEException { 167 168 super(secret, SUPPORTED_ALGORITHMS); 169 170 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 171 } 172 173 174 @Override 175 public Set<String> getProcessedCriticalHeaderParams() { 176 177 return critPolicy.getProcessedCriticalHeaderParams(); 178 } 179 180 181 @Override 182 public Set<String> getDeferredCriticalHeaderParams() { 183 184 return critPolicy.getProcessedCriticalHeaderParams(); 185 } 186 187 188 @Override 189 public boolean verify(final JWSHeader header, 190 final byte[] signedContent, 191 final Base64URL signature) 192 throws JOSEException { 193 194 if (! critPolicy.headerPasses(header)) { 195 return false; 196 } 197 198 String jcaAlg = getJCAAlgorithmName(header.getAlgorithm()); 199 byte[] expectedHMAC = HMAC.compute(jcaAlg, getSecret(), signedContent, getJCAContext().getProvider()); 200 return ConstantTimeUtils.areEqual(expectedHMAC, signature.decode()); 201 } 202}