001    package com.nimbusds.jose.crypto;
002    
003    
004    import java.security.Signature;
005    import java.security.InvalidKeyException;
006    import java.security.SignatureException;
007    
008    import java.security.interfaces.RSAPrivateKey;
009    
010    import net.jcip.annotations.ThreadSafe;
011    
012    import com.nimbusds.jose.JOSEException;
013    import com.nimbusds.jose.JWSSigner;
014    import com.nimbusds.jose.ReadOnlyJWSHeader;
015    
016    import com.nimbusds.jose.util.Base64URL;
017    
018    
019    
020    /**
021     * RSA Signature-Scheme-with-Appendix (RSASSA) signer 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     * </ul>
031     * 
032     * @author Vladimir Dzhuvinov
033     * @version $version$ (2012-10-23)
034     */
035    @ThreadSafe
036    public class RSASSASigner extends RSASSAProvider implements JWSSigner {
037    
038    
039            /**
040             * The private RSA key.
041             */
042            private final RSAPrivateKey privateKey;
043            
044            
045            /**
046             * Creates a new RSA Signature-Scheme-with-Appendix (RSASSA) signer.
047             *
048             * @param privateKey The private RSA key. Must not be {@code null}.
049             */
050            public RSASSASigner(final RSAPrivateKey privateKey) {
051    
052                    if (privateKey == null)
053                            throw new IllegalArgumentException("The private RSA key must not be null");
054                    
055                    this.privateKey = privateKey;
056            }
057            
058            
059            /**
060             * Gets the private RSA key.
061             *
062             * @return The private RSA key.
063             */
064            public RSAPrivateKey getPrivateKey() {
065            
066                    return privateKey;
067            }
068    
069    
070            @Override
071            public Base64URL sign(final ReadOnlyJWSHeader header, final byte[] signableContent)
072                    throws JOSEException {
073                    
074                    Signature signer = getRSASignerAndVerifier(header.getAlgorithm());
075                    
076                    try {
077                            signer.initSign(privateKey);
078                            signer.update(signableContent);
079                            return Base64URL.encode(signer.sign());
080                            
081                    } catch (InvalidKeyException e) {
082                    
083                            throw new JOSEException("Invalid private RSA key: " + e.getMessage(), e);
084                            
085                    } catch (SignatureException e) {
086                    
087                            throw new JOSEException("RSA signature exception: " + e.getMessage(), e);
088                    }
089            }
090    }