001package com.nimbusds.jose.crypto;
002
003
004import java.security.interfaces.RSAPublicKey;
005import javax.crypto.SecretKey;
006
007import net.jcip.annotations.ThreadSafe;
008
009import com.nimbusds.jose.EncryptionMethod;
010import com.nimbusds.jose.JOSEException;
011import com.nimbusds.jose.JWEAlgorithm;
012import com.nimbusds.jose.JWECryptoParts;
013import com.nimbusds.jose.JWEEncrypter;
014import com.nimbusds.jose.JWEHeader;
015import com.nimbusds.jose.jwk.RSAKey;
016import com.nimbusds.jose.util.Base64URL;
017
018
019/**
020 * RSA encrypter of {@link com.nimbusds.jose.JWEObject JWE objects}. This class
021 * is thread-safe.
022 *
023 * <p>Supports the following key management algorithms:
024 *
025 * <ul>
026 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA1_5}
027 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP}
028 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP_256}
029 * </ul>
030 *
031 * <p>Supports the following content encryption algorithms:
032 *
033 * <ul>
034 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256}
035 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384}
036 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512}
037 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM}
038 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM}
039 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM}
040 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED}
041 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED}
042 * </ul>
043 *
044 * @author David Ortiz
045 * @author Vladimir Dzhuvinov
046 * @version 2015-06-08
047 */
048@ThreadSafe
049public class RSAEncrypter extends RSACryptoProvider implements JWEEncrypter {
050
051
052        /**
053         * The public RSA key.
054         */
055        private final RSAPublicKey publicKey;
056
057
058        /**
059         * Creates a new RSA encrypter.
060         *
061         * @param publicKey The public RSA key. Must not be {@code null}.
062         */
063        public RSAEncrypter(final RSAPublicKey publicKey) {
064
065                if (publicKey == null) {
066                        throw new IllegalArgumentException("The public RSA key must not be null");
067                }
068
069                this.publicKey = publicKey;
070        }
071
072
073        /**
074         * Creates a new RSA encrypter.
075         *
076         *  @param rsaJWK The RSA JSON Web Key (JWK). Must not be {@code null}.
077         *
078         * @throws JOSEException If the RSA JWK extraction failed.
079         */
080        public RSAEncrypter(final RSAKey rsaJWK)
081                throws JOSEException {
082
083                this(rsaJWK.toRSAPublicKey());
084        }
085
086
087        /**
088         * Gets the public RSA key.
089         *
090         * @return The public RSA key.
091         */
092        public RSAPublicKey getPublicKey() {
093
094                return publicKey;
095        }
096
097
098        @Override
099        public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText)
100                throws JOSEException {
101
102                final JWEAlgorithm alg = header.getAlgorithm();
103                final EncryptionMethod enc = header.getEncryptionMethod();
104
105                // Generate and encrypt the CEK according to the enc method
106                final SecretKey cek = ContentCryptoProvider.generateCEK(enc, getJCAContext().getSecureRandom());
107
108                final Base64URL encryptedKey; // The second JWE part
109
110                if (alg.equals(JWEAlgorithm.RSA1_5)) {
111
112                        encryptedKey = Base64URL.encode(RSA1_5.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider()));
113
114                } else if (alg.equals(JWEAlgorithm.RSA_OAEP)) {
115
116                        encryptedKey = Base64URL.encode(RSA_OAEP.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider()));
117
118                } else if (alg.equals(JWEAlgorithm.RSA_OAEP_256)) {
119                        
120                        encryptedKey = Base64URL.encode(RSA_OAEP_256.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider()));
121                        
122                } else {
123
124                        throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS));
125                }
126
127                return ContentCryptoProvider.encrypt(header, clearText, cek, encryptedKey, getJCAContext());
128        }
129}