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