All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opensaml.xmlsec.encryption.support.Encrypter Maven / Gradle / Ivy

/*
 * Licensed to the University Corporation for Advanced Internet Development,
 * Inc. (UCAID) under one or more contributor license agreements.  See the
 * NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The UCAID licenses this file to You under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.opensaml.xmlsec.encryption.support;

import java.security.Key;
import java.security.KeyException;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.ECPublicKey;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.crypto.SecretKey;

import net.shibboleth.utilities.java.support.codec.Base64Support;
import net.shibboleth.utilities.java.support.logic.Constraint;

import org.apache.xml.security.Init;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.encryption.XMLEncryptionException;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilderFactory;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.core.xml.io.Marshaller;
import org.opensaml.core.xml.io.MarshallingException;
import org.opensaml.core.xml.io.Unmarshaller;
import org.opensaml.core.xml.io.UnmarshallerFactory;
import org.opensaml.core.xml.io.UnmarshallingException;
import org.opensaml.security.SecurityException;
import org.opensaml.security.credential.CredentialSupport;
import org.opensaml.xmlsec.algorithm.AlgorithmSupport;
import org.opensaml.xmlsec.encryption.EncryptedData;
import org.opensaml.xmlsec.encryption.EncryptedKey;
import org.opensaml.xmlsec.keyinfo.KeyInfoGenerator;
import org.opensaml.xmlsec.signature.KeyInfo;
import org.opensaml.xmlsec.signature.XMLSignatureBuilder;
import org.opensaml.xmlsec.signature.support.SignatureConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.google.common.base.Strings;

/**
 * Supports encryption of XMLObjects, their content and keys, according to the XML Encryption specification, version
 * 20021210.
 * 
 * 

* Various overloaded method variants are supplied for encrypting XMLObjects and their contents (with or without * encryption of the associated data encryption key), as well as for encrypting keys separately. *

* *

* The parameters for data encryption are specified with an instance of {@link DataEncryptionParameters}. The parameters * for key encryption are specified with one or more instances of {@link KeyEncryptionParameters}. *

* *

* The data encryption credential supplied by {@link DataEncryptionParameters#getEncryptionCredential()} is mandatory * unless key encryption is also being performed and all associated key encryption parameters contain a valid key * encryption credential containing a valid key encryption key. In this case the data encryption key will be randomly * generated based on the algorithm URI supplied by {@link DataEncryptionParameters#getAlgorithm()}. *

* *

* If encryption of the data encryption key is being performed using the overloaded methods for elements or content, the * resulting EncryptedKey(s) will be placed inline within the KeyInfo of the resulting EncryptedData. If this is not the * desired behavior, the XMLObject and the data encryption key should be encrypted separately, and the placement of * EncryptedKey(s) handled by the caller. Specialized subclasses of this class maybe also handle key placement in an * application-specific manner. *

* */ public class Encrypter { /** Class logger. */ private final Logger log = LoggerFactory.getLogger(Encrypter.class); /** Unmarshaller used to create EncryptedData objects from DOM element. */ private final Unmarshaller encryptedDataUnmarshaller; /** Unmarshaller used to create EncryptedData objects from DOM element. */ private final Unmarshaller encryptedKeyUnmarshaller; /** Builder instance for building KeyInfo objects. */ private final XMLSignatureBuilder keyInfoBuilder; /** The name of the JCA security provider to use. */ private String jcaProviderName; /** * Constructor. * */ public Encrypter() { UnmarshallerFactory unmarshallerFactory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory(); encryptedDataUnmarshaller = unmarshallerFactory.getUnmarshaller(EncryptedData.DEFAULT_ELEMENT_NAME); encryptedKeyUnmarshaller = unmarshallerFactory.getUnmarshaller(EncryptedKey.DEFAULT_ELEMENT_NAME); Constraint.isNotNull(encryptedDataUnmarshaller, "EncryptedData unmarshaller not configured"); Constraint.isNotNull(encryptedKeyUnmarshaller, "EncryptedKey unmarshaller not configured"); XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory(); keyInfoBuilder = (XMLSignatureBuilder) builderFactory.getBuilder(KeyInfo.DEFAULT_ELEMENT_NAME); Constraint.isNotNull(keyInfoBuilder, "KeyInfo builder not configured"); } /** * Get the Java Cryptography Architecture (JCA) security provider name that should be used to provide the encryption * support. * * Defaults to null, which means that the first registered provider which supports the requested * encryption algorithm URI will be used. * * @return the JCA provider name to use */ @Nullable public String getJCAProviderName() { return jcaProviderName; } /** * Set the Java Cryptography Architecture (JCA) security provider name that should be used to provide the encryption * support. * * Defaults to null, which means that the first registered provider which supports the requested * encryption algorithm URI will be used. * * @param providerName the JCA provider name to use */ public void setJCAProviderName(@Nullable final String providerName) { jcaProviderName = providerName; } /** * Encrypts the DOM representation of the XMLObject. * * @param xmlObject the XMLObject to be encrypted * @param encParams parameters for encrypting the data * * @return the resulting EncryptedData element * @throws EncryptionException exception thrown on encryption errors */ @Nonnull public EncryptedData encryptElement(@Nonnull final XMLObject xmlObject, @Nonnull final DataEncryptionParameters encParams) throws EncryptionException { List emptyKEKParamsList = new ArrayList<>(); return encryptElement(xmlObject, encParams, emptyKEKParamsList, false); } /** * Encrypts the DOM representation of the XMLObject, encrypts the encryption key using the specified key encryption * parameters and places the resulting EncryptedKey within the EncryptedData's KeyInfo. * * @param xmlObject the XMLObject to be encrypted * @param encParams parameters for encrypting the data * @param kekParams parameters for encrypting the encryption key * * @return the resulting EncryptedData element * @throws EncryptionException exception thrown on encryption errors */ @Nonnull public EncryptedData encryptElement(@Nonnull final XMLObject xmlObject, @Nonnull final DataEncryptionParameters encParams, @Nonnull final KeyEncryptionParameters kekParams) throws EncryptionException { List kekParamsList = new ArrayList<>(); kekParamsList.add(kekParams); return encryptElement(xmlObject, encParams, kekParamsList, false); } /** * Encrypts the DOM representation of the XMLObject, encrypts the encryption key using the specified key encryption * parameters and places the resulting EncryptedKey(s) within the EncryptedData's KeyInfo. * * @param xmlObject the XMLObject to be encrypted * @param encParams parameters for encrypting the data * @param kekParamsList parameters for encrypting the encryption key * * @return the resulting EncryptedData element * @throws EncryptionException exception thrown on encryption errors */ @Nonnull public EncryptedData encryptElement(@Nonnull final XMLObject xmlObject, @Nonnull final DataEncryptionParameters encParams, @Nonnull final List kekParamsList) throws EncryptionException { return encryptElement(xmlObject, encParams, kekParamsList, false); } /** * Encrypts the DOM representation of the content of an XMLObject. * * @param xmlObject the XMLObject to be encrypted * @param encParams parameters for encrypting the data * * @return the resulting EncryptedData element * @throws EncryptionException exception thrown on encryption errors */ @Nonnull public EncryptedData encryptElementContent(@Nonnull final XMLObject xmlObject, @Nonnull final DataEncryptionParameters encParams) throws EncryptionException { List emptyKEKParamsList = new ArrayList<>(); return encryptElement(xmlObject, encParams, emptyKEKParamsList, true); } /** * Encrypts the DOM representation of the content of an XMLObject, encrypts the encryption key using the specified * key encryption parameters and places the resulting EncryptedKey within the EncryptedData's KeyInfo.. * * @param xmlObject the XMLObject to be encrypted * @param encParams parameters for encrypting the data * @param kekParams parameters for encrypting the encryption key * * @return the resulting EncryptedData element * @throws EncryptionException exception thrown on encryption errors */ @Nonnull public EncryptedData encryptElementContent(@Nonnull final XMLObject xmlObject, @Nonnull final DataEncryptionParameters encParams, @Nonnull final KeyEncryptionParameters kekParams) throws EncryptionException { List kekParamsList = new ArrayList<>(); kekParamsList.add(kekParams); return encryptElement(xmlObject, encParams, kekParamsList, true); } /** * Encrypts the DOM representation of the content of an XMLObject, encrypts the encryption key using the specified * key encryption parameters and places the resulting EncryptedKey(s) within the EncryptedData's KeyInfo.. * * @param xmlObject the XMLObject to be encrypted * @param encParams parameters for encrypting the data * @param kekParamsList parameters for encrypting the encryption key * * @return the resulting EncryptedData element * @throws EncryptionException exception thrown on encryption errors */ @Nonnull public EncryptedData encryptElementContent(@Nonnull final XMLObject xmlObject, @Nonnull final DataEncryptionParameters encParams, @Nonnull final List kekParamsList) throws EncryptionException { return encryptElement(xmlObject, encParams, kekParamsList, true); } /** * Encrypts a key once for each key encryption parameters set that is supplied. * * @param key the key to encrypt * @param kekParamsList a list parameters for encrypting the key * @param containingDocument the document that will own the DOM element underlying the resulting EncryptedKey * objects * * @return the resulting list of EncryptedKey objects * * @throws EncryptionException exception thrown on encryption errors */ @Nonnull public List encryptKey(@Nonnull final Key key, @Nonnull final List kekParamsList, @Nonnull final Document containingDocument) throws EncryptionException { checkParams(kekParamsList, false); List encKeys = new ArrayList<>(); for (KeyEncryptionParameters kekParam : kekParamsList) { encKeys.add(encryptKey(key, kekParam, containingDocument)); } return encKeys; } /** * Encrypts a key. * * @param key the key to encrypt * @param kekParams parameters for encrypting the key * @param containingDocument the document that will own the DOM element underlying the resulting EncryptedKey object * * @return the resulting EncryptedKey object * * @throws EncryptionException exception thrown on encryption errors */ @Nonnull public EncryptedKey encryptKey(@Nonnull final Key key, @Nonnull final KeyEncryptionParameters kekParams, @Nonnull final Document containingDocument) throws EncryptionException { checkParams(kekParams, false); Key encryptionKey = CredentialSupport.extractEncryptionKey(kekParams.getEncryptionCredential()); EncryptedKey encryptedKey = encryptKey(key, encryptionKey, kekParams.getAlgorithm(), kekParams.getRSAOAEPParameters(), containingDocument); if (kekParams.getKeyInfoGenerator() != null) { KeyInfoGenerator generator = kekParams.getKeyInfoGenerator(); log.debug("Dynamically generating KeyInfo from Credential for EncryptedKey using generator: {}", generator .getClass().getName()); try { encryptedKey.setKeyInfo(generator.generate(kekParams.getEncryptionCredential())); } catch (SecurityException e) { log.error("Error during EncryptedKey KeyInfo generation", e); throw new EncryptionException("Error during EncryptedKey KeyInfo generation", e); } } if (kekParams.getRecipient() != null) { encryptedKey.setRecipient(kekParams.getRecipient()); } return encryptedKey; } /** * Encrypts a key using the specified encryption key and algorithm URI. * * @param targetKey the key to encrypt * @param encryptionKey the key with which to encrypt the target key * @param encryptionAlgorithmURI the XML Encryption algorithm URI corresponding to the encryption key * @param rsaOAEPParams the RSA-OAEP params instance (may be null) * @param containingDocument the document that will own the resulting element * @return the new EncryptedKey object * @throws EncryptionException exception thrown on encryption errors */ @Nonnull protected EncryptedKey encryptKey(@Nonnull final Key targetKey, @Nonnull final Key encryptionKey, @Nonnull final String encryptionAlgorithmURI, @Nullable final RSAOAEPParameters rsaOAEPParams, @Nonnull final Document containingDocument) throws EncryptionException { Constraint.isNotNull(encryptionAlgorithmURI, "Encryption algorithm URI cannot be null"); Constraint.isNotNull(containingDocument, "Containing document cannot be null"); if (targetKey == null) { log.error("Target key for key encryption was null"); throw new EncryptionException("Target key was null"); } else if (encryptionKey == null) { log.error("Encryption key for key encryption was null"); throw new EncryptionException("Encryption key was null"); } log.debug("Encrypting encryption key with algorithm: {}", encryptionAlgorithmURI); XMLCipher xmlCipher; try { xmlCipher = buildXMLCipher(encryptionKey, encryptionAlgorithmURI, rsaOAEPParams); } catch (XMLEncryptionException e) { log.error("Error initializing cipher instance on key encryption", e); throw new EncryptionException("Error initializing cipher instance on key encryption", e); } org.apache.xml.security.encryption.EncryptedKey apacheEncryptedKey; try { if (AlgorithmSupport.isRSAOAEP(encryptionAlgorithmURI) && rsaOAEPParams != null) { apacheEncryptedKey = xmlCipher.encryptKey(containingDocument, targetKey, getEffectiveMGF(encryptionAlgorithmURI, rsaOAEPParams), decodeOAEPParams(rsaOAEPParams.getOAEPParams())); } else { apacheEncryptedKey = xmlCipher.encryptKey(containingDocument, targetKey); } postProcessApacheEncryptedKey(apacheEncryptedKey, targetKey, encryptionKey, encryptionAlgorithmURI, containingDocument); } catch (XMLEncryptionException e) { log.error("Error encrypting element on key encryption", e); throw new EncryptionException("Error encrypting element on key encryption", e); } try { Element encKeyElement = xmlCipher.martial(containingDocument, apacheEncryptedKey); return (EncryptedKey) encryptedKeyUnmarshaller.unmarshall(encKeyElement); } catch (UnmarshallingException e) { log.error("Error unmarshalling EncryptedKey element", e); throw new EncryptionException("Error unmarshalling EncryptedKey element"); } } /** * Construct and return an instance of {@link XMLCipher} based on the given inputs. * * @param encryptionKey the key transport encryption key with which to initialize the XMLCipher * @param encryptionAlgorithmURI the key transport encryption algorithm URI * @param rsaOAEPParams the optional RSA OAEP parameters instance * @return new XMLCipher instance * @throws XMLEncryptionException if there is a problem constructing the XMLCipher instance */ @Nonnull protected XMLCipher buildXMLCipher(@Nonnull final Key encryptionKey, @Nonnull final String encryptionAlgorithmURI, @Nullable final RSAOAEPParameters rsaOAEPParams) throws XMLEncryptionException { XMLCipher xmlCipher; if (getJCAProviderName() != null) { if (AlgorithmSupport.isRSAOAEP(encryptionAlgorithmURI) && rsaOAEPParams != null && rsaOAEPParams.getDigestMethod() != null) { xmlCipher = XMLCipher.getProviderInstance(encryptionAlgorithmURI, getJCAProviderName(), null, rsaOAEPParams.getDigestMethod()); } else { xmlCipher = XMLCipher.getProviderInstance(encryptionAlgorithmURI, getJCAProviderName()); } } else { if (AlgorithmSupport.isRSAOAEP(encryptionAlgorithmURI) && rsaOAEPParams != null && rsaOAEPParams.getDigestMethod() != null) { xmlCipher = XMLCipher.getInstance(encryptionAlgorithmURI, null, rsaOAEPParams.getDigestMethod()); } else { xmlCipher = XMLCipher.getInstance(encryptionAlgorithmURI); } } xmlCipher.init(XMLCipher.WRAP_MODE, encryptionKey); return xmlCipher; } /** * Get the effective RSA OAEP mask generation function (MGF) to use. * * @param encryptionAlgorithmURI the key transport encryption algorithm URI * @param rsaOAEPParams the optional RSA OAEP params instance * @return the effective MGF algorithm URI to use, may be null */ @Nullable protected String getEffectiveMGF(@Nonnull final String encryptionAlgorithmURI, @Nullable final RSAOAEPParameters rsaOAEPParams) { if (EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP11.equals(encryptionAlgorithmURI) && rsaOAEPParams != null) { return rsaOAEPParams.getMaskGenerationFunction(); } else { return null; } } /** * Safely decode and normalize base64-encoded OAEPParams data. * * @param base64Params the base64-encoded parameters * @return the decoded parameters or null * @throws EncryptionException if there is a problem base64-decoding the OAEPParams data */ @Nullable protected byte[] decodeOAEPParams(@Nullable final String base64Params) throws EncryptionException { try { if (base64Params != null) { byte[] oaepParams = Base64Support.decode(base64Params); if (oaepParams.length == 0) { return null; } else { return oaepParams; } } else { return null; } } catch (RuntimeException e) { throw new EncryptionException(String.format("Error decoding OAEPParams data '%s'", base64Params), e); } } /** * * Post-process the Apache EncryptedKey, prior to marshalling to DOM and unmarshalling into an XMLObject. * * @param apacheEncryptedKey the Apache EncryptedKeyObject to post-process * @param targetKey the key to encrypt * @param encryptionKey the key with which to encrypt the target key * @param encryptionAlgorithmURI the XML Encryption algorithm URI corresponding to the encryption key * @param containingDocument the document that will own the resulting element * * @throws EncryptionException exception thrown on encryption errors */ protected void postProcessApacheEncryptedKey( @Nonnull final org.apache.xml.security.encryption.EncryptedKey apacheEncryptedKey, @Nonnull final Key targetKey, @Nonnull final Key encryptionKey, @Nonnull final String encryptionAlgorithmURI, @Nonnull final Document containingDocument) throws EncryptionException { // To maximize interop, explicitly express the defaults of SHA-1 digest method and MGF-1 w/ SHA-1 input // parameters to RSA-OAEP key transport algorithm. The latter only applies to the XML Encryption 1.1 variant. // Check and only add if the library hasn't already done so. if (AlgorithmSupport.isRSAOAEP(encryptionAlgorithmURI)) { org.apache.xml.security.encryption.EncryptionMethod apacheEncryptionMethod = apacheEncryptedKey.getEncryptionMethod(); if (apacheEncryptionMethod.getDigestAlgorithm() == null) { apacheEncryptionMethod.setDigestAlgorithm(SignatureConstants.ALGO_ID_DIGEST_SHA1); } if (!EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP.equals(encryptionAlgorithmURI)) { if (apacheEncryptionMethod.getMGFAlgorithm() == null) { apacheEncryptionMethod.setMGFAlgorithm(EncryptionConstants.ALGO_ID_MGF1_SHA1); } } } } /** * Encrypts the given XMLObject using the specified encryption key, algorithm URI and content mode flag. * * @param xmlObject the XMLObject to be encrypted * @param encryptionKey the key with which to encrypt the XMLObject * @param encryptionAlgorithmURI the XML Encryption algorithm URI corresponding to the encryption key * @param encryptContentMode whether just the content of the XMLObject should be encrypted * @return the resulting EncryptedData object * @throws EncryptionException exception thrown on encryption errors */ @Nonnull protected EncryptedData encryptElement(@Nonnull final XMLObject xmlObject, @Nonnull final Key encryptionKey, @Nonnull final String encryptionAlgorithmURI, boolean encryptContentMode) throws EncryptionException { if (xmlObject == null) { log.error("XMLObject for encryption was null"); throw new EncryptionException("XMLObject cannot be null"); } else if (encryptionKey == null) { log.error("Encryption key for key encryption was null"); throw new EncryptionException("Encryption key cannot be null"); } log.debug("Encrypting XMLObject using algorithm URI {} with content mode {}", encryptionAlgorithmURI, encryptContentMode); checkAndMarshall(xmlObject); Element targetElement = xmlObject.getDOM(); Document ownerDocument = targetElement.getOwnerDocument(); XMLCipher xmlCipher; try { if (getJCAProviderName() != null) { xmlCipher = XMLCipher.getProviderInstance(encryptionAlgorithmURI, getJCAProviderName()); } else { xmlCipher = XMLCipher.getInstance(encryptionAlgorithmURI); } xmlCipher.init(XMLCipher.ENCRYPT_MODE, encryptionKey); } catch (XMLEncryptionException e) { log.error("Error initializing cipher instance on XMLObject encryption", e); throw new EncryptionException("Error initializing cipher instance", e); } org.apache.xml.security.encryption.EncryptedData apacheEncryptedData; try { apacheEncryptedData = xmlCipher.encryptData(ownerDocument, targetElement, encryptContentMode); } catch (Exception e) { log.error("Error encrypting XMLObject", e); throw new EncryptionException("Error encrypting XMLObject", e); } try { Element encDataElement = xmlCipher.martial(ownerDocument, apacheEncryptedData); return (EncryptedData) encryptedDataUnmarshaller.unmarshall(encDataElement); } catch (UnmarshallingException e) { log.error("Error unmarshalling EncryptedData element", e); throw new EncryptionException("Error unmarshalling EncryptedData element", e); } } /** * Encrypts the given XMLObject using the specified encryption key, algorithm URI and content mode flag. * EncryptedKeys, if any, are placed inline within the KeyInfo of the resulting EncryptedData. * * @param xmlObject the XMLObject to be encrypted * @param encParams the encryption parameters to use * @param kekParamsList the key encryption parameters to use * @param encryptContentMode whether just the content of the XMLObject should be encrypted * * @return the resulting EncryptedData object * @throws EncryptionException exception thrown on encryption errors */ @Nonnull private EncryptedData encryptElement(@Nonnull final XMLObject xmlObject, @Nonnull final DataEncryptionParameters encParams, @Nonnull final List kekParamsList, boolean encryptContentMode) throws EncryptionException { checkParams(encParams, kekParamsList); String encryptionAlgorithmURI = encParams.getAlgorithm(); Key encryptionKey = CredentialSupport.extractEncryptionKey(encParams.getEncryptionCredential()); if (encryptionKey == null) { encryptionKey = generateEncryptionKey(encryptionAlgorithmURI); } EncryptedData encryptedData = encryptElement(xmlObject, encryptionKey, encryptionAlgorithmURI, encryptContentMode); Document ownerDocument = encryptedData.getDOM().getOwnerDocument(); if (encParams.getKeyInfoGenerator() != null) { KeyInfoGenerator generator = encParams.getKeyInfoGenerator(); log.debug("Dynamically generating KeyInfo from Credential for EncryptedData using generator: {}", generator .getClass().getName()); try { encryptedData.setKeyInfo(generator.generate(encParams.getEncryptionCredential())); } catch (SecurityException e) { log.error("Error during EncryptedData KeyInfo generation", e); throw new EncryptionException("Error during EncryptedData KeyInfo generation", e); } } for (KeyEncryptionParameters kekParams : kekParamsList) { EncryptedKey encryptedKey = encryptKey(encryptionKey, kekParams, ownerDocument); if (encryptedData.getKeyInfo() == null) { KeyInfo keyInfo = keyInfoBuilder.buildObject(); encryptedData.setKeyInfo(keyInfo); } encryptedData.getKeyInfo().getEncryptedKeys().add(encryptedKey); } return encryptedData; } /** * Ensure that the XMLObject is marshalled. * * @param xmlObject the object to check and marshall * @throws EncryptionException thrown if there is an error when marshalling the XMLObject */ protected void checkAndMarshall(@Nonnull final XMLObject xmlObject) throws EncryptionException { Element targetElement = xmlObject.getDOM(); if (targetElement == null) { try { Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(xmlObject); if (marshaller == null) { throw new MarshallingException("No marshaller available for " + xmlObject.getElementQName()); } targetElement = marshaller.marshall(xmlObject); } catch (MarshallingException e) { log.error("Error marshalling target XMLObject", e); throw new EncryptionException("Error marshalling target XMLObject", e); } } } /** * Check data encryption parameters for consistency and required values. * * @param encParams the data encryption parameters to check * * @throws EncryptionException thrown if any parameters are missing or have invalid values */ protected void checkParams(@Nonnull final DataEncryptionParameters encParams) throws EncryptionException { if (encParams == null) { log.error("Data encryption parameters are required"); throw new EncryptionException("Data encryption parameters are required"); } else if (Strings.isNullOrEmpty(encParams.getAlgorithm())) { log.error("Data encryption algorithm URI is required"); throw new EncryptionException("Data encryption algorithm URI is required"); } } /** * Check key encryption parameters for consistency and required values. * * @param kekParams the key encryption parameters to check * @param allowEmpty if false, a null parameter is treated as an error * * @throws EncryptionException thrown if any parameters are missing or have invalid values */ protected void checkParams(@Nullable final KeyEncryptionParameters kekParams, boolean allowEmpty) throws EncryptionException { if (kekParams == null) { if (allowEmpty) { return; } else { log.error("Key encryption parameters are required"); throw new EncryptionException("Key encryption parameters are required"); } } Key key = CredentialSupport.extractEncryptionKey(kekParams.getEncryptionCredential()); if (key == null) { log.error("Key encryption credential and contained key are required"); throw new EncryptionException("Key encryption credential and contained key are required"); } else if (key instanceof DSAPublicKey) { log.error("Attempt made to use DSA key for encrypted key transport"); throw new EncryptionException("DSA keys may not be used for encrypted key transport"); } else if (key instanceof ECPublicKey) { log.error("Attempt made to use EC key for encrypted key transport"); throw new EncryptionException("EC keys may not be used for encrypted key transport"); } else if (Strings.isNullOrEmpty(kekParams.getAlgorithm())) { log.error("Key encryption algorithm URI is required"); throw new EncryptionException("Key encryption algorithm URI is required"); } } /** * Check a list of key encryption parameters for consistency and required values. * * @param kekParamsList the key encryption parameters list to check * @param allowEmpty if false, a null or empty list is treated as an error * * @throws EncryptionException thrown if any parameters are missing or have invalid values */ protected void checkParams(@Nullable final List kekParamsList, boolean allowEmpty) throws EncryptionException { if (kekParamsList == null || kekParamsList.isEmpty()) { if (allowEmpty) { return; } else { log.error("Key encryption parameters list may not be empty"); throw new EncryptionException("Key encryption parameters list may not be empty"); } } for (KeyEncryptionParameters kekParams : kekParamsList) { checkParams(kekParams, false); } } /** * Check the encryption parameters and key encryption parameters for valid combinations of options. * * @param encParams the encryption parameters to use * @param kekParamsList the key encryption parameters to use * @throws EncryptionException exception thrown on encryption errors */ protected void checkParams(@Nonnull final DataEncryptionParameters encParams, @Nullable final List kekParamsList) throws EncryptionException { checkParams(encParams); checkParams(kekParamsList, true); if (CredentialSupport.extractEncryptionKey(encParams.getEncryptionCredential()) == null && (kekParamsList == null || kekParamsList.isEmpty())) { log.error("Using a generated encryption key requires a KeyEncryptionParameters " + "object and key encryption key"); throw new EncryptionException("Using a generated encryption key requires a KeyEncryptionParameters " + "object and key encryption key"); } } /** * Generate a random symmetric encryption key. * * @param encryptionAlgorithmURI the encryption algorithm URI * @return a randomly generated symmetric key * @throws EncryptionException thrown if the key cannot be generated based on the specified algorithm URI */ @Nonnull protected SecretKey generateEncryptionKey(@Nonnull final String encryptionAlgorithmURI) throws EncryptionException { try { log.debug("Generating random symmetric data encryption key from algorithm URI: {}", encryptionAlgorithmURI); return AlgorithmSupport.generateSymmetricKey(encryptionAlgorithmURI); } catch (NoSuchAlgorithmException e) { log.error("Could not generate encryption key, algorithm URI was invalid: " + encryptionAlgorithmURI); throw new EncryptionException("Could not generate encryption key, algorithm URI was invalid: " + encryptionAlgorithmURI); } catch (KeyException e) { log.error("Could not generate encryption key from algorithm URI: " + encryptionAlgorithmURI); throw new EncryptionException("Could not generate encryption key from algorithm URI: " + encryptionAlgorithmURI); } } /* * Initialize the Apache XML security library if it hasn't been already */ static { if (!Init.isInitialized()) { Init.init(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy