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