001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2013-2016 ForgeRock AS. 015 */ 016 017package org.forgerock.json.jose.jwe.handlers.encryption; 018 019import java.security.GeneralSecurityException; 020import java.security.InvalidAlgorithmParameterException; 021import java.security.InvalidKeyException; 022import java.security.Key; 023import java.security.NoSuchAlgorithmException; 024import java.util.logging.Level; 025import java.util.logging.Logger; 026 027import javax.crypto.BadPaddingException; 028import javax.crypto.Cipher; 029import javax.crypto.IllegalBlockSizeException; 030import javax.crypto.NoSuchPaddingException; 031import javax.crypto.spec.IvParameterSpec; 032import javax.crypto.spec.SecretKeySpec; 033 034import org.forgerock.json.jose.exceptions.JweDecryptionException; 035import org.forgerock.json.jose.exceptions.JweEncryptionException; 036 037/** 038 * A base implementation of an EncryptionHandler that provides common encryption and decryption methods for all 039 * concrete EncryptionHandler implementations. 040 * 041 * @since 2.0.0 042 * @deprecated Use {@link ContentEncryptionHandler} instead. 043 */ 044@Deprecated 045public abstract class AbstractEncryptionHandler implements EncryptionHandler { 046 private static final Logger LOGGER = Logger.getLogger(AbstractEncryptionHandler.class.getName()); 047 048 /** 049 * Encrypts the given plaintext using the specified key with the specified encryption algorithm. 050 * 051 * @param algorithm The Java Cryptographic encryption algorithm. 052 * @param key The encryption key. 053 * @param data The data to encrypt. 054 * @return An array of bytes representing the encrypted data. 055 */ 056 protected byte[] encrypt(String algorithm, Key key, byte[] data) { 057 try { 058 Cipher cipher = Cipher.getInstance(algorithm); 059 cipher.init(Cipher.ENCRYPT_MODE, key); 060 return cipher.doFinal(data); 061 } catch (NoSuchAlgorithmException e) { 062 throw new JweEncryptionException("Unsupported Encryption Algorithm, " + algorithm, e); 063 } catch (IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException | BadPaddingException e) { 064 throw new JweEncryptionException(e); 065 } 066 } 067 068 /** 069 * Encrypts the given plaintext using the specified key and initialisation vector with the specified encryption 070 * algorithm. 071 * 072 * @param algorithm The Java Cryptographic encryption algorithm. 073 * @param key The encryption key. 074 * @param initialisationVector The initialisation vector. 075 * @param data The data to encrypt. 076 * @return An array of bytes representing the encrypted data. 077 */ 078 protected byte[] encrypt(String algorithm, Key key, byte[] initialisationVector, byte[] data) { 079 080 try { 081 Cipher cipher = Cipher.getInstance(algorithm); 082 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getEncoded(), key.getAlgorithm()); 083 IvParameterSpec ivParameterSpec = new IvParameterSpec(initialisationVector); 084 cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); 085 return cipher.doFinal(data); 086 } catch (NoSuchAlgorithmException e) { 087 throw new JweEncryptionException("Unsupported Encryption Algorithm, " + algorithm, e); 088 } catch (IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException | BadPaddingException 089 | InvalidAlgorithmParameterException e) { 090 throw new JweEncryptionException(e); 091 } 092 } 093 094 /** 095 * Decrypts the given ciphertext using the private key and with the same encryption algorithm that was used in the 096 * encryption. 097 * 098 * @param algorithm The Java Cryptographic encryption algorithm. 099 * @param privateKey The private key pair to the public key used in the encryption. 100 * @param data The ciphertext to decrypt. 101 * @return An array of bytes representing the decrypted data. 102 */ 103 public byte[] decrypt(String algorithm, Key privateKey, byte[] data) { 104 105 try { 106 Cipher cipher = Cipher.getInstance(algorithm); 107 cipher.init(Cipher.DECRYPT_MODE, privateKey); 108 return cipher.doFinal(data); 109 } catch (GeneralSecurityException e) { 110 logDecryptionFailure(e); 111 throw new JweDecryptionException(); 112 } 113 } 114 115 /** 116 * Decrypts the given ciphertext using the private key and initialisation vector with the same encryption algorithm 117 * that was used in the encryption. 118 * 119 * @param algorithm The Java Cryptographic encryption algorithm. 120 * @param key The private key pair to the public key used in the encryption. 121 * @param initialisationVector The same initialisation vector that was used in the encryption. 122 * @param data The ciphertext to decrypt. 123 * @return An array of bytes representing the decrypted data. 124 */ 125 protected byte[] decrypt(String algorithm, Key key, byte[] initialisationVector, byte[] data) { 126 127 try { 128 Cipher cipher = Cipher.getInstance(algorithm); 129 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getEncoded(), key.getAlgorithm()); 130 IvParameterSpec ivParameterSpec = new IvParameterSpec(initialisationVector); 131 cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); 132 return cipher.doFinal(data); 133 } catch (GeneralSecurityException e) { 134 logDecryptionFailure(e); 135 throw new JweDecryptionException(); 136 } 137 } 138 139 /** 140 * Log the root cause of any decryption error before throwing a generic exception. 141 */ 142 private void logDecryptionFailure(Throwable cause) { 143 if (LOGGER.isLoggable(Level.FINE)) { 144 LOGGER.log(Level.FINE, "Decryption failed: " + cause, cause); 145 } 146 } 147}