001package com.nimbusds.jose.crypto; 002 003 004import java.security.InvalidKeyException; 005import java.security.Signature; 006import java.security.SignatureException; 007import java.security.interfaces.RSAPublicKey; 008import java.util.Set; 009 010import net.jcip.annotations.ThreadSafe; 011 012import com.nimbusds.jose.*; 013import com.nimbusds.jose.jwk.RSAKey; 014import com.nimbusds.jose.util.Base64URL; 015 016 017/** 018 * RSA Signature-Scheme-with-Appendix (RSASSA) verifier of 019 * {@link com.nimbusds.jose.JWSObject JWS objects}. This class is thread-safe. 020 * 021 * <p>Supports the following algorithms: 022 * 023 * <ul> 024 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS256} 025 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS384} 026 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS512} 027 * <li>{@link com.nimbusds.jose.JWSAlgorithm#PS256} 028 * <li>{@link com.nimbusds.jose.JWSAlgorithm#PS384} 029 * <li>{@link com.nimbusds.jose.JWSAlgorithm#PS512} 030 * </ul> 031 * 032 * @author Vladimir Dzhuvinov 033 * @version 2015-06-02 034 */ 035@ThreadSafe 036public class RSASSAVerifier extends RSASSAProvider implements JWSVerifier, CriticalHeaderParamsAware { 037 038 039 /** 040 * The critical header policy. 041 */ 042 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 043 044 045 /** 046 * The public RSA key. 047 */ 048 private final RSAPublicKey publicKey; 049 050 051 /** 052 * Creates a new RSA Signature-Scheme-with-Appendix (RSASSA) verifier. 053 * 054 * @param publicKey The public RSA key. Must not be {@code null}. 055 */ 056 public RSASSAVerifier(final RSAPublicKey publicKey) { 057 058 this(publicKey, null); 059 } 060 061 062 /** 063 * Creates a new RSA Signature-Scheme-with-Appendix (RSASSA) verifier. 064 * 065 * @param rsaJWK The RSA JSON Web Key (JWK). Must not be {@code null}. 066 * 067 * @throws JOSEException If the RSA JWK extraction failed. 068 */ 069 public RSASSAVerifier(final RSAKey rsaJWK) 070 throws JOSEException { 071 072 this(rsaJWK.toRSAPublicKey(), null); 073 } 074 075 076 /** 077 * Creates a new RSA Signature-Scheme-with-Appendix (RSASSA) verifier. 078 * 079 * @param publicKey The public RSA key. Must not be {@code null}. 080 * @param defCritHeaders The names of the critical header parameters 081 * that are deferred to the application for 082 * processing, empty set or {@code null} if none. 083 */ 084 public RSASSAVerifier(final RSAPublicKey publicKey, 085 final Set<String> defCritHeaders) { 086 087 if (publicKey == null) { 088 throw new IllegalArgumentException("The public RSA key must not be null"); 089 } 090 091 this.publicKey = publicKey; 092 093 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 094 } 095 096 097 /** 098 * Gets the public RSA key. 099 * 100 * @return The public RSA key. 101 */ 102 public RSAPublicKey getPublicKey() { 103 104 return publicKey; 105 } 106 107 108 @Override 109 public Set<String> getProcessedCriticalHeaderParams() { 110 111 return critPolicy.getProcessedCriticalHeaderParams(); 112 } 113 114 115 @Override 116 public Set<String> getDeferredCriticalHeaderParams() { 117 118 return critPolicy.getProcessedCriticalHeaderParams(); 119 } 120 121 122 @Override 123 public boolean verify(final JWSHeader header, 124 final byte[] signedContent, 125 final Base64URL signature) 126 throws JOSEException { 127 128 if (! critPolicy.headerPasses(header)) { 129 return false; 130 } 131 132 final Signature verifier = RSASSA.getSignerAndVerifier(header.getAlgorithm(), getJCAContext().getProvider()); 133 134 try { 135 verifier.initVerify(publicKey); 136 137 } catch (InvalidKeyException e) { 138 throw new JOSEException("Invalid public RSA key: " + e.getMessage(), e); 139 } 140 141 try { 142 verifier.update(signedContent); 143 return verifier.verify(signature.decode()); 144 145 } catch (SignatureException e) { 146 return false; 147 } 148 } 149}