001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2016, Connect2id Ltd and contributors. 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.impl; 019 020 021import com.nimbusds.jose.JOSEException; 022import com.nimbusds.jose.crypto.opts.CipherMode; 023import net.jcip.annotations.ThreadSafe; 024 025import javax.crypto.Cipher; 026import javax.crypto.SecretKey; 027import javax.crypto.spec.SecretKeySpec; 028import java.security.InvalidKeyException; 029import java.security.PrivateKey; 030import java.security.Provider; 031import java.security.SecureRandom; 032import java.security.interfaces.RSAPublicKey; 033 034 035/** 036 * RSAES OAEP methods for Content Encryption Key (CEK) encryption and 037 * decryption. Uses the BouncyCastle.org provider. This class is thread-safe 038 * 039 * @author Vladimir Dzhuvinov 040 * @version 2025-07-19 041 */ 042@ThreadSafe 043public class RSA_OAEP { 044 045 046 /** 047 * The JCA algorithm name for RSA-OAEP. 048 */ 049 private static final String RSA_OEAP_JCA_ALG = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"; 050 051 052 /** 053 * Encrypts the specified Content Encryption Key (CEK). 054 * 055 * @param pub The public RSA key. Must not be {@code null}. 056 * @param cek The Content Encryption Key (CEK) to encrypt. Must 057 * not be {@code null}. 058 * @param mode The cipher mode to use. Must not be {@code null}. 059 * @param provider The JCA provider, {@code null} to use the default. 060 * 061 * @return The encrypted Content Encryption Key (CEK). 062 * 063 * @throws JOSEException If encryption failed. 064 */ 065 public static byte[] encryptCEK(final RSAPublicKey pub, final SecretKey cek, final CipherMode mode, final Provider provider) 066 throws JOSEException { 067 068 assert mode == CipherMode.WRAP_UNWRAP || mode == CipherMode.ENCRYPT_DECRYPT; 069 070 try { 071 Cipher cipher = CipherHelper.getInstance(RSA_OEAP_JCA_ALG, provider); 072 cipher.init(mode.getForJWEEncrypter(), pub, new SecureRandom()); 073 if (mode == CipherMode.WRAP_UNWRAP) { 074 return cipher.wrap(cek); 075 } else { 076 // CipherMode.ENCRYPT_DECRYPT 077 return cipher.doFinal(cek.getEncoded()); 078 } 079 080 } catch (InvalidKeyException e) { 081 throw new JOSEException("RSA block size exception: The RSA key is too short, try a longer one", e); 082 } catch (Exception e) { 083 // java.security.NoSuchAlgorithmException 084 // java.security.NoSuchPaddingException 085 // java.security.InvalidKeyException 086 // javax.crypto.BadPaddingException 087 throw new JOSEException(e.getMessage(), e); 088 } 089 } 090 091 092 /** 093 * Decrypts the specified encrypted Content Encryption Key (CEK). 094 * 095 * @param priv The private RSA key. Must not be {@code null}. 096 * @param encryptedCEK The encrypted Content Encryption Key (CEK) to 097 * decrypt. Must not be {@code null}. 098 * @param mode The cipher mode to use. Must not be 099 * {@code null}. 100 * @param provider The JCA provider, {@code null} to use the 101 * default. 102 * 103 * @return The decrypted Content Encryption Key (CEK). 104 * 105 * @throws JOSEException If decryption failed. 106 */ 107 public static SecretKey decryptCEK(final PrivateKey priv, final byte[] encryptedCEK, final CipherMode mode, final Provider provider) 108 throws JOSEException { 109 110 assert mode == CipherMode.WRAP_UNWRAP || mode == CipherMode.ENCRYPT_DECRYPT; 111 112 try { 113 Cipher cipher = CipherHelper.getInstance(RSA_OEAP_JCA_ALG, provider); 114 cipher.init(mode.getForJWEDecrypter(), priv); 115 116 if (mode == CipherMode.WRAP_UNWRAP) { 117 return (SecretKey) cipher.unwrap(encryptedCEK, "AES", Cipher.SECRET_KEY); 118 } else { 119 // CipherMode.ENCRYPT_DECRYPT 120 return new SecretKeySpec(cipher.doFinal(encryptedCEK), "AES"); 121 } 122 123 } catch (Exception e) { 124 // java.security.NoSuchAlgorithmException 125 // java.security.NoSuchPaddingException 126 // java.security.InvalidKeyException 127 // javax.crypto.IllegalBlockSizeException 128 // javax.crypto.BadPaddingException 129 throw new JOSEException(e.getMessage(), e); 130 } 131 } 132 133 134 /** 135 * Prevents public instantiation. 136 */ 137 private RSA_OAEP() { } 138}