001 package com.nimbusds.jose.crypto;
002
003
004 import java.util.HashSet;
005 import java.util.Set;
006
007 import java.security.Signature;
008 import java.security.InvalidKeyException;
009 import java.security.SignatureException;
010
011 import java.security.interfaces.RSAPublicKey;
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 * RSA Signature-Scheme-with-Appendix (RSASSA) 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#RS256}
032 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS384}
033 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS512}
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 RSASSAVerifier extends RSASSAProvider 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 * The public RSA key.
079 */
080 private final RSAPublicKey publicKey;
081
082
083 /**
084 * Creates a new RSA Signature-Scheme-with-Appendix (RSASSA) verifier.
085 *
086 * @param publicKey The public RSA key. Must not be {@code null}.
087 */
088 public RSASSAVerifier(final RSAPublicKey publicKey) {
089
090 if (publicKey == null)
091 throw new IllegalArgumentException("The public RSA key must not be null");
092
093 this.publicKey = publicKey;
094
095 headerFilter = new DefaultJWSHeaderFilter(supportedAlgorithms(), ACCEPTED_HEADER_PARAMETERS);
096 }
097
098
099 /**
100 * Gets the public RSA key.
101 *
102 * @return The public RSA key.
103 */
104 public RSAPublicKey getPublicKey() {
105
106 return publicKey;
107 }
108
109
110 @Override
111 public JWSHeaderFilter getJWSHeaderFilter() {
112
113 return headerFilter;
114 }
115
116
117 @Override
118 public boolean verify(final ReadOnlyJWSHeader header,
119 final byte[] signedContent,
120 final Base64URL signature)
121 throws JOSEException {
122
123 Signature verifier = getRSASignerAndVerifier(header.getAlgorithm());
124
125 try {
126 verifier.initVerify(publicKey);
127 verifier.update(signedContent);
128 return verifier.verify(signature.decode());
129
130 } catch (InvalidKeyException e) {
131
132 throw new JOSEException("Invalid public RSA key: " + e.getMessage(), e);
133
134 } catch (SignatureException e) {
135
136 throw new JOSEException("RSA signature exception: " + e.getMessage(), e);
137 }
138 }
139 }