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 com.nimbusds.jose.*; 025import com.nimbusds.jose.crypto.impl.*; 026import net.jcip.annotations.ThreadSafe; 027 028import com.nimbusds.jose.jwk.RSAKey; 029import com.nimbusds.jose.util.Base64URL; 030 031 032/** 033 * RSA encrypter of {@link com.nimbusds.jose.JWEObject JWE objects}. Expects a 034 * public RSA key. 035 * 036 * <p>Encrypts the plain text with a generated AES key (the Content Encryption 037 * Key) according to the specified JOSE encryption method, then encrypts the 038 * CEK with the public RSA key and returns it alongside the IV, cipher text and 039 * authentication tag. See RFC 7518, sections 040 * <a href="https://tools.ietf.org/html/rfc7518#section-4.2">4.2</a> and 041 * <a href="https://tools.ietf.org/html/rfc7518#section-4.3">4.3</a> for more 042 * information. 043 * 044 * <p>This class is thread-safe. 045 * 046 * <p>Supports the following key management algorithms: 047 * 048 * <ul> 049 * <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP_256} 050 * <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP_384} 051 * <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP_512} 052 * <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP} (deprecated) 053 * <li>{@link com.nimbusds.jose.JWEAlgorithm#RSA1_5} (deprecated) 054 * </ul> 055 * 056 * <p>Supports the following content encryption algorithms: 057 * 058 * <ul> 059 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} 060 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} 061 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} 062 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM} 063 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM} 064 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM} 065 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED} 066 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED} 067 * <li>{@link com.nimbusds.jose.EncryptionMethod#XC20P} 068 * </ul> 069 * 070 * @author David Ortiz 071 * @author Vladimir Dzhuvinov 072 * @author Jun Yu 073 * @author Egor Puzanov 074 * @version 2023-09-10 075 */ 076@ThreadSafe 077public class RSAEncrypter extends RSACryptoProvider implements JWEEncrypter { 078 079 080 /** 081 * The public RSA key. 082 */ 083 private final RSAPublicKey publicKey; 084 085 086 087 /** 088 * Creates a new RSA encrypter. 089 * 090 * @param publicKey The public RSA key. Must not be {@code null}. 091 */ 092 public RSAEncrypter(final RSAPublicKey publicKey) { 093 094 this(publicKey, null); 095 } 096 097 098 /** 099 * Creates a new RSA encrypter. 100 * 101 * @param rsaJWK The RSA JSON Web Key (JWK). Must not be {@code null}. 102 * 103 * @throws JOSEException If the RSA JWK extraction failed. 104 */ 105 public RSAEncrypter(final RSAKey rsaJWK) 106 throws JOSEException { 107 108 this(rsaJWK.toRSAPublicKey()); 109 } 110 111 112 /** 113 * Creates a new RSA encrypter with an optionally specified content 114 * encryption key (CEK). 115 * 116 * @param publicKey The public RSA key. Must not be 117 * {@code null}. 118 * @param contentEncryptionKey The content encryption key (CEK) to use. 119 * If specified its algorithm must be "AES" 120 * or "ChaCha20" and its length must match 121 * the expected for the JWE encryption 122 * method ("enc"). If {@code null} a CEK 123 * will be generated for each JWE. 124 */ 125 public RSAEncrypter(final RSAPublicKey publicKey, final SecretKey contentEncryptionKey) { 126 127 super(contentEncryptionKey); 128 129 if (publicKey == null) { 130 throw new IllegalArgumentException("The public RSA key must not be null"); 131 } 132 this.publicKey = publicKey; 133 } 134 135 136 /** 137 * Gets the public RSA key. 138 * 139 * @return The public RSA key. 140 */ 141 public RSAPublicKey getPublicKey() { 142 143 return publicKey; 144 } 145 146 147 /** 148 * Encrypts the specified clear text of a {@link JWEObject JWE object}. 149 * 150 * @param header The JSON Web Encryption (JWE) header. Must specify 151 * a supported JWE algorithm and method. Must not be 152 * {@code null}. 153 * @param clearText The clear text to encrypt. Must not be {@code null}. 154 * 155 * @return The resulting JWE crypto parts. 156 * 157 * @throws JOSEException If the JWE algorithm or method is not 158 * supported or if encryption failed for some 159 * other internal reason. 160 */ 161 @Deprecated 162 public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText) 163 throws JOSEException { 164 165 return encrypt(header, clearText, AAD.compute(header)); 166 } 167 168 169 @Override 170 public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText, final byte[] aad) 171 throws JOSEException { 172 173 final JWEAlgorithm alg = JWEHeaderValidation.getAlgorithmAndEnsureNotNull(header); 174 final EncryptionMethod enc = header.getEncryptionMethod(); 175 final SecretKey cek = getCEK(enc); // Generate and encrypt the CEK according to the enc method 176 177 final Base64URL encryptedKey; // The second JWE part 178 179 if (alg.equals(JWEAlgorithm.RSA1_5)) { 180 encryptedKey = Base64URL.encode(RSA1_5.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider())); 181 } else if (alg.equals(JWEAlgorithm.RSA_OAEP)) { 182 encryptedKey = Base64URL.encode(RSA_OAEP.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider())); 183 } else if (alg.equals(JWEAlgorithm.RSA_OAEP_256)) { 184 encryptedKey = Base64URL.encode(RSA_OAEP_SHA2.encryptCEK(publicKey, cek, 256, getJCAContext().getKeyEncryptionProvider())); 185 } else if (alg.equals(JWEAlgorithm.RSA_OAEP_384)) { 186 encryptedKey = Base64URL.encode(RSA_OAEP_SHA2.encryptCEK(publicKey, cek, 384, getJCAContext().getKeyEncryptionProvider())); 187 } else if (alg.equals(JWEAlgorithm.RSA_OAEP_512)) { 188 encryptedKey = Base64URL.encode(RSA_OAEP_SHA2.encryptCEK(publicKey, cek, 512, getJCAContext().getKeyEncryptionProvider())); 189 } else { 190 throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS)); 191 } 192 193 return ContentCryptoProvider.encrypt(header, clearText, aad, cek, encryptedKey, getJCAContext()); 194 } 195}