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}