001 package com.nimbusds.jose.crypto;
002
003
004 import java.util.HashSet;
005 import java.util.Set;
006
007 import java.security.InvalidKeyException;
008
009 import javax.crypto.Mac;
010
011 import javax.crypto.spec.SecretKeySpec;
012
013 import net.jcip.annotations.ThreadSafe;
014
015 import com.nimbusds.jose.JOSEException;
016 import com.nimbusds.jose.JWSHeaderFilter;
017 import com.nimbusds.jose.JWSVerifier;
018 import com.nimbusds.jose.ReadOnlyJWSHeader;
019
020 import com.nimbusds.jose.util.Base64URL;
021
022
023
024 /**
025 * Message Authentication Code (MAC) verifier of
026 * {@link com.nimbusds.jose.JWSObject JWS objects}. This class is thread-safe.
027 *
028 * <p>Supports the following JSON Web Algorithms (JWAs):
029 *
030 * <ul>
031 * <li>{@link com.nimbusds.jose.JWSAlgorithm#HS256}
032 * <li>{@link com.nimbusds.jose.JWSAlgorithm#HS384}
033 * <li>{@link com.nimbusds.jose.JWSAlgorithm#HS512}
034 * </ul>
035 *
036 * <p>Accepts the following JWS header parameters:
037 *
038 * <ul>
039 * <li>{@code alg}
040 * <li>{@code typ}
041 * <li>{@code cty}
042 * </ul>
043 *
044 * @author Vladimir Dzhuvinov
045 * @version $version$ (2012-10-23)
046 */
047 @ThreadSafe
048 public class MACVerifier extends MACProvider implements JWSVerifier {
049
050
051 /**
052 * The accepted JWS header parameters.
053 */
054 private static final Set<String> ACCEPTED_HEADER_PARAMETERS;
055
056
057 /**
058 * Initialises the accepted JWS header parameters.
059 */
060 static {
061
062 Set<String> params = new HashSet<String>();
063 params.add("alg");
064 params.add("typ");
065 params.add("cty");
066
067 ACCEPTED_HEADER_PARAMETERS = params;
068 }
069
070
071 /**
072 * The JWS header filter.
073 */
074 private DefaultJWSHeaderFilter headerFilter;
075
076
077 /**
078 * Creates a new Message Authentication (MAC) verifier.
079 *
080 * @param sharedSecret The shared secret. Must not be {@code null}.
081 */
082 public MACVerifier(final byte[] sharedSecret) {
083
084 super(sharedSecret);
085
086 headerFilter = new DefaultJWSHeaderFilter(supportedAlgorithms(), ACCEPTED_HEADER_PARAMETERS);
087 }
088
089
090 @Override
091 public JWSHeaderFilter getJWSHeaderFilter() {
092
093 return headerFilter;
094 }
095
096
097 @Override
098 public boolean verify(final ReadOnlyJWSHeader header,
099 final byte[] signedContent,
100 final Base64URL signature)
101 throws JOSEException {
102
103 Mac mac = getMAC(header.getAlgorithm());
104
105 try {
106 mac.init(new SecretKeySpec(getSharedSecret(), mac.getAlgorithm()));
107
108 } catch (InvalidKeyException e) {
109
110 throw new JOSEException("Invalid HMAC key: " + e.getMessage(), e);
111 }
112
113 mac.update(signedContent);
114
115 Base64URL expectedSignature = Base64URL.encode(mac.doFinal());
116
117 if (expectedSignature.equals(signature))
118 return true;
119 else
120 return false;
121 }
122 }