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