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.interfaces.RSAPublicKey;
022import javax.crypto.SecretKey;
023
024import net.jcip.annotations.ThreadSafe;
025
026import com.nimbusds.jose.EncryptionMethod;
027import com.nimbusds.jose.JOSEException;
028import com.nimbusds.jose.JWEAlgorithm;
029import com.nimbusds.jose.JWECryptoParts;
030import com.nimbusds.jose.JWEEncrypter;
031import com.nimbusds.jose.JWEHeader;
032import com.nimbusds.jose.jwk.RSAKey;
033import com.nimbusds.jose.util.Base64URL;
034
035
036/**
037 * RSA encrypter of {@link com.nimbusds.jose.JWEObject JWE objects}. Expects a
038 * public RSA key.
039 *
040 * <p>Encrypts the plain text with a generated AES key (the Content Encryption
041 * Key) according to the specified JOSE encryption method, then encrypts the
042 * CEK with the public RSA key and returns it alongside the IV, cipher text and
043 * authentication tag. See RFC 7518, sections
044 * <a href="https://tools.ietf.org/html/rfc7518#section-4.2">4.2</a> and
045 * <a href="https://tools.ietf.org/html/rfc7518#section-4.3">4.3</a> for more
046 * information.
047 *
048 * <p>This class is thread-safe.
049 *
050 * <p>Supports the following key management algorithms:
051 *
052 * <ul>
053 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP_256}
054 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP} (deprecated)
055 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA1_5} (deprecated)
056 * </ul>
057 *
058 * <p>Supports the following content encryption algorithms:
059 *
060 * <ul>
061 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256}
062 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384}
063 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512}
064 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM}
065 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM}
066 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM}
067 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED}
068 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED}
069 * </ul>
070 *
071 * @author David Ortiz
072 * @author Vladimir Dzhuvinov
073 * @version 2015-06-08
074 */
075@ThreadSafe
076public class RSAEncrypter extends RSACryptoProvider implements JWEEncrypter {
077
078
079        /**
080         * The public RSA key.
081         */
082        private final RSAPublicKey publicKey;
083
084
085        /**
086         * Creates a new RSA encrypter.
087         *
088         * @param publicKey The public RSA key. Must not be {@code null}.
089         */
090        public RSAEncrypter(final RSAPublicKey publicKey) {
091
092                if (publicKey == null) {
093                        throw new IllegalArgumentException("The public RSA key must not be null");
094                }
095
096                this.publicKey = publicKey;
097        }
098
099
100        /**
101         * Creates a new RSA encrypter.
102         *
103         *  @param rsaJWK The RSA JSON Web Key (JWK). Must not be {@code null}.
104         *
105         * @throws JOSEException If the RSA JWK extraction failed.
106         */
107        public RSAEncrypter(final RSAKey rsaJWK)
108                throws JOSEException {
109
110                this(rsaJWK.toRSAPublicKey());
111        }
112
113
114        /**
115         * Gets the public RSA key.
116         *
117         * @return The public RSA key.
118         */
119        public RSAPublicKey getPublicKey() {
120
121                return publicKey;
122        }
123
124
125        @Override
126        public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText)
127                throws JOSEException {
128
129                final JWEAlgorithm alg = header.getAlgorithm();
130                final EncryptionMethod enc = header.getEncryptionMethod();
131
132                // Generate and encrypt the CEK according to the enc method
133                final SecretKey cek = ContentCryptoProvider.generateCEK(enc, getJCAContext().getSecureRandom());
134
135                final Base64URL encryptedKey; // The second JWE part
136
137                if (alg.equals(JWEAlgorithm.RSA1_5)) {
138
139                        encryptedKey = Base64URL.encode(RSA1_5.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider()));
140
141                } else if (alg.equals(JWEAlgorithm.RSA_OAEP)) {
142
143                        encryptedKey = Base64URL.encode(RSA_OAEP.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider()));
144
145                } else if (alg.equals(JWEAlgorithm.RSA_OAEP_256)) {
146                        
147                        encryptedKey = Base64URL.encode(RSA_OAEP_256.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider()));
148                        
149                } else {
150
151                        throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS));
152                }
153
154                return ContentCryptoProvider.encrypt(header, clearText, cek, encryptedKey, getJCAContext());
155        }
156}