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 com.nimbusds.jose.*; 022import com.nimbusds.jose.crypto.impl.*; 023import com.nimbusds.jose.jwk.RSAKey; 024import com.nimbusds.jose.util.Base64URL; 025import net.jcip.annotations.ThreadSafe; 026 027import javax.crypto.SecretKey; 028import java.security.interfaces.RSAPublicKey; 029import java.util.Objects; 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 2024-04-20 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 this.publicKey = Objects.requireNonNull(publicKey); 129 } 130 131 132 /** 133 * Gets the public RSA key. 134 * 135 * @return The public RSA key. 136 */ 137 public RSAPublicKey getPublicKey() { 138 139 return publicKey; 140 } 141 142 143 /** 144 * Encrypts the specified clear text of a {@link JWEObject JWE object}. 145 * 146 * @param header The JSON Web Encryption (JWE) header. Must specify 147 * a supported JWE algorithm and method. Must not be 148 * {@code null}. 149 * @param clearText The clear text to encrypt. Must not be {@code null}. 150 * 151 * @return The resulting JWE crypto parts. 152 * 153 * @throws JOSEException If the JWE algorithm or method is not 154 * supported or if encryption failed for some 155 * other internal reason. 156 */ 157 @Deprecated 158 public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText) 159 throws JOSEException { 160 161 return encrypt(header, clearText, AAD.compute(header)); 162 } 163 164 165 @Override 166 public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText, final byte[] aad) 167 throws JOSEException { 168 169 final JWEAlgorithm alg = JWEHeaderValidation.getAlgorithmAndEnsureNotNull(header); 170 final EncryptionMethod enc = header.getEncryptionMethod(); 171 final SecretKey cek = getCEK(enc); // Generate and encrypt the CEK according to the enc method 172 173 final Base64URL encryptedKey; // The second JWE part 174 175 if (alg.equals(JWEAlgorithm.RSA1_5)) { 176 encryptedKey = Base64URL.encode(RSA1_5.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider())); 177 } else if (alg.equals(JWEAlgorithm.RSA_OAEP)) { 178 encryptedKey = Base64URL.encode(RSA_OAEP.encryptCEK(publicKey, cek, getJCAContext().getKeyEncryptionProvider())); 179 } else if (alg.equals(JWEAlgorithm.RSA_OAEP_256)) { 180 encryptedKey = Base64URL.encode(RSA_OAEP_SHA2.encryptCEK(publicKey, cek, 256, getJCAContext().getKeyEncryptionProvider())); 181 } else if (alg.equals(JWEAlgorithm.RSA_OAEP_384)) { 182 encryptedKey = Base64URL.encode(RSA_OAEP_SHA2.encryptCEK(publicKey, cek, 384, getJCAContext().getKeyEncryptionProvider())); 183 } else if (alg.equals(JWEAlgorithm.RSA_OAEP_512)) { 184 encryptedKey = Base64URL.encode(RSA_OAEP_SHA2.encryptCEK(publicKey, cek, 512, getJCAContext().getKeyEncryptionProvider())); 185 } else { 186 throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS)); 187 } 188 189 return ContentCryptoProvider.encrypt(header, clearText, aad, cek, encryptedKey, getJCAContext()); 190 } 191}