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 java.security.AlgorithmParameters; 022import java.security.PrivateKey; 023import java.security.Provider; 024import java.security.interfaces.RSAPublicKey; 025import java.security.spec.AlgorithmParameterSpec; 026import java.security.spec.MGF1ParameterSpec; 027import javax.crypto.Cipher; 028import javax.crypto.IllegalBlockSizeException; 029import javax.crypto.SecretKey; 030import javax.crypto.spec.OAEPParameterSpec; 031import javax.crypto.spec.PSource; 032import javax.crypto.spec.SecretKeySpec; 033 034import com.nimbusds.jose.JOSEException; 035import net.jcip.annotations.ThreadSafe; 036 037 038/** 039 * RSAES OAEP (SHA-256) methods for Content Encryption Key (CEK) encryption and 040 * decryption. Uses the BouncyCastle.org provider. This class is thread-safe 041 * 042 * @author Vladimir Dzhuvinov 043 * @author Justin Richer 044 * @version 2017-11-27 045 */ 046@ThreadSafe 047public class RSA_OAEP_256 { 048 049 050 /** 051 * The JCA algorithm name for RSA-OAEP-256. 052 */ 053 private static final String RSA_OEAP_256_JCA_ALG = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"; 054 055 056 /** 057 * Encrypts the specified Content Encryption Key (CEK). 058 * 059 * @param pub The public RSA key. Must not be {@code null}. 060 * @param cek The Content Encryption Key (CEK) to encrypt. Must 061 * not be {@code null}. 062 * @param provider The JCA provider, or {@code null} to use the default 063 * one. 064 * 065 * @return The encrypted Content Encryption Key (CEK). 066 * 067 * @throws JOSEException If encryption failed. 068 */ 069 public static byte[] encryptCEK(final RSAPublicKey pub, final SecretKey cek, final Provider provider) 070 throws JOSEException { 071 072 try { 073 AlgorithmParameters algp = AlgorithmParametersHelper.getInstance("OAEP", provider); 074 AlgorithmParameterSpec paramSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); 075 algp.init(paramSpec); 076 Cipher cipher = CipherHelper.getInstance(RSA_OEAP_256_JCA_ALG, provider); 077 cipher.init(Cipher.ENCRYPT_MODE, pub, algp); 078 return cipher.doFinal(cek.getEncoded()); 079 080 } catch (IllegalBlockSizeException 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 provider The JCA provider, or {@code null} to use the 099 * default one. 100 * 101 * @return The decrypted Content Encryption Key (CEK). 102 * 103 * @throws JOSEException If decryption failed. 104 */ 105 public static SecretKey decryptCEK(final PrivateKey priv, 106 final byte[] encryptedCEK, final Provider provider) 107 throws JOSEException { 108 109 try { 110 AlgorithmParameters algp = AlgorithmParametersHelper.getInstance("OAEP", provider); 111 AlgorithmParameterSpec paramSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); 112 algp.init(paramSpec); 113 Cipher cipher = CipherHelper.getInstance(RSA_OEAP_256_JCA_ALG, provider); 114 cipher.init(Cipher.DECRYPT_MODE, priv, algp); 115 return new SecretKeySpec(cipher.doFinal(encryptedCEK), "AES"); 116 117 } catch (Exception e) { 118 // java.security.NoSuchAlgorithmException 119 // java.security.NoSuchPaddingException 120 // java.security.InvalidKeyException 121 // javax.crypto.IllegalBlockSizeException 122 // javax.crypto.BadPaddingException 123 throw new JOSEException(e.getMessage(), e); 124 } 125 } 126 127 128 /** 129 * Prevents public instantiation. 130 */ 131 private RSA_OAEP_256() { } 132}