001package com.nimbusds.jose.crypto; 002 003 004import java.security.InvalidKeyException; 005import java.security.Signature; 006import java.security.SignatureException; 007import java.security.interfaces.RSAPrivateKey; 008 009import net.jcip.annotations.ThreadSafe; 010 011import com.nimbusds.jose.JOSEException; 012import com.nimbusds.jose.JWSSigner; 013import com.nimbusds.jose.JWSHeader; 014import com.nimbusds.jose.jwk.RSAKey; 015import com.nimbusds.jose.util.Base64URL; 016 017 018 019/** 020 * RSA Signature-Scheme-with-Appendix (RSASSA) signer of 021 * {@link com.nimbusds.jose.JWSObject JWS objects}. This class is thread-safe. 022 * 023 * <p>Supports the following algorithms: 024 * 025 * <ul> 026 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS256} 027 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS384} 028 * <li>{@link com.nimbusds.jose.JWSAlgorithm#RS512} 029 * <li>{@link com.nimbusds.jose.JWSAlgorithm#PS256} 030 * <li>{@link com.nimbusds.jose.JWSAlgorithm#PS384} 031 * <li>{@link com.nimbusds.jose.JWSAlgorithm#PS512} 032 * </ul> 033 * 034 * @author Vladimir Dzhuvinov 035 * @version 2015-06-02 036 */ 037@ThreadSafe 038public class RSASSASigner extends RSASSAProvider implements JWSSigner { 039 040 041 /** 042 * The private RSA key. 043 */ 044 private final RSAPrivateKey privateKey; 045 046 047 /** 048 * Creates a new RSA Signature-Scheme-with-Appendix (RSASSA) signer. 049 * 050 * @param privateKey The private RSA key. Must not be {@code null}. 051 */ 052 public RSASSASigner(final RSAPrivateKey privateKey) { 053 054 if (privateKey == null) { 055 throw new IllegalArgumentException("The private RSA key must not be null"); 056 } 057 058 this.privateKey = privateKey; 059 } 060 061 062 /** 063 * Creates a new RSA Signature-Scheme-with-Appendix (RSASSA) signer. 064 * 065 * @param rsaJWK The RSA JSON Web Key (JWK). Must contain a private 066 * part. Must not be {@code null}. 067 * 068 * @throws JOSEException If the RSA JWK doesn't contain a private part 069 * or its extraction failed. 070 */ 071 public RSASSASigner(final RSAKey rsaJWK) 072 throws JOSEException { 073 074 if (! rsaJWK.isPrivate()) { 075 throw new JOSEException("The RSA JWK doesn't contain a private part"); 076 } 077 078 privateKey = rsaJWK.toRSAPrivateKey(); 079 } 080 081 082 /** 083 * Gets the private RSA key. 084 * 085 * @return The private RSA key. 086 */ 087 public RSAPrivateKey getPrivateKey() { 088 089 return privateKey; 090 } 091 092 093 @Override 094 public Base64URL sign(final JWSHeader header, final byte[] signingInput) 095 throws JOSEException { 096 097 Signature signer = RSASSA.getSignerAndVerifier(header.getAlgorithm(), getJCAContext().getProvider()); 098 099 try { 100 signer.initSign(privateKey); 101 signer.update(signingInput); 102 return Base64URL.encode(signer.sign()); 103 104 } catch (InvalidKeyException e) { 105 throw new JOSEException("Invalid private RSA key: " + e.getMessage(), e); 106 107 } catch (SignatureException e) { 108 throw new JOSEException("RSA signature exception: " + e.getMessage(), e); 109 } 110 } 111}