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.HashSet; 009import java.util.Set; 010 011import net.jcip.annotations.ThreadSafe; 012 013import com.nimbusds.jose.JOSEException; 014import com.nimbusds.jose.JWSAlgorithm; 015import com.nimbusds.jose.JWSVerifier; 016import com.nimbusds.jose.JWSHeader; 017import com.nimbusds.jose.util.Base64URL; 018 019 020/** 021 * RSA Signature-Scheme-with-Appendix (RSASSA) verifier of 022 * {@link com.nimbusds.jose.JWSObject JWS objects}. This class is thread-safe. 023 * 024 * <p>Supports the following JSON Web Algorithms (JWAs): 025 * 026 * <ul> 027 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS256} 028 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS384} 029 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS512} 030 * <li>{@link com.nimbusds.jose.JWSAlgorithm#PS256} 031 * <li>{@link com.nimbusds.jose.JWSAlgorithm#PS384} 032 * <li>{@link com.nimbusds.jose.JWSAlgorithm#PS512} 033 * </ul> 034 * 035 * <p>Accepts all {@link com.nimbusds.jose.JWSHeader#getRegisteredParameterNames 036 * registered JWS header parameters}. Use {@link #setAcceptedAlgorithms} to 037 * restrict the acceptable JWS algorithms. 038 * 039 * @author Vladimir Dzhuvinov 040 * @version $version$ (2014-04-22) 041 */ 042@ThreadSafe 043public class RSASSAVerifier extends RSASSAProvider implements JWSVerifier { 044 045 046 /** 047 * The accepted JWS algorithms. 048 */ 049 private Set<JWSAlgorithm> acceptedAlgs = 050 new HashSet<>(supportedAlgorithms()); 051 052 053 /** 054 * The critical header parameter checker. 055 */ 056 private final CriticalHeaderParameterChecker critParamChecker = 057 new CriticalHeaderParameterChecker(); 058 059 060 /** 061 * The public RSA key. 062 */ 063 private final RSAPublicKey publicKey; 064 065 066 /** 067 * Creates a new RSA Signature-Scheme-with-Appendix (RSASSA) verifier. 068 * 069 * @param publicKey The public RSA key. Must not be {@code null}. 070 */ 071 public RSASSAVerifier(final RSAPublicKey publicKey) { 072 073 if (publicKey == null) { 074 075 throw new IllegalArgumentException("The public RSA key must not be null"); 076 } 077 078 this.publicKey = publicKey; 079 } 080 081 082 /** 083 * Gets the public RSA key. 084 * 085 * @return The public RSA key. 086 */ 087 public RSAPublicKey getPublicKey() { 088 089 return publicKey; 090 } 091 092 093 @Override 094 public Set<JWSAlgorithm> getAcceptedAlgorithms() { 095 096 return acceptedAlgs; 097 } 098 099 100 @Override 101 public void setAcceptedAlgorithms(final Set<JWSAlgorithm> acceptedAlgs) { 102 103 if (acceptedAlgs == null) { 104 throw new IllegalArgumentException("The accepted JWS algorithms must not be null"); 105 } 106 107 if (! supportedAlgorithms().containsAll(acceptedAlgs)) { 108 throw new IllegalArgumentException("Unsupported JWS algorithm(s)"); 109 } 110 111 this.acceptedAlgs = acceptedAlgs; 112 } 113 114 115 @Override 116 public Set<String> getIgnoredCriticalHeaderParameters() { 117 118 return critParamChecker.getIgnoredCriticalHeaders(); 119 } 120 121 122 @Override 123 public void setIgnoredCriticalHeaderParameters(final Set<String> headers) { 124 125 critParamChecker.setIgnoredCriticalHeaders(headers); 126 } 127 128 129 @Override 130 public boolean verify(final JWSHeader header, 131 final byte[] signedContent, 132 final Base64URL signature) 133 throws JOSEException { 134 135 if (! critParamChecker.headerPasses(header)) { 136 return false; 137 } 138 139 Signature verifier = getRSASignerAndVerifier(header.getAlgorithm(), provider); 140 141 try { 142 verifier.initVerify(publicKey); 143 144 } catch (InvalidKeyException e) { 145 146 throw new JOSEException("Invalid public RSA key: " + e.getMessage(), e); 147 } 148 149 try { 150 verifier.update(signedContent); 151 return verifier.verify(signature.decode()); 152 153 } catch (SignatureException e) { 154 155 return false; 156 } 157 } 158}