| /* |
| * reserved comment block |
| * DO NOT REMOVE OR ALTER! |
| */ |
| /* |
| * Copyright 2003-2004 The Apache Software Foundation. |
| * |
| * Licensed 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 com.sun.org.apache.xml.internal.security.encryption; |
| |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.io.UnsupportedEncodingException; |
| import java.security.InvalidAlgorithmParameterException; |
| import java.security.InvalidKeyException; |
| import java.security.Key; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.NoSuchProviderException; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import javax.crypto.BadPaddingException; |
| import javax.crypto.Cipher; |
| import javax.crypto.IllegalBlockSizeException; |
| import javax.crypto.NoSuchPaddingException; |
| import javax.crypto.spec.IvParameterSpec; |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| |
| import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper; |
| import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm; |
| import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; |
| import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; |
| import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; |
| import com.sun.org.apache.xml.internal.security.keys.KeyInfo; |
| import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverException; |
| import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.EncryptedKeyResolver; |
| import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; |
| import com.sun.org.apache.xml.internal.security.transforms.InvalidTransformException; |
| import com.sun.org.apache.xml.internal.security.transforms.TransformationException; |
| import com.sun.org.apache.xml.internal.security.utils.Base64; |
| import com.sun.org.apache.xml.internal.security.utils.Constants; |
| import com.sun.org.apache.xml.internal.security.utils.ElementProxy; |
| import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants; |
| import com.sun.org.apache.xml.internal.security.utils.XMLUtils; |
| import com.sun.org.apache.xml.internal.utils.URI; |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.DocumentFragment; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| |
| /** |
| * <code>XMLCipher</code> encrypts and decrypts the contents of |
| * <code>Document</code>s, <code>Element</code>s and <code>Element</code> |
| * contents. It was designed to resemble <code>javax.crypto.Cipher</code> in |
| * order to facilitate understanding of its functioning. |
| * |
| * @author Axl Mattheus (Sun Microsystems) |
| * @author Christian Geuer-Pollmann |
| */ |
| public class XMLCipher { |
| |
| private static java.util.logging.Logger logger = |
| java.util.logging.Logger.getLogger(XMLCipher.class.getName()); |
| |
| //J- |
| /** Triple DES EDE (192 bit key) in CBC mode */ |
| public static final String TRIPLEDES = |
| EncryptionConstants.ALGO_ID_BLOCKCIPHER_TRIPLEDES; |
| /** AES 128 Cipher */ |
| public static final String AES_128 = |
| EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128; |
| /** AES 256 Cipher */ |
| public static final String AES_256 = |
| EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256; |
| /** AES 192 Cipher */ |
| public static final String AES_192 = |
| EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192; |
| /** RSA 1.5 Cipher */ |
| public static final String RSA_v1dot5 = |
| EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15; |
| /** RSA OAEP Cipher */ |
| public static final String RSA_OAEP = |
| EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP; |
| /** DIFFIE_HELLMAN Cipher */ |
| public static final String DIFFIE_HELLMAN = |
| EncryptionConstants.ALGO_ID_KEYAGREEMENT_DH; |
| /** Triple DES EDE (192 bit key) in CBC mode KEYWRAP*/ |
| public static final String TRIPLEDES_KeyWrap = |
| EncryptionConstants.ALGO_ID_KEYWRAP_TRIPLEDES; |
| /** AES 128 Cipher KeyWrap */ |
| public static final String AES_128_KeyWrap = |
| EncryptionConstants.ALGO_ID_KEYWRAP_AES128; |
| /** AES 256 Cipher KeyWrap */ |
| public static final String AES_256_KeyWrap = |
| EncryptionConstants.ALGO_ID_KEYWRAP_AES256; |
| /** AES 192 Cipher KeyWrap */ |
| public static final String AES_192_KeyWrap = |
| EncryptionConstants.ALGO_ID_KEYWRAP_AES192; |
| /** SHA1 Cipher */ |
| public static final String SHA1 = |
| Constants.ALGO_ID_DIGEST_SHA1; |
| /** SHA256 Cipher */ |
| public static final String SHA256 = |
| MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256; |
| /** SHA512 Cipher */ |
| public static final String SHA512 = |
| MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA512; |
| /** RIPEMD Cipher */ |
| public static final String RIPEMD_160 = |
| MessageDigestAlgorithm.ALGO_ID_DIGEST_RIPEMD160; |
| /** XML Signature NS */ |
| public static final String XML_DSIG = |
| Constants.SignatureSpecNS; |
| /** N14C_XML */ |
| public static final String N14C_XML = |
| Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS; |
| /** N14C_XML with comments*/ |
| public static final String N14C_XML_WITH_COMMENTS = |
| Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS; |
| /** N14C_XML excluisve */ |
| public static final String EXCL_XML_N14C = |
| Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; |
| /** N14C_XML exclusive with commetns*/ |
| public static final String EXCL_XML_N14C_WITH_COMMENTS = |
| Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS; |
| /** Base64 encoding */ |
| public static final String BASE64_ENCODING = |
| com.sun.org.apache.xml.internal.security.transforms.Transforms.TRANSFORM_BASE64_DECODE; |
| //J+ |
| |
| /** ENCRYPT Mode */ |
| public static final int ENCRYPT_MODE = Cipher.ENCRYPT_MODE; |
| /** DECRYPT Mode */ |
| public static final int DECRYPT_MODE = Cipher.DECRYPT_MODE; |
| /** UNWRAP Mode */ |
| public static final int UNWRAP_MODE = Cipher.UNWRAP_MODE; |
| /** WRAP Mode */ |
| public static final int WRAP_MODE = Cipher.WRAP_MODE; |
| |
| private static final String ENC_ALGORITHMS = TRIPLEDES + "\n" + |
| AES_128 + "\n" + AES_256 + "\n" + AES_192 + "\n" + RSA_v1dot5 + "\n" + |
| RSA_OAEP + "\n" + TRIPLEDES_KeyWrap + "\n" + AES_128_KeyWrap + "\n" + |
| AES_256_KeyWrap + "\n" + AES_192_KeyWrap+ "\n"; |
| |
| /** Cipher created during initialisation that is used for encryption */ |
| private Cipher _contextCipher; |
| /** Mode that the XMLCipher object is operating in */ |
| private int _cipherMode = Integer.MIN_VALUE; |
| /** URI of algorithm that is being used for cryptographic operation */ |
| private String _algorithm = null; |
| /** Cryptographic provider requested by caller */ |
| private String _requestedJCEProvider = null; |
| /** Holds c14n to serialize, if initialized then _always_ use this c14n to serialize */ |
| private Canonicalizer _canon; |
| /** Used for creation of DOM nodes in WRAP and ENCRYPT modes */ |
| private Document _contextDocument; |
| /** Instance of factory used to create XML Encryption objects */ |
| private Factory _factory; |
| /** Internal serializer class for going to/from UTF-8 */ |
| private Serializer _serializer; |
| |
| /** Local copy of user's key */ |
| private Key _key; |
| /** Local copy of the kek (used to decrypt EncryptedKeys during a |
| * DECRYPT_MODE operation */ |
| private Key _kek; |
| |
| // The EncryptedKey being built (part of a WRAP operation) or read |
| // (part of an UNWRAP operation) |
| |
| private EncryptedKey _ek; |
| |
| // The EncryptedData being built (part of a WRAP operation) or read |
| // (part of an UNWRAP operation) |
| |
| private EncryptedData _ed; |
| |
| /** |
| * Creates a new <code>XMLCipher</code>. |
| * |
| * @since 1.0. |
| */ |
| private XMLCipher() { |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Constructing XMLCipher..."); |
| |
| _factory = new Factory(); |
| _serializer = new Serializer(); |
| |
| } |
| |
| /** |
| * Checks to ensure that the supplied algorithm is valid. |
| * |
| * @param algorithm the algorithm to check. |
| * @return true if the algorithm is valid, otherwise false. |
| * @since 1.0. |
| */ |
| private static boolean isValidEncryptionAlgorithm(String algorithm) { |
| boolean result = ( |
| algorithm.equals(TRIPLEDES) || |
| algorithm.equals(AES_128) || |
| algorithm.equals(AES_256) || |
| algorithm.equals(AES_192) || |
| algorithm.equals(RSA_v1dot5) || |
| algorithm.equals(RSA_OAEP) || |
| algorithm.equals(TRIPLEDES_KeyWrap) || |
| algorithm.equals(AES_128_KeyWrap) || |
| algorithm.equals(AES_256_KeyWrap) || |
| algorithm.equals(AES_192_KeyWrap) |
| ); |
| |
| return (result); |
| } |
| |
| /** |
| * Returns an <code>XMLCipher</code> that implements the specified |
| * transformation and operates on the specified context document. |
| * <p> |
| * If the default provider package supplies an implementation of the |
| * requested transformation, an instance of Cipher containing that |
| * implementation is returned. If the transformation is not available in |
| * the default provider package, other provider packages are searched. |
| * <p> |
| * <b>NOTE<sub>1</sub>:</b> The transformation name does not follow the same |
| * pattern as that oulined in the Java Cryptography Extension Reference |
| * Guide but rather that specified by the XML Encryption Syntax and |
| * Processing document. The rational behind this is to make it easier for a |
| * novice at writing Java Encryption software to use the library. |
| * <p> |
| * <b>NOTE<sub>2</sub>:</b> <code>getInstance()</code> does not follow the |
| * same pattern regarding exceptional conditions as that used in |
| * <code>javax.crypto.Cipher</code>. Instead, it only throws an |
| * <code>XMLEncryptionException</code> which wraps an underlying exception. |
| * The stack trace from the exception should be self explanitory. |
| * |
| * @param transformation the name of the transformation, e.g., |
| * <code>XMLCipher.TRIPLEDES</code> which is shorthand for |
| * "http://www.w3.org/2001/04/xmlenc#tripledes-cbc" |
| * @throws XMLEncryptionException |
| * @return the XMLCipher |
| * @see javax.crypto.Cipher#getInstance(java.lang.String) |
| */ |
| public static XMLCipher getInstance(String transformation) throws |
| XMLEncryptionException { |
| // sanity checks |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Getting XMLCipher..."); |
| if (null == transformation) |
| logger.log(java.util.logging.Level.SEVERE, "Transformation unexpectedly null..."); |
| if(!isValidEncryptionAlgorithm(transformation)) |
| logger.log(java.util.logging.Level.WARNING, "Algorithm non-standard, expected one of " + ENC_ALGORITHMS); |
| |
| XMLCipher instance = new XMLCipher(); |
| |
| instance._algorithm = transformation; |
| instance._key = null; |
| instance._kek = null; |
| |
| |
| /* Create a canonicaliser - used when serialising DOM to octets |
| * prior to encryption (and for the reverse) */ |
| |
| try { |
| instance._canon = Canonicalizer.getInstance |
| (Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS); |
| |
| } catch (InvalidCanonicalizerException ice) { |
| throw new XMLEncryptionException("empty", ice); |
| } |
| |
| String jceAlgorithm = JCEMapper.translateURItoJCEID(transformation); |
| |
| try { |
| instance._contextCipher = Cipher.getInstance(jceAlgorithm); |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "cihper.algoritm = " + |
| instance._contextCipher.getAlgorithm()); |
| } catch (NoSuchAlgorithmException nsae) { |
| throw new XMLEncryptionException("empty", nsae); |
| } catch (NoSuchPaddingException nspe) { |
| throw new XMLEncryptionException("empty", nspe); |
| } |
| |
| return (instance); |
| } |
| |
| public static XMLCipher getInstance(String transformation,Cipher cipher) throws |
| XMLEncryptionException { |
| // sanity checks |
| logger.log(java.util.logging.Level.FINE, "Getting XMLCipher..."); |
| if (null == transformation) |
| logger.log(java.util.logging.Level.SEVERE, "Transformation unexpectedly null..."); |
| if(!isValidEncryptionAlgorithm(transformation)) |
| logger.log(java.util.logging.Level.WARNING, "Algorithm non-standard, expected one of " + ENC_ALGORITHMS); |
| |
| XMLCipher instance = new XMLCipher(); |
| |
| instance._algorithm = transformation; |
| instance._key = null; |
| instance._kek = null; |
| |
| |
| /* Create a canonicaliser - used when serialising DOM to octets |
| * prior to encryption (and for the reverse) */ |
| |
| try { |
| instance._canon = Canonicalizer.getInstance |
| (Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS); |
| |
| } catch (InvalidCanonicalizerException ice) { |
| throw new XMLEncryptionException("empty", ice); |
| } |
| |
| String jceAlgorithm = JCEMapper.translateURItoJCEID(transformation); |
| |
| try { |
| instance._contextCipher = cipher; |
| //Cipher.getInstance(jceAlgorithm); |
| logger.log(java.util.logging.Level.FINE, "cihper.algoritm = " + |
| instance._contextCipher.getAlgorithm()); |
| }catch(Exception ex) { |
| throw new XMLEncryptionException("empty", ex); |
| } |
| |
| return (instance); |
| } |
| |
| |
| |
| /** |
| * Returns an <code>XMLCipher</code> that implements the specified |
| * transformation, operates on the specified context document and serializes |
| * the document with the specified canonicalization algorithm before it |
| * encrypts the document. |
| * <p> |
| * |
| * @param transformation the name of the transformation, e.g., |
| * <code>XMLCipher.TRIPLEDES</code> which is |
| * shorthand for |
| * "http://www.w3.org/2001/04/xmlenc#tripledes-cbc" |
| * @param canon the name of the c14n algorithm, if |
| * <code>null</code> use standard serializer |
| * @return |
| * @throws XMLEncryptionException |
| */ |
| |
| public static XMLCipher getInstance(String transformation, String canon) |
| throws XMLEncryptionException { |
| XMLCipher instance = XMLCipher.getInstance(transformation); |
| |
| if (canon != null) { |
| try { |
| instance._canon = Canonicalizer.getInstance(canon); |
| } catch (InvalidCanonicalizerException ice) { |
| throw new XMLEncryptionException("empty", ice); |
| } |
| } |
| |
| return instance; |
| } |
| |
| |
| /** |
| * Returns an <code>XMLCipher</code> that implements the specified |
| * transformation and operates on the specified context document. |
| * |
| * @param transformation the name of the transformation, e.g., |
| * <code>XMLCipher.TRIPLEDES</code> which is shorthand for |
| * "http://www.w3.org/2001/04/xmlenc#tripledes-cbc" |
| * @param provider the JCE provider that supplies the transformation |
| * @return the XMLCipher |
| * @throws XMLEncryptionException |
| */ |
| |
| public static XMLCipher getProviderInstance(String transformation, String provider) |
| throws XMLEncryptionException { |
| // sanity checks |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Getting XMLCipher..."); |
| if (null == transformation) |
| logger.log(java.util.logging.Level.SEVERE, "Transformation unexpectedly null..."); |
| if(null == provider) |
| logger.log(java.util.logging.Level.SEVERE, "Provider unexpectedly null.."); |
| if("" == provider) |
| logger.log(java.util.logging.Level.SEVERE, "Provider's value unexpectedly not specified..."); |
| if(!isValidEncryptionAlgorithm(transformation)) |
| logger.log(java.util.logging.Level.WARNING, "Algorithm non-standard, expected one of " + ENC_ALGORITHMS); |
| |
| XMLCipher instance = new XMLCipher(); |
| |
| instance._algorithm = transformation; |
| instance._requestedJCEProvider = provider; |
| instance._key = null; |
| instance._kek = null; |
| |
| /* Create a canonicaliser - used when serialising DOM to octets |
| * prior to encryption (and for the reverse) */ |
| |
| try { |
| instance._canon = Canonicalizer.getInstance |
| (Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS); |
| } catch (InvalidCanonicalizerException ice) { |
| throw new XMLEncryptionException("empty", ice); |
| } |
| |
| try { |
| String jceAlgorithm = |
| JCEMapper.translateURItoJCEID(transformation); |
| |
| instance._contextCipher = Cipher.getInstance(jceAlgorithm, provider); |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "cipher._algorithm = " + |
| instance._contextCipher.getAlgorithm()); |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "provider.name = " + provider); |
| } catch (NoSuchAlgorithmException nsae) { |
| throw new XMLEncryptionException("empty", nsae); |
| } catch (NoSuchProviderException nspre) { |
| throw new XMLEncryptionException("empty", nspre); |
| } catch (NoSuchPaddingException nspe) { |
| throw new XMLEncryptionException("empty", nspe); |
| } |
| |
| return (instance); |
| } |
| |
| /** |
| * Returns an <code>XMLCipher</code> that implements the specified |
| * transformation, operates on the specified context document and serializes |
| * the document with the specified canonicalization algorithm before it |
| * encrypts the document. |
| * <p> |
| * |
| * @param transformation the name of the transformation, e.g., |
| * <code>XMLCipher.TRIPLEDES</code> which is |
| * shorthand for |
| * "http://www.w3.org/2001/04/xmlenc#tripledes-cbc" |
| * @param provider the JCE provider that supplies the transformation |
| * @param canon the name of the c14n algorithm, if |
| * <code>null</code> use standard serializer |
| * @return |
| * @throws XMLEncryptionException |
| */ |
| public static XMLCipher getProviderInstance( |
| String transformation, |
| String provider, |
| String canon) |
| throws XMLEncryptionException { |
| |
| XMLCipher instance = XMLCipher.getProviderInstance(transformation, provider); |
| if (canon != null) { |
| try { |
| instance._canon = Canonicalizer.getInstance(canon); |
| } catch (InvalidCanonicalizerException ice) { |
| throw new XMLEncryptionException("empty", ice); |
| } |
| } |
| return instance; |
| } |
| |
| /** |
| * Returns an <code>XMLCipher</code> that implements no specific |
| * transformation, and can therefore only be used for decrypt or |
| * unwrap operations where the encryption method is defined in the |
| * <code>EncryptionMethod</code> element. |
| * |
| * @return The XMLCipher |
| * @throws XMLEncryptionException |
| */ |
| |
| public static XMLCipher getInstance() |
| throws XMLEncryptionException { |
| // sanity checks |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Getting XMLCipher for no transformation..."); |
| |
| XMLCipher instance = new XMLCipher(); |
| |
| instance._algorithm = null; |
| instance._requestedJCEProvider = null; |
| instance._key = null; |
| instance._kek = null; |
| instance._contextCipher = null; |
| |
| /* Create a canonicaliser - used when serialising DOM to octets |
| * prior to encryption (and for the reverse) */ |
| |
| try { |
| instance._canon = Canonicalizer.getInstance |
| (Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS); |
| } catch (InvalidCanonicalizerException ice) { |
| throw new XMLEncryptionException("empty", ice); |
| } |
| |
| return (instance); |
| } |
| |
| /** |
| * Returns an <code>XMLCipher</code> that implements no specific |
| * transformation, and can therefore only be used for decrypt or |
| * unwrap operations where the encryption method is defined in the |
| * <code>EncryptionMethod</code> element. |
| * |
| * Allows the caller to specify a provider that will be used for |
| * cryptographic operations. |
| * |
| * @param provider the JCE provider that supplies the cryptographic |
| * needs. |
| * @return the XMLCipher |
| * @throws XMLEncryptionException |
| */ |
| |
| public static XMLCipher getProviderInstance(String provider) |
| throws XMLEncryptionException { |
| // sanity checks |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Getting XMLCipher, provider but no transformation"); |
| if(null == provider) |
| logger.log(java.util.logging.Level.SEVERE, "Provider unexpectedly null.."); |
| if("" == provider) |
| logger.log(java.util.logging.Level.SEVERE, "Provider's value unexpectedly not specified..."); |
| |
| XMLCipher instance = new XMLCipher(); |
| |
| instance._algorithm = null; |
| instance._requestedJCEProvider = provider; |
| instance._key = null; |
| instance._kek = null; |
| instance._contextCipher = null; |
| |
| try { |
| instance._canon = Canonicalizer.getInstance |
| (Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS); |
| } catch (InvalidCanonicalizerException ice) { |
| throw new XMLEncryptionException("empty", ice); |
| } |
| |
| return (instance); |
| } |
| |
| /** |
| * Initializes this cipher with a key. |
| * <p> |
| * The cipher is initialized for one of the following four operations: |
| * encryption, decryption, key wrapping or key unwrapping, depending on the |
| * value of opmode. |
| * |
| * For WRAP and ENCRYPT modes, this also initialises the internal |
| * EncryptedKey or EncryptedData (with a CipherValue) |
| * structure that will be used during the ensuing operations. This |
| * can be obtained (in order to modify KeyInfo elements etc. prior to |
| * finalising the encryption) by calling |
| * {@link #getEncryptedData} or {@link #getEncryptedKey}. |
| * |
| * @param opmode the operation mode of this cipher (this is one of the |
| * following: ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE or UNWRAP_MODE) |
| * @param key |
| * @see javax.crypto.Cipher#init(int, java.security.Key) |
| * @throws XMLEncryptionException |
| */ |
| public void init(int opmode, Key key) throws XMLEncryptionException { |
| // sanity checks |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Initializing XMLCipher..."); |
| |
| _ek = null; |
| _ed = null; |
| |
| switch (opmode) { |
| |
| case ENCRYPT_MODE : |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "opmode = ENCRYPT_MODE"); |
| _ed = createEncryptedData(CipherData.VALUE_TYPE, "NO VALUE YET"); |
| break; |
| case DECRYPT_MODE : |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "opmode = DECRYPT_MODE"); |
| break; |
| case WRAP_MODE : |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "opmode = WRAP_MODE"); |
| _ek = createEncryptedKey(CipherData.VALUE_TYPE, "NO VALUE YET"); |
| break; |
| case UNWRAP_MODE : |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "opmode = UNWRAP_MODE"); |
| break; |
| default : |
| logger.log(java.util.logging.Level.SEVERE, "Mode unexpectedly invalid"); |
| throw new XMLEncryptionException("Invalid mode in init"); |
| } |
| |
| _cipherMode = opmode; |
| _key = key; |
| |
| } |
| |
| /** |
| * Get the EncryptedData being build |
| * |
| * Returns the EncryptedData being built during an ENCRYPT operation. |
| * This can then be used by applications to add KeyInfo elements and |
| * set other parameters. |
| * |
| * @return The EncryptedData being built |
| */ |
| |
| public EncryptedData getEncryptedData() { |
| |
| // Sanity checks |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Returning EncryptedData"); |
| return _ed; |
| |
| } |
| |
| /** |
| * Get the EncryptedData being build |
| * |
| * Returns the EncryptedData being built during an ENCRYPT operation. |
| * This can then be used by applications to add KeyInfo elements and |
| * set other parameters. |
| * |
| * @return The EncryptedData being built |
| */ |
| |
| public EncryptedKey getEncryptedKey() { |
| |
| // Sanity checks |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Returning EncryptedKey"); |
| return _ek; |
| } |
| |
| /** |
| * Set a Key Encryption Key. |
| * <p> |
| * The Key Encryption Key (KEK) is used for encrypting/decrypting |
| * EncryptedKey elements. By setting this separately, the XMLCipher |
| * class can know whether a key applies to the data part or wrapped key |
| * part of an encrypted object. |
| * |
| * @param kek The key to use for de/encrypting key data |
| */ |
| |
| public void setKEK(Key kek) { |
| |
| _kek = kek; |
| |
| } |
| |
| /** |
| * Martial an EncryptedData |
| * |
| * Takes an EncryptedData object and returns a DOM Element that |
| * represents the appropriate <code>EncryptedData</code> |
| * <p> |
| * <b>Note:</b> This should only be used in cases where the context |
| * document has been passed in via a call to doFinal. |
| * |
| * @param encryptedData EncryptedData object to martial |
| * @return the DOM <code>Element</code> representing the passed in |
| * object |
| */ |
| |
| public Element martial(EncryptedData encryptedData) { |
| |
| return (_factory.toElement (encryptedData)); |
| |
| } |
| |
| /** |
| * Martial an EncryptedKey |
| * |
| * Takes an EncryptedKey object and returns a DOM Element that |
| * represents the appropriate <code>EncryptedKey</code> |
| * |
| * <p> |
| * <b>Note:</b> This should only be used in cases where the context |
| * document has been passed in via a call to doFinal. |
| * |
| * @param encryptedKey EncryptedKey object to martial |
| * @return the DOM <code>Element</code> representing the passed in |
| * object */ |
| |
| public Element martial(EncryptedKey encryptedKey) { |
| |
| return (_factory.toElement (encryptedKey)); |
| |
| } |
| |
| /** |
| * Martial an EncryptedData |
| * |
| * Takes an EncryptedData object and returns a DOM Element that |
| * represents the appropriate <code>EncryptedData</code> |
| * |
| * @param context The document that will own the returned nodes |
| * @param encryptedData EncryptedData object to martial |
| * @return the DOM <code>Element</code> representing the passed in |
| * object */ |
| |
| public Element martial(Document context, EncryptedData encryptedData) { |
| |
| _contextDocument = context; |
| return (_factory.toElement (encryptedData)); |
| |
| } |
| |
| /** |
| * Martial an EncryptedKey |
| * |
| * Takes an EncryptedKey object and returns a DOM Element that |
| * represents the appropriate <code>EncryptedKey</code> |
| * |
| * @param context The document that will own the created nodes |
| * @param encryptedKey EncryptedKey object to martial |
| * @return the DOM <code>Element</code> representing the passed in |
| * object */ |
| |
| public Element martial(Document context, EncryptedKey encryptedKey) { |
| |
| _contextDocument = context; |
| return (_factory.toElement (encryptedKey)); |
| |
| } |
| |
| /** |
| * Encrypts an <code>Element</code> and replaces it with its encrypted |
| * counterpart in the context <code>Document</code>, that is, the |
| * <code>Document</code> specified when one calls |
| * {@link #getInstance(String) getInstance}. |
| * |
| * @param element the <code>Element</code> to encrypt. |
| * @return the context <code>Document</code> with the encrypted |
| * <code>Element</code> having replaced the source <code>Element</code>. |
| * @throws Exception |
| */ |
| |
| private Document encryptElement(Element element) throws Exception{ |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypting element..."); |
| if(null == element) |
| logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null..."); |
| if(_cipherMode != ENCRYPT_MODE) |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE..."); |
| |
| if (_algorithm == null) { |
| throw new XMLEncryptionException("XMLCipher instance without transformation specified"); |
| } |
| encryptData(_contextDocument, element, false); |
| |
| Element encryptedElement = _factory.toElement(_ed); |
| |
| Node sourceParent = element.getParentNode(); |
| sourceParent.replaceChild(encryptedElement, element); |
| |
| return (_contextDocument); |
| } |
| |
| /** |
| * Encrypts a <code>NodeList</code> (the contents of an |
| * <code>Element</code>) and replaces its parent <code>Element</code>'s |
| * content with this the resulting <code>EncryptedType</code> within the |
| * context <code>Document</code>, that is, the <code>Document</code> |
| * specified when one calls |
| * {@link #getInstance(String) getInstance}. |
| * |
| * @param element the <code>NodeList</code> to encrypt. |
| * @return the context <code>Document</code> with the encrypted |
| * <code>NodeList</code> having replaced the content of the source |
| * <code>Element</code>. |
| * @throws Exception |
| */ |
| private Document encryptElementContent(Element element) throws |
| /* XMLEncryption */Exception { |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypting element content..."); |
| if(null == element) |
| logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null..."); |
| if(_cipherMode != ENCRYPT_MODE) |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE..."); |
| |
| if (_algorithm == null) { |
| throw new XMLEncryptionException("XMLCipher instance without transformation specified"); |
| } |
| encryptData(_contextDocument, element, true); |
| |
| Element encryptedElement = _factory.toElement(_ed); |
| |
| removeContent(element); |
| element.appendChild(encryptedElement); |
| |
| return (_contextDocument); |
| } |
| |
| /** |
| * Process a DOM <code>Document</code> node. The processing depends on the |
| * initialization parameters of {@link #init(int, Key) init()}. |
| * |
| * @param context the context <code>Document</code>. |
| * @param source the <code>Document</code> to be encrypted or decrypted. |
| * @return the processed <code>Document</code>. |
| * @throws Exception to indicate any exceptional conditions. |
| */ |
| public Document doFinal(Document context, Document source) throws |
| /* XMLEncryption */Exception { |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Processing source document..."); |
| if(null == context) |
| logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
| if(null == source) |
| logger.log(java.util.logging.Level.SEVERE, "Source document unexpectedly null..."); |
| |
| _contextDocument = context; |
| |
| Document result = null; |
| |
| switch (_cipherMode) { |
| case DECRYPT_MODE: |
| result = decryptElement(source.getDocumentElement()); |
| break; |
| case ENCRYPT_MODE: |
| result = encryptElement(source.getDocumentElement()); |
| break; |
| case UNWRAP_MODE: |
| break; |
| case WRAP_MODE: |
| break; |
| default: |
| throw new XMLEncryptionException( |
| "empty", new IllegalStateException()); |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * Process a DOM <code>Element</code> node. The processing depends on the |
| * initialization parameters of {@link #init(int, Key) init()}. |
| * |
| * @param context the context <code>Document</code>. |
| * @param element the <code>Element</code> to be encrypted. |
| * @return the processed <code>Document</code>. |
| * @throws Exception to indicate any exceptional conditions. |
| */ |
| public Document doFinal(Document context, Element element) throws |
| /* XMLEncryption */Exception { |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Processing source element..."); |
| if(null == context) |
| logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
| if(null == element) |
| logger.log(java.util.logging.Level.SEVERE, "Source element unexpectedly null..."); |
| |
| _contextDocument = context; |
| |
| Document result = null; |
| |
| switch (_cipherMode) { |
| case DECRYPT_MODE: |
| result = decryptElement(element); |
| break; |
| case ENCRYPT_MODE: |
| result = encryptElement(element); |
| break; |
| case UNWRAP_MODE: |
| break; |
| case WRAP_MODE: |
| break; |
| default: |
| throw new XMLEncryptionException( |
| "empty", new IllegalStateException()); |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * Process the contents of a DOM <code>Element</code> node. The processing |
| * depends on the initialization parameters of |
| * {@link #init(int, Key) init()}. |
| * |
| * @param context the context <code>Document</code>. |
| * @param element the <code>Element</code> which contents is to be |
| * encrypted. |
| * @param content |
| * @return the processed <code>Document</code>. |
| * @throws Exception to indicate any exceptional conditions. |
| */ |
| public Document doFinal(Document context, Element element, boolean content) |
| throws /* XMLEncryption*/ Exception { |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Processing source element..."); |
| if(null == context) |
| logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
| if(null == element) |
| logger.log(java.util.logging.Level.SEVERE, "Source element unexpectedly null..."); |
| |
| _contextDocument = context; |
| |
| Document result = null; |
| |
| switch (_cipherMode) { |
| case DECRYPT_MODE: |
| if (content) { |
| result = decryptElementContent(element); |
| } else { |
| result = decryptElement(element); |
| } |
| break; |
| case ENCRYPT_MODE: |
| if (content) { |
| result = encryptElementContent(element); |
| } else { |
| result = encryptElement(element); |
| } |
| break; |
| case UNWRAP_MODE: |
| break; |
| case WRAP_MODE: |
| break; |
| default: |
| throw new XMLEncryptionException( |
| "empty", new IllegalStateException()); |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * Returns an <code>EncryptedData</code> interface. Use this operation if |
| * you want to have full control over the contents of the |
| * <code>EncryptedData</code> structure. |
| * |
| * this does not change the source document in any way. |
| * |
| * @param context the context <code>Document</code>. |
| * @param element the <code>Element</code> that will be encrypted. |
| * @return the <code>EncryptedData</code> |
| * @throws Exception |
| */ |
| public EncryptedData encryptData(Document context, Element element) throws |
| /* XMLEncryption */Exception { |
| return encryptData(context, element, false); |
| } |
| |
| /** |
| * Returns an <code>EncryptedData</code> interface. Use this operation if |
| * you want to have full control over the contents of the |
| * <code>EncryptedData</code> structure. |
| * |
| * this does not change the source document in any way. |
| * |
| * @param context the context <code>Document</code>. |
| * @param element the <code>Element</code> that will be encrypted. |
| * @param contentMode <code>true</code> to encrypt element's content only, |
| * <code>false</code> otherwise |
| * @return the <code>EncryptedData</code> |
| * @throws Exception |
| */ |
| public EncryptedData encryptData(Document context, Element element, boolean contentMode) throws |
| /* XMLEncryption */ Exception { |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypting element..."); |
| if (null == context) |
| logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
| if (null == element) |
| logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null..."); |
| if (_cipherMode != ENCRYPT_MODE) |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE..."); |
| |
| _contextDocument = context; |
| |
| if (_algorithm == null) { |
| throw new XMLEncryptionException("XMLCipher instance without transformation specified"); |
| } |
| |
| String serializedOctets = null; |
| if (contentMode) { |
| NodeList children = element.getChildNodes(); |
| if ((null != children)) { |
| serializedOctets = _serializer.serialize(children); |
| } else { |
| Object exArgs[] = { "Element has no content." }; |
| throw new XMLEncryptionException("empty", exArgs); |
| } |
| } else { |
| serializedOctets = _serializer.serialize(element); |
| } |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Serialized octets:\n" + serializedOctets); |
| |
| byte[] encryptedBytes = null; |
| |
| // Now create the working cipher if none was created already |
| Cipher c; |
| if (_contextCipher == null) { |
| String jceAlgorithm = |
| JCEMapper.translateURItoJCEID(_algorithm); |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "alg = " + jceAlgorithm); |
| |
| try { |
| if (_requestedJCEProvider == null) |
| c = Cipher.getInstance(jceAlgorithm); |
| else |
| c = Cipher.getInstance(jceAlgorithm, _requestedJCEProvider); |
| } catch (NoSuchAlgorithmException nsae) { |
| throw new XMLEncryptionException("empty", nsae); |
| } catch (NoSuchProviderException nspre) { |
| throw new XMLEncryptionException("empty", nspre); |
| } catch (NoSuchPaddingException nspae) { |
| throw new XMLEncryptionException("empty", nspae); |
| } |
| } |
| else { |
| c = _contextCipher; |
| } |
| // Now perform the encryption |
| |
| try { |
| // Should internally generate an IV |
| // todo - allow user to set an IV |
| c.init(_cipherMode, _key); |
| } catch (InvalidKeyException ike) { |
| throw new XMLEncryptionException("empty", ike); |
| } |
| |
| try { |
| encryptedBytes = |
| c.doFinal(serializedOctets.getBytes("UTF-8")); |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Expected cipher.outputSize = " + |
| Integer.toString(c.getOutputSize( |
| serializedOctets.getBytes().length))); |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Actual cipher.outputSize = " + |
| Integer.toString(encryptedBytes.length)); |
| } catch (IllegalStateException ise) { |
| throw new XMLEncryptionException("empty", ise); |
| } catch (IllegalBlockSizeException ibse) { |
| throw new XMLEncryptionException("empty", ibse); |
| } catch (BadPaddingException bpe) { |
| throw new XMLEncryptionException("empty", bpe); |
| } catch (UnsupportedEncodingException uee) { |
| throw new XMLEncryptionException("empty", uee); |
| } |
| |
| // Now build up to a properly XML Encryption encoded octet stream |
| // IvParameterSpec iv; |
| |
| byte[] iv = c.getIV(); |
| byte[] finalEncryptedBytes = |
| new byte[iv.length + encryptedBytes.length]; |
| System.arraycopy(iv, 0, finalEncryptedBytes, 0, |
| iv.length); |
| System.arraycopy(encryptedBytes, 0, finalEncryptedBytes, |
| iv.length, |
| encryptedBytes.length); |
| |
| String base64EncodedEncryptedOctets = Base64.encode(finalEncryptedBytes); |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypted octets:\n" + base64EncodedEncryptedOctets); |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypted octets length = " + |
| base64EncodedEncryptedOctets.length()); |
| |
| try { |
| CipherData cd = _ed.getCipherData(); |
| CipherValue cv = cd.getCipherValue(); |
| // cv.setValue(base64EncodedEncryptedOctets.getBytes()); |
| cv.setValue(base64EncodedEncryptedOctets); |
| |
| if (contentMode) { |
| _ed.setType( |
| new URI(EncryptionConstants.TYPE_CONTENT).toString()); |
| } else { |
| _ed.setType( |
| new URI(EncryptionConstants.TYPE_ELEMENT).toString()); |
| } |
| EncryptionMethod method = |
| _factory.newEncryptionMethod(new URI(_algorithm).toString()); |
| _ed.setEncryptionMethod(method); |
| } catch (URI.MalformedURIException mfue) { |
| throw new XMLEncryptionException("empty", mfue); |
| } |
| return (_ed); |
| } |
| |
| |
| |
| public EncryptedData encryptData(Document context, byte [] serializedOctets, boolean contentMode) throws |
| /* XMLEncryption */ Exception { |
| logger.log(java.util.logging.Level.FINE, "Encrypting element..."); |
| if (null == context) |
| logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
| if (null == serializedOctets) |
| logger.log(java.util.logging.Level.SEVERE, "Canonicalized Data is unexpectedly null..."); |
| if (_cipherMode != ENCRYPT_MODE) |
| logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE..."); |
| |
| _contextDocument = context; |
| |
| if (_algorithm == null) { |
| throw new XMLEncryptionException("XMLCipher instance without transformation specified"); |
| } |
| |
| |
| logger.log(java.util.logging.Level.FINE, "Serialized octets:\n" + serializedOctets); |
| |
| byte[] encryptedBytes = null; |
| |
| // Now create the working cipher if none was created already |
| Cipher c; |
| if (_contextCipher == null) { |
| String jceAlgorithm = |
| JCEMapper.translateURItoJCEID(_algorithm); |
| |
| logger.log(java.util.logging.Level.FINE, "alg = " + jceAlgorithm); |
| |
| try { |
| if (_requestedJCEProvider == null) |
| c = Cipher.getInstance(jceAlgorithm); |
| else |
| c = Cipher.getInstance(jceAlgorithm, _requestedJCEProvider); |
| } catch (NoSuchAlgorithmException nsae) { |
| throw new XMLEncryptionException("empty", nsae); |
| } catch (NoSuchProviderException nspre) { |
| throw new XMLEncryptionException("empty", nspre); |
| } catch (NoSuchPaddingException nspae) { |
| throw new XMLEncryptionException("empty", nspae); |
| } |
| } else { |
| c = _contextCipher; |
| } |
| // Now perform the encryption |
| |
| try { |
| // Should internally generate an IV |
| // todo - allow user to set an IV |
| c.init(_cipherMode, _key); |
| } catch (InvalidKeyException ike) { |
| throw new XMLEncryptionException("empty", ike); |
| } |
| |
| try { |
| encryptedBytes = |
| c.doFinal(serializedOctets); |
| |
| logger.log(java.util.logging.Level.FINE, "Expected cipher.outputSize = " + |
| Integer.toString(c.getOutputSize( |
| serializedOctets.length))); |
| logger.log(java.util.logging.Level.FINE, "Actual cipher.outputSize = " + |
| Integer.toString(encryptedBytes.length)); |
| } catch (IllegalStateException ise) { |
| throw new XMLEncryptionException("empty", ise); |
| } catch (IllegalBlockSizeException ibse) { |
| throw new XMLEncryptionException("empty", ibse); |
| } catch (BadPaddingException bpe) { |
| throw new XMLEncryptionException("empty", bpe); |
| } catch (Exception uee) { |
| throw new XMLEncryptionException("empty", uee); |
| } |
| |
| // Now build up to a properly XML Encryption encoded octet stream |
| // IvParameterSpec iv; |
| |
| byte[] iv = c.getIV(); |
| byte[] finalEncryptedBytes = |
| new byte[iv.length + encryptedBytes.length]; |
| System.arraycopy(iv, 0, finalEncryptedBytes, 0, |
| iv.length); |
| System.arraycopy(encryptedBytes, 0, finalEncryptedBytes, |
| iv.length, |
| encryptedBytes.length); |
| |
| String base64EncodedEncryptedOctets = Base64.encode(finalEncryptedBytes); |
| |
| logger.log(java.util.logging.Level.FINE, "Encrypted octets:\n" + base64EncodedEncryptedOctets); |
| logger.log(java.util.logging.Level.FINE, "Encrypted octets length = " + |
| base64EncodedEncryptedOctets.length()); |
| |
| try { |
| CipherData cd = _ed.getCipherData(); |
| CipherValue cv = cd.getCipherValue(); |
| // cv.setValue(base64EncodedEncryptedOctets.getBytes()); |
| cv.setValue(base64EncodedEncryptedOctets); |
| |
| if (contentMode) { |
| _ed.setType( |
| new URI(EncryptionConstants.TYPE_CONTENT).toString()); |
| } else { |
| _ed.setType( |
| new URI(EncryptionConstants.TYPE_ELEMENT).toString()); |
| } |
| EncryptionMethod method = |
| _factory.newEncryptionMethod(new URI(_algorithm).toString()); |
| _ed.setEncryptionMethod(method); |
| } catch (URI.MalformedURIException mfue) { |
| throw new XMLEncryptionException("empty", mfue); |
| } |
| return (_ed); |
| } |
| |
| |
| /** |
| * Returns an <code>EncryptedData</code> interface. Use this operation if |
| * you want to load an <code>EncryptedData</code> structure from a DOM |
| * structure and manipulate the contents |
| * |
| * @param context the context <code>Document</code>. |
| * @param element the <code>Element</code> that will be loaded |
| * @throws XMLEncryptionException |
| * @return |
| */ |
| public EncryptedData loadEncryptedData(Document context, Element element) |
| throws XMLEncryptionException { |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Loading encrypted element..."); |
| if(null == context) |
| logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
| if(null == element) |
| logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null..."); |
| if(_cipherMode != DECRYPT_MODE) |
| logger.log(java.util.logging.Level.SEVERE, "XMLCipher unexpectedly not in DECRYPT_MODE..."); |
| |
| _contextDocument = context; |
| _ed = _factory.newEncryptedData(element); |
| |
| return (_ed); |
| } |
| |
| /** |
| * Returns an <code>EncryptedKey</code> interface. Use this operation if |
| * you want to load an <code>EncryptedKey</code> structure from a DOM |
| * structure and manipulate the contents. |
| * |
| * @param context the context <code>Document</code>. |
| * @param element the <code>Element</code> that will be loaded |
| * @return |
| * @throws XMLEncryptionException |
| */ |
| |
| public EncryptedKey loadEncryptedKey(Document context, Element element) |
| throws XMLEncryptionException { |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Loading encrypted key..."); |
| if(null == context) |
| logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null..."); |
| if(null == element) |
| logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null..."); |
| if(_cipherMode != UNWRAP_MODE && _cipherMode != DECRYPT_MODE) |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in UNWRAP_MODE or DECRYPT_MODE..."); |
| |
| _contextDocument = context; |
| _ek = _factory.newEncryptedKey(element); |
| return (_ek); |
| } |
| |
| /** |
| * Returns an <code>EncryptedKey</code> interface. Use this operation if |
| * you want to load an <code>EncryptedKey</code> structure from a DOM |
| * structure and manipulate the contents. |
| * |
| * Assumes that the context document is the document that owns the element |
| * |
| * @param element the <code>Element</code> that will be loaded |
| * @return |
| * @throws XMLEncryptionException |
| */ |
| |
| public EncryptedKey loadEncryptedKey(Element element) |
| throws XMLEncryptionException { |
| |
| return (loadEncryptedKey(element.getOwnerDocument(), element)); |
| } |
| |
| /** |
| * Encrypts a key to an EncryptedKey structure |
| * |
| * @param doc the Context document that will be used to general DOM |
| * @param key Key to encrypt (will use previously set KEK to |
| * perform encryption |
| * @return |
| * @throws XMLEncryptionException |
| */ |
| |
| public EncryptedKey encryptKey(Document doc, Key key) throws |
| XMLEncryptionException { |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypting key ..."); |
| |
| if(null == key) |
| logger.log(java.util.logging.Level.SEVERE, "Key unexpectedly null..."); |
| if(_cipherMode != WRAP_MODE) |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in WRAP_MODE..."); |
| |
| if (_algorithm == null) { |
| |
| throw new XMLEncryptionException("XMLCipher instance without transformation specified"); |
| } |
| |
| _contextDocument = doc; |
| |
| byte[] encryptedBytes = null; |
| Cipher c; |
| |
| if (_contextCipher == null) { |
| // Now create the working cipher |
| |
| String jceAlgorithm = |
| JCEMapper.translateURItoJCEID(_algorithm); |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "alg = " + jceAlgorithm); |
| |
| try { |
| if (_requestedJCEProvider == null) |
| c = Cipher.getInstance(jceAlgorithm); |
| else |
| c = Cipher.getInstance(jceAlgorithm, _requestedJCEProvider); |
| } catch (NoSuchAlgorithmException nsae) { |
| throw new XMLEncryptionException("empty", nsae); |
| } catch (NoSuchProviderException nspre) { |
| throw new XMLEncryptionException("empty", nspre); |
| } catch (NoSuchPaddingException nspae) { |
| throw new XMLEncryptionException("empty", nspae); |
| } |
| } else { |
| c = _contextCipher; |
| } |
| // Now perform the encryption |
| |
| try { |
| // Should internally generate an IV |
| // todo - allow user to set an IV |
| c.init(Cipher.WRAP_MODE, _key); |
| encryptedBytes = c.wrap(key); |
| } catch (InvalidKeyException ike) { |
| throw new XMLEncryptionException("empty", ike); |
| } catch (IllegalBlockSizeException ibse) { |
| throw new XMLEncryptionException("empty", ibse); |
| } |
| |
| String base64EncodedEncryptedOctets = Base64.encode(encryptedBytes); |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypted key octets:\n" + base64EncodedEncryptedOctets); |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypted key octets length = " + |
| base64EncodedEncryptedOctets.length()); |
| |
| CipherValue cv = _ek.getCipherData().getCipherValue(); |
| cv.setValue(base64EncodedEncryptedOctets); |
| |
| try { |
| EncryptionMethod method = _factory.newEncryptionMethod( |
| new URI(_algorithm).toString()); |
| _ek.setEncryptionMethod(method); |
| } catch (URI.MalformedURIException mfue) { |
| throw new XMLEncryptionException("empty", mfue); |
| } |
| return _ek; |
| |
| } |
| |
| /** |
| * Decrypt a key from a passed in EncryptedKey structure |
| * |
| * @param encryptedKey Previously loaded EncryptedKey that needs |
| * to be decrypted. |
| * @param algorithm Algorithm for the decryption |
| * @return a key corresponding to the give type |
| * @throws XMLEncryptionException |
| */ |
| |
| public Key decryptKey(EncryptedKey encryptedKey, String algorithm) throws |
| XMLEncryptionException { |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decrypting key from previously loaded EncryptedKey..."); |
| |
| if(_cipherMode != UNWRAP_MODE) |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in UNWRAP_MODE..."); |
| |
| if (algorithm == null) { |
| throw new XMLEncryptionException("Cannot decrypt a key without knowing the algorithm"); |
| } |
| |
| if (_key == null) { |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Trying to find a KEK via key resolvers"); |
| |
| KeyInfo ki = encryptedKey.getKeyInfo(); |
| if (ki != null) { |
| try { |
| _key = ki.getSecretKey(); |
| } |
| catch (Exception e) { |
| } |
| } |
| if (_key == null) { |
| logger.log(java.util.logging.Level.SEVERE, "XMLCipher::decryptKey called without a KEK and cannot resolve"); |
| throw new XMLEncryptionException("Unable to decrypt without a KEK"); |
| } |
| } |
| |
| // Obtain the encrypted octets |
| XMLCipherInput cipherInput = new XMLCipherInput(encryptedKey); |
| byte [] encryptedBytes = cipherInput.getBytes(); |
| |
| String jceKeyAlgorithm = |
| JCEMapper.getJCEKeyAlgorithmFromURI(algorithm); |
| |
| Cipher c; |
| if (_contextCipher == null) { |
| // Now create the working cipher |
| |
| String jceAlgorithm = |
| JCEMapper.translateURItoJCEID( |
| encryptedKey.getEncryptionMethod().getAlgorithm()); |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "JCE Algorithm = " + jceAlgorithm); |
| |
| try { |
| if (_requestedJCEProvider == null) |
| c = Cipher.getInstance(jceAlgorithm); |
| else |
| c = Cipher.getInstance(jceAlgorithm, _requestedJCEProvider); |
| } catch (NoSuchAlgorithmException nsae) { |
| throw new XMLEncryptionException("empty", nsae); |
| } catch (NoSuchProviderException nspre) { |
| throw new XMLEncryptionException("empty", nspre); |
| } catch (NoSuchPaddingException nspae) { |
| throw new XMLEncryptionException("empty", nspae); |
| } |
| } else { |
| c = _contextCipher; |
| } |
| |
| Key ret; |
| |
| try { |
| c.init(Cipher.UNWRAP_MODE, _key); |
| ret = c.unwrap(encryptedBytes, jceKeyAlgorithm, Cipher.SECRET_KEY); |
| |
| } catch (InvalidKeyException ike) { |
| throw new XMLEncryptionException("empty", ike); |
| } catch (NoSuchAlgorithmException nsae) { |
| throw new XMLEncryptionException("empty", nsae); |
| } |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decryption of key type " + algorithm + " OK"); |
| |
| return ret; |
| |
| } |
| |
| /** |
| * Decrypt a key from a passed in EncryptedKey structure. This version |
| * is used mainly internally, when the cipher already has an |
| * EncryptedData loaded. The algorithm URI will be read from the |
| * EncryptedData |
| * |
| * @param encryptedKey Previously loaded EncryptedKey that needs |
| * to be decrypted. |
| * @return a key corresponding to the give type |
| * @throws XMLEncryptionException |
| */ |
| |
| public Key decryptKey(EncryptedKey encryptedKey) throws |
| XMLEncryptionException { |
| |
| return decryptKey(encryptedKey, _ed.getEncryptionMethod().getAlgorithm()); |
| |
| } |
| |
| /** |
| * Removes the contents of a <code>Node</code>. |
| * |
| * @param node the <code>Node</code> to clear. |
| */ |
| private void removeContent(Node node) { |
| NodeList list = node.getChildNodes(); |
| if (list.getLength() > 0) { |
| Node n = list.item(0); |
| if (null != n) { |
| n.getParentNode().removeChild(n); |
| } |
| removeContent(node); |
| } |
| } |
| |
| /** |
| * Decrypts <code>EncryptedData</code> in a single-part operation. |
| * |
| * @param element the <code>EncryptedData</code> to decrypt. |
| * @return the <code>Node</code> as a result of the decrypt operation. |
| * @throws XMLEncryptionException |
| */ |
| private Document decryptElement(Element element) throws |
| XMLEncryptionException { |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decrypting element..."); |
| |
| if(_cipherMode != DECRYPT_MODE) |
| logger.log(java.util.logging.Level.SEVERE, "XMLCipher unexpectedly not in DECRYPT_MODE..."); |
| |
| String octets; |
| try { |
| octets = new String(decryptToByteArray(element), "UTF-8"); |
| } catch (UnsupportedEncodingException uee) { |
| throw new XMLEncryptionException("empty", uee); |
| } |
| |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decrypted octets:\n" + octets); |
| |
| Node sourceParent = element.getParentNode(); |
| |
| DocumentFragment decryptedFragment = |
| _serializer.deserialize(octets, sourceParent); |
| |
| |
| // The de-serialiser returns a fragment whose children we need to |
| // take on. |
| |
| if (sourceParent instanceof Document) { |
| |
| // If this is a content decryption, this may have problems |
| |
| _contextDocument.removeChild(_contextDocument.getDocumentElement()); |
| _contextDocument.appendChild(decryptedFragment); |
| } |
| else { |
| sourceParent.replaceChild(decryptedFragment, element); |
| |
| } |
| |
| return (_contextDocument); |
| } |
| |
| |
| /** |
| * |
| * @param element |
| * @return |
| * @throws XMLEncryptionException |
| */ |
| private Document decryptElementContent(Element element) throws |
| XMLEncryptionException { |
| Element e = (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTEDDATA).item(0); |
| |
| if (null == e) { |
| throw new XMLEncryptionException("No EncryptedData child element."); |
| } |
| |
| return (decryptElement(e)); |
| } |
| |
| /** |
| * Decrypt an EncryptedData element to a byte array |
| * |
| * When passed in an EncryptedData node, returns the decryption |
| * as a byte array. |
| * |
| * Does not modify the source document |
| * @param element |
| * @return |
| * @throws XMLEncryptionException |
| */ |
| |
| public byte[] decryptToByteArray(Element element) |
| throws XMLEncryptionException { |
| |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decrypting to ByteArray..."); |
| |
| if(_cipherMode != DECRYPT_MODE) |
| logger.log(java.util.logging.Level.SEVERE, "XMLCipher unexpectedly not in DECRYPT_MODE..."); |
| |
| EncryptedData encryptedData = _factory.newEncryptedData(element); |
| |
| if (_key == null) { |
| |
| KeyInfo ki = encryptedData.getKeyInfo(); |
| |
| if (ki != null) { |
| try { |
| // Add a EncryptedKey resolver |
| ki.registerInternalKeyResolver( |
| new EncryptedKeyResolver(encryptedData. |
| getEncryptionMethod(). |
| getAlgorithm(), |
| _kek)); |
| _key = ki.getSecretKey(); |
| } catch (KeyResolverException kre) { |
| // We will throw in a second... |
| } |
| } |
| |
| if (_key == null) { |
| logger.log(java.util.logging.Level.SEVERE, "XMLCipher::decryptElement called without a key and unable to resolve"); |
| |
| throw new XMLEncryptionException("encryption.nokey"); |
| } |
| } |
| |
| // Obtain the encrypted octets |
| XMLCipherInput cipherInput = new XMLCipherInput(encryptedData); |
| byte [] encryptedBytes = cipherInput.getBytes(); |
| |
| // Now create the working cipher |
| |
| String jceAlgorithm = |
| JCEMapper.translateURItoJCEID(encryptedData.getEncryptionMethod().getAlgorithm()); |
| |
| Cipher c; |
| try { |
| if (_requestedJCEProvider == null) |
| c = Cipher.getInstance(jceAlgorithm); |
| else |
| c = Cipher.getInstance(jceAlgorithm, _requestedJCEProvider); |
| } catch (NoSuchAlgorithmException nsae) { |
| throw new XMLEncryptionException("empty", nsae); |
| } catch (NoSuchProviderException nspre) { |
| throw new XMLEncryptionException("empty", nspre); |
| } catch (NoSuchPaddingException nspae) { |
| throw new XMLEncryptionException("empty", nspae); |
| } |
| |
| // Calculate the IV length and copy out |
| |
| // For now, we only work with Block ciphers, so this will work. |
| // This should probably be put into the JCE mapper. |
| |
| int ivLen = c.getBlockSize(); |
| byte[] ivBytes = new byte[ivLen]; |
| |
| // You may be able to pass the entire piece in to IvParameterSpec |
| // and it will only take the first x bytes, but no way to be certain |
| // that this will work for every JCE provider, so lets copy the |
| // necessary bytes into a dedicated array. |
| |
| System.arraycopy(encryptedBytes, 0, ivBytes, 0, ivLen); |
| IvParameterSpec iv = new IvParameterSpec(ivBytes); |
| |
| try { |
| c.init(_cipherMode, _key, iv); |
| } catch (InvalidKeyException ike) { |
| throw new XMLEncryptionException("empty", ike); |
| } catch (InvalidAlgorithmParameterException iape) { |
| throw new XMLEncryptionException("empty", iape); |
| } |
| |
| byte[] plainBytes; |
| |
| try { |
| plainBytes = c.doFinal(encryptedBytes, |
| ivLen, |
| encryptedBytes.length - ivLen); |
| |
| } catch (IllegalBlockSizeException ibse) { |
| throw new XMLEncryptionException("empty", ibse); |
| } catch (BadPaddingException bpe) { |
| throw new XMLEncryptionException("empty", bpe); |
| } |
| |
| return (plainBytes); |
| } |
| |
| /* |
| * Expose the interface for creating XML Encryption objects |
| */ |
| |
| /** |
| * Creates an <code>EncryptedData</code> <code>Element</code>. |
| * |
| * The newEncryptedData and newEncryptedKey methods create fairly complete |
| * elements that are immediately useable. All the other create* methods |
| * return bare elements that still need to be built upon. |
| *<p> |
| * An EncryptionMethod will still need to be added however |
| * |
| * @param type Either REFERENCE_TYPE or VALUE_TYPE - defines what kind of |
| * CipherData this EncryptedData will contain. |
| * @param value the Base 64 encoded, encrypted text to wrap in the |
| * <code>EncryptedData</code> or the URI to set in the CipherReference |
| * (usage will depend on the <code>type</code> |
| * @return the <code>EncryptedData</code> <code>Element</code>. |
| * |
| * <!-- |
| * <EncryptedData Id[OPT] Type[OPT] MimeType[OPT] Encoding[OPT]> |
| * <EncryptionMethod/>[OPT] |
| * <ds:KeyInfo>[OPT] |
| * <EncryptedKey/>[OPT] |
| * <AgreementMethod/>[OPT] |
| * <ds:KeyName/>[OPT] |
| * <ds:RetrievalMethod/>[OPT] |
| * <ds:[MUL]/>[OPT] |
| * </ds:KeyInfo> |
| * <CipherData>[MAN] |
| * <CipherValue/> XOR <CipherReference/> |
| * </CipherData> |
| * <EncryptionProperties/>[OPT] |
| * </EncryptedData> |
| * --> |
| * @throws XMLEncryptionException |
| */ |
| |
| public EncryptedData createEncryptedData(int type, String value) throws |
| XMLEncryptionException { |
| EncryptedData result = null; |
| CipherData data = null; |
| |
| switch (type) { |
| case CipherData.REFERENCE_TYPE: |
| CipherReference cipherReference = _factory.newCipherReference( |
| value); |
| data = _factory.newCipherData(type); |
| data.setCipherReference(cipherReference); |
| result = _factory.newEncryptedData(data); |
| break; |
| case CipherData.VALUE_TYPE: |
| CipherValue cipherValue = _factory.newCipherValue(value); |
| data = _factory.newCipherData(type); |
| data.setCipherValue(cipherValue); |
| result = _factory.newEncryptedData(data); |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * Creates an <code>EncryptedKey</code> <code>Element</code>. |
| * |
| * The newEncryptedData and newEncryptedKey methods create fairly complete |
| * elements that are immediately useable. All the other create* methods |
| * return bare elements that still need to be built upon. |
| *<p> |
| * An EncryptionMethod will still need to be added however |
| * |
| * @param type Either REFERENCE_TYPE or VALUE_TYPE - defines what kind of |
| * CipherData this EncryptedData will contain. |
| * @param value the Base 64 encoded, encrypted text to wrap in the |
| * <code>EncryptedKey</code> or the URI to set in the CipherReference |
| * (usage will depend on the <code>type</code> |
| * @return the <code>EncryptedKey</code> <code>Element</code>. |
| * |
| * <!-- |
| * <EncryptedKey Id[OPT] Type[OPT] MimeType[OPT] Encoding[OPT]> |
| * <EncryptionMethod/>[OPT] |
| * <ds:KeyInfo>[OPT] |
| * <EncryptedKey/>[OPT] |
| * <AgreementMethod/>[OPT] |
| * <ds:KeyName/>[OPT] |
| * <ds:RetrievalMethod/>[OPT] |
| * <ds:[MUL]/>[OPT] |
| * </ds:KeyInfo> |
| * <CipherData>[MAN] |
| * <CipherValue/> XOR <CipherReference/> |
| * </CipherData> |
| * <EncryptionProperties/>[OPT] |
| * </EncryptedData> |
| * --> |
| * @throws XMLEncryptionException |
| */ |
| |
| public EncryptedKey createEncryptedKey(int type, String value) throws |
| XMLEncryptionException { |
| EncryptedKey result = null; |
| CipherData data = null; |
| |
| switch (type) { |
| case CipherData.REFERENCE_TYPE: |
| CipherReference cipherReference = _factory.newCipherReference( |
| value); |
| data = _factory.newCipherData(type); |
| data.setCipherReference(cipherReference); |
| result = _factory.newEncryptedKey(data); |
| break; |
| case CipherData.VALUE_TYPE: |
| CipherValue cipherValue = _factory.newCipherValue(value); |
| data = _factory.newCipherData(type); |
| data.setCipherValue(cipherValue); |
| result = _factory.newEncryptedKey(data); |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * Create an AgreementMethod object |
| * |
| * @param algorithm Algorithm of the agreement method |
| * @return |
| */ |
| |
| public AgreementMethod createAgreementMethod(String algorithm) { |
| return (_factory.newAgreementMethod(algorithm)); |
| } |
| |
| /** |
| * Create a CipherData object |
| * |
| * @param type Type of this CipherData (either VALUE_TUPE or |
| * REFERENCE_TYPE) |
| * @return |
| */ |
| |
| public CipherData createCipherData(int type) { |
| return (_factory.newCipherData(type)); |
| } |
| |
| /** |
| * Create a CipherReference object |
| * |
| * @return |
| * @param uri The URI that the reference will refer |
| */ |
| |
| public CipherReference createCipherReference(String uri) { |
| return (_factory.newCipherReference(uri)); |
| } |
| |
| /** |
| * Create a CipherValue element |
| * |
| * @param value The value to set the ciphertext to |
| * @return |
| */ |
| |
| public CipherValue createCipherValue(String value) { |
| return (_factory.newCipherValue(value)); |
| } |
| |
| /** |
| * Create an EncryptedMethod object |
| * |
| * @param algorithm Algorithm for the encryption |
| * @return |
| */ |
| public EncryptionMethod createEncryptionMethod(String algorithm) { |
| return (_factory.newEncryptionMethod(algorithm)); |
| } |
| |
| /** |
| * Create an EncryptedProperties element |
| * @return |
| */ |
| public EncryptionProperties createEncryptionProperties() { |
| return (_factory.newEncryptionProperties()); |
| } |
| |
| /** |
| * Create a new EncryptionProperty element |
| * @return |
| */ |
| public EncryptionProperty createEncryptionProperty() { |
| return (_factory.newEncryptionProperty()); |
| } |
| |
| /** |
| * Create a new ReferenceList object |
| * @return |
| * @param type |
| */ |
| public ReferenceList createReferenceList(int type) { |
| return (_factory.newReferenceList(type)); |
| } |
| |
| /** |
| * Create a new Transforms object |
| * <p> |
| * <b>Note</b>: A context document <i>must</i> have been set |
| * elsewhere (possibly via a call to doFinal). If not, use the |
| * createTransforms(Document) method. |
| * @return |
| */ |
| |
| public Transforms createTransforms() { |
| return (_factory.newTransforms()); |
| } |
| |
| /** |
| * Create a new Transforms object |
| * |
| * Because the handling of Transforms is currently done in the signature |
| * code, the creation of a Transforms object <b>requires</b> a |
| * context document. |
| * |
| * @param doc Document that will own the created Transforms node |
| * @return |
| */ |
| public Transforms createTransforms(Document doc) { |
| return (_factory.newTransforms(doc)); |
| } |
| |
| /** |
| * Converts <code>String</code>s into <code>Node</code>s and visa versa. |
| * <p> |
| * <b>NOTE:</b> For internal use only. |
| * |
| * @author Axl Mattheus |
| */ |
| |
| private class Serializer { |
| /** |
| * Initialize the <code>XMLSerializer</code> with the specified context |
| * <code>Document</code>. |
| * <p/> |
| * Setup OutputFormat in a way that the serialization does <b>not</b> |
| * modifiy the contents, that is it shall not do any pretty printing |
| * and so on. This would destroy the original content before |
| * encryption. If that content was signed before encryption and the |
| * serialization modifies the content the signature verification will |
| * fail. |
| */ |
| Serializer() { |
| } |
| |
| /** |
| * Returns a <code>String</code> representation of the specified |
| * <code>Document</code>. |
| * <p/> |
| * Refer also to comments about setup of format. |
| * |
| * @param document the <code>Document</code> to serialize. |
| * @return the <code>String</code> representation of the serilaized |
| * <code>Document</code>. |
| * @throws Exception |
| */ |
| String serialize(Document document) throws Exception { |
| return canonSerialize(document); |
| } |
| |
| /** |
| * Returns a <code>String</code> representation of the specified |
| * <code>Element</code>. |
| * <p/> |
| * Refer also to comments about setup of format. |
| * |
| * @param element the <code>Element</code> to serialize. |
| * @return the <code>String</code> representation of the serilaized |
| * <code>Element</code>. |
| * @throws Exception |
| */ |
| String serialize(Element element) throws Exception { |
| return canonSerialize(element); |
| } |
| |
| /** |
| * Returns a <code>String</code> representation of the specified |
| * <code>NodeList</code>. |
| * <p/> |
| * This is a special case because the NodeList may represent a |
| * <code>DocumentFragment</code>. A document fragement may be a |
| * non-valid XML document (refer to appropriate description of |
| * W3C) because it my start with a non-element node, e.g. a text |
| * node. |
| * <p/> |
| * The methods first converts the node list into a document fragment. |
| * Special care is taken to not destroy the current document, thus |
| * the method clones the nodes (deep cloning) before it appends |
| * them to the document fragment. |
| * <p/> |
| * Refer also to comments about setup of format. |
| * |
| * @param content the <code>NodeList</code> to serialize. |
| * @return the <code>String</code> representation of the serilaized |
| * <code>NodeList</code>. |
| * @throws Exception |
| */ |
| String serialize(NodeList content) throws Exception { //XMLEncryptionException { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| _canon.setWriter(baos); |
| _canon.notReset(); |
| for (int i = 0; i < content.getLength(); i++) { |
| _canon.canonicalizeSubtree(content.item(i)); |
| } |
| baos.close(); |
| return baos.toString("UTF-8"); |
| } |
| |
| /** |
| * Use the Canoncializer to serialize the node |
| * @param node |
| * @return |
| * @throws Exception |
| */ |
| String canonSerialize(Node node) throws Exception { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| _canon.setWriter(baos); |
| _canon.notReset(); |
| _canon.canonicalizeSubtree(node); |
| baos.close(); |
| return baos.toString("UTF-8"); |
| } |
| /** |
| * @param source |
| * @param ctx |
| * @return |
| * @throws XMLEncryptionException |
| * |
| */ |
| DocumentFragment deserialize(String source, Node ctx) throws XMLEncryptionException { |
| DocumentFragment result; |
| final String tagname = "fragment"; |
| |
| // Create the context to parse the document against |
| StringBuffer sb; |
| |
| sb = new StringBuffer(); |
| sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><"+tagname); |
| |
| // Run through each node up to the document node and find any |
| // xmlns: nodes |
| |
| Node wk = ctx; |
| |
| while (wk != null) { |
| |
| NamedNodeMap atts = wk.getAttributes(); |
| int length; |
| if (atts != null) |
| length = atts.getLength(); |
| else |
| length = 0; |
| |
| for (int i = 0 ; i < length ; ++i) { |
| Node att = atts.item(i); |
| if (att.getNodeName().startsWith("xmlns:") || |
| att.getNodeName().equals("xmlns")) { |
| |
| // Check to see if this node has already been found |
| Node p = ctx; |
| boolean found = false; |
| while (p != wk) { |
| NamedNodeMap tstAtts = p.getAttributes(); |
| if (tstAtts != null && |
| tstAtts.getNamedItem(att.getNodeName()) != null) { |
| found = true; |
| break; |
| } |
| p = p.getParentNode(); |
| } |
| if (found == false) { |
| |
| // This is an attribute node |
| sb.append(" " + att.getNodeName() + "=\"" + |
| att.getNodeValue() + "\""); |
| } |
| } |
| } |
| wk = wk.getParentNode(); |
| } |
| sb.append(">" + source + "</" + tagname + ">"); |
| String fragment = sb.toString(); |
| |
| try { |
| DocumentBuilderFactory dbf = |
| DocumentBuilderFactory.newInstance(); |
| dbf.setNamespaceAware(true); |
| dbf.setAttribute("http://xml.org/sax/features/namespaces", Boolean.TRUE); |
| DocumentBuilder db = dbf.newDocumentBuilder(); |
| Document d = db.parse( |
| new InputSource(new StringReader(fragment))); |
| |
| Element fragElt = (Element) _contextDocument.importNode( |
| d.getDocumentElement(), true); |
| result = _contextDocument.createDocumentFragment(); |
| Node child = fragElt.getFirstChild(); |
| while (child != null) { |
| fragElt.removeChild(child); |
| result.appendChild(child); |
| child = fragElt.getFirstChild(); |
| } |
| // String outp = serialize(d); |
| |
| } catch (SAXException se) { |
| throw new XMLEncryptionException("empty", se); |
| } catch (ParserConfigurationException pce) { |
| throw new XMLEncryptionException("empty", pce); |
| } catch (IOException ioe) { |
| throw new XMLEncryptionException("empty", ioe); |
| } |
| |
| return (result); |
| } |
| } |
| |
| |
| /** |
| * |
| * @author Axl Mattheus |
| */ |
| private class Factory { |
| /** |
| * @param algorithm |
| * @return |
| * |
| */ |
| AgreementMethod newAgreementMethod(String algorithm) { |
| return (new AgreementMethodImpl(algorithm)); |
| } |
| |
| /** |
| * @param type |
| * @return |
| * |
| */ |
| CipherData newCipherData(int type) { |
| return (new CipherDataImpl(type)); |
| } |
| |
| /** |
| * @param uri |
| * @return |
| * |
| */ |
| CipherReference newCipherReference(String uri) { |
| return (new CipherReferenceImpl(uri)); |
| } |
| |
| /** |
| * @param value |
| * @return |
| * |
| */ |
| CipherValue newCipherValue(String value) { |
| return (new CipherValueImpl(value)); |
| } |
| |
| /** |
| * |
| |
| CipherValue newCipherValue(byte[] value) { |
| return (new CipherValueImpl(value)); |
| } |
| */ |
| /** |
| * @param data |
| * @return |
| * |
| */ |
| EncryptedData newEncryptedData(CipherData data) { |
| return (new EncryptedDataImpl(data)); |
| } |
| |
| /** |
| * @param data |
| * @return |
| * |
| */ |
| EncryptedKey newEncryptedKey(CipherData data) { |
| return (new EncryptedKeyImpl(data)); |
| } |
| |
| /** |
| * @param algorithm |
| * @return |
| * |
| */ |
| EncryptionMethod newEncryptionMethod(String algorithm) { |
| return (new EncryptionMethodImpl(algorithm)); |
| } |
| |
| /** |
| * @return |
| * |
| */ |
| EncryptionProperties newEncryptionProperties() { |
| return (new EncryptionPropertiesImpl()); |
| } |
| |
| /** |
| * @return |
| * |
| */ |
| EncryptionProperty newEncryptionProperty() { |
| return (new EncryptionPropertyImpl()); |
| } |
| |
| /** |
| * @param type |
| * @return |
| * |
| */ |
| ReferenceList newReferenceList(int type) { |
| return (new ReferenceListImpl(type)); |
| } |
| |
| /** |
| * @return |
| * |
| */ |
| Transforms newTransforms() { |
| return (new TransformsImpl()); |
| } |
| |
| /** |
| * @param doc |
| * @return |
| * |
| */ |
| Transforms newTransforms(Document doc) { |
| return (new TransformsImpl(doc)); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * @throws XMLEncryptionException |
| * |
| */ |
| // <element name="AgreementMethod" type="xenc:AgreementMethodType"/> |
| // <complexType name="AgreementMethodType" mixed="true"> |
| // <sequence> |
| // <element name="KA-Nonce" minOccurs="0" type="base64Binary"/> |
| // <!-- <element ref="ds:DigestMethod" minOccurs="0"/> --> |
| // <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> |
| // <element name="OriginatorKeyInfo" minOccurs="0" type="ds:KeyInfoType"/> |
| // <element name="RecipientKeyInfo" minOccurs="0" type="ds:KeyInfoType"/> |
| // </sequence> |
| // <attribute name="Algorithm" type="anyURI" use="required"/> |
| // </complexType> |
| AgreementMethod newAgreementMethod(Element element) throws |
| XMLEncryptionException { |
| if (null == element) { |
| //complain |
| } |
| |
| String algorithm = element.getAttributeNS(null, |
| EncryptionConstants._ATT_ALGORITHM); |
| AgreementMethod result = newAgreementMethod(algorithm); |
| |
| Element kaNonceElement = (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_KA_NONCE).item(0); |
| if (null != kaNonceElement) { |
| result.setKANonce(kaNonceElement.getNodeValue().getBytes()); |
| } |
| // TODO: /////////////////////////////////////////////////////////// |
| // Figure out how to make this pesky line work.. |
| // <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> |
| |
| // TODO: Work out how to handle relative URI |
| |
| Element originatorKeyInfoElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ORIGINATORKEYINFO).item(0); |
| if (null != originatorKeyInfoElement) { |
| try { |
| result.setOriginatorKeyInfo( |
| new KeyInfo(originatorKeyInfoElement, null)); |
| } catch (XMLSecurityException xse) { |
| throw new XMLEncryptionException("empty", xse); |
| } |
| } |
| |
| // TODO: Work out how to handle relative URI |
| |
| Element recipientKeyInfoElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_RECIPIENTKEYINFO).item(0); |
| if (null != recipientKeyInfoElement) { |
| try { |
| result.setRecipientKeyInfo( |
| new KeyInfo(recipientKeyInfoElement, null)); |
| } catch (XMLSecurityException xse) { |
| throw new XMLEncryptionException("empty", xse); |
| } |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * @throws XMLEncryptionException |
| * |
| */ |
| // <element name='CipherData' type='xenc:CipherDataType'/> |
| // <complexType name='CipherDataType'> |
| // <choice> |
| // <element name='CipherValue' type='base64Binary'/> |
| // <element ref='xenc:CipherReference'/> |
| // </choice> |
| // </complexType> |
| CipherData newCipherData(Element element) throws |
| XMLEncryptionException { |
| if (null == element) { |
| // complain |
| } |
| |
| int type = 0; |
| Element e = null; |
| if (element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CIPHERVALUE).getLength() > 0) { |
| type = CipherData.VALUE_TYPE; |
| e = (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CIPHERVALUE).item(0); |
| } else if (element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CIPHERREFERENCE).getLength() > 0) { |
| type = CipherData.REFERENCE_TYPE; |
| e = (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CIPHERREFERENCE).item(0); |
| } |
| |
| CipherData result = newCipherData(type); |
| if (type == CipherData.VALUE_TYPE) { |
| result.setCipherValue(newCipherValue(e)); |
| } else if (type == CipherData.REFERENCE_TYPE) { |
| result.setCipherReference(newCipherReference(e)); |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * @throws XMLEncryptionException |
| * |
| */ |
| // <element name='CipherReference' type='xenc:CipherReferenceType'/> |
| // <complexType name='CipherReferenceType'> |
| // <sequence> |
| // <element name='Transforms' type='xenc:TransformsType' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='URI' type='anyURI' use='required'/> |
| // </complexType> |
| CipherReference newCipherReference(Element element) throws |
| XMLEncryptionException { |
| |
| Attr URIAttr = |
| element.getAttributeNodeNS(null, EncryptionConstants._ATT_URI); |
| CipherReference result = new CipherReferenceImpl(URIAttr); |
| |
| // Find any Transforms |
| |
| NodeList transformsElements = element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_TRANSFORMS); |
| Element transformsElement = |
| (Element) transformsElements.item(0); |
| |
| if (transformsElement != null) { |
| if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Creating a DSIG based Transforms element"); |
| try { |
| result.setTransforms(new TransformsImpl(transformsElement)); |
| } |
| catch (XMLSignatureException xse) { |
| throw new XMLEncryptionException("empty", xse); |
| } catch (InvalidTransformException ite) { |
| throw new XMLEncryptionException("empty", ite); |
| } catch (XMLSecurityException xse) { |
| throw new XMLEncryptionException("empty", xse); |
| } |
| |
| } |
| |
| return result; |
| } |
| |
| /** |
| * @param element |
| * @return |
| * |
| */ |
| CipherValue newCipherValue(Element element) { |
| String value = XMLUtils.getFullTextChildrenFromElement(element); |
| |
| CipherValue result = newCipherValue(value); |
| |
| return (result); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * @throws XMLEncryptionException |
| * |
| */ |
| // <complexType name='EncryptedType' abstract='true'> |
| // <sequence> |
| // <element name='EncryptionMethod' type='xenc:EncryptionMethodType' |
| // minOccurs='0'/> |
| // <element ref='ds:KeyInfo' minOccurs='0'/> |
| // <element ref='xenc:CipherData'/> |
| // <element ref='xenc:EncryptionProperties' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // <attribute name='Type' type='anyURI' use='optional'/> |
| // <attribute name='MimeType' type='string' use='optional'/> |
| // <attribute name='Encoding' type='anyURI' use='optional'/> |
| // </complexType> |
| // <element name='EncryptedData' type='xenc:EncryptedDataType'/> |
| // <complexType name='EncryptedDataType'> |
| // <complexContent> |
| // <extension base='xenc:EncryptedType'/> |
| // </complexContent> |
| // </complexType> |
| EncryptedData newEncryptedData(Element element) throws |
| XMLEncryptionException { |
| EncryptedData result = null; |
| |
| NodeList dataElements = element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CIPHERDATA); |
| |
| // Need to get the last CipherData found, as earlier ones will |
| // be for elements in the KeyInfo lists |
| |
| Element dataElement = |
| (Element) dataElements.item(dataElements.getLength() - 1); |
| |
| CipherData data = newCipherData(dataElement); |
| |
| result = newEncryptedData(data); |
| |
| try { |
| result.setId(element.getAttributeNS( |
| null, EncryptionConstants._ATT_ID)); |
| result.setType(new URI( |
| element.getAttributeNS( |
| null, EncryptionConstants._ATT_TYPE)).toString()); |
| result.setMimeType(element.getAttributeNS( |
| null, EncryptionConstants._ATT_MIMETYPE)); |
| result.setEncoding(new URI( |
| element.getAttributeNS( |
| null, Constants._ATT_ENCODING)).toString()); |
| } catch (URI.MalformedURIException mfue) { |
| // do nothing |
| } |
| |
| Element encryptionMethodElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTIONMETHOD).item(0); |
| if (null != encryptionMethodElement) { |
| result.setEncryptionMethod(newEncryptionMethod( |
| encryptionMethodElement)); |
| } |
| |
| // BFL 16/7/03 - simple implementation |
| // TODO: Work out how to handle relative URI |
| |
| Element keyInfoElement = |
| (Element) element.getElementsByTagNameNS( |
| Constants.SignatureSpecNS, Constants._TAG_KEYINFO).item(0); |
| if (null != keyInfoElement) { |
| try { |
| result.setKeyInfo(new KeyInfo(keyInfoElement, null)); |
| } catch (XMLSecurityException xse) { |
| throw new XMLEncryptionException("Error loading Key Info", |
| xse); |
| } |
| } |
| |
| // TODO: Implement |
| Element encryptionPropertiesElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTIONPROPERTIES).item(0); |
| if (null != encryptionPropertiesElement) { |
| result.setEncryptionProperties( |
| newEncryptionProperties(encryptionPropertiesElement)); |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * @throws XMLEncryptionException |
| * |
| */ |
| // <complexType name='EncryptedType' abstract='true'> |
| // <sequence> |
| // <element name='EncryptionMethod' type='xenc:EncryptionMethodType' |
| // minOccurs='0'/> |
| // <element ref='ds:KeyInfo' minOccurs='0'/> |
| // <element ref='xenc:CipherData'/> |
| // <element ref='xenc:EncryptionProperties' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // <attribute name='Type' type='anyURI' use='optional'/> |
| // <attribute name='MimeType' type='string' use='optional'/> |
| // <attribute name='Encoding' type='anyURI' use='optional'/> |
| // </complexType> |
| // <element name='EncryptedKey' type='xenc:EncryptedKeyType'/> |
| // <complexType name='EncryptedKeyType'> |
| // <complexContent> |
| // <extension base='xenc:EncryptedType'> |
| // <sequence> |
| // <element ref='xenc:ReferenceList' minOccurs='0'/> |
| // <element name='CarriedKeyName' type='string' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='Recipient' type='string' use='optional'/> |
| // </extension> |
| // </complexContent> |
| // </complexType> |
| EncryptedKey newEncryptedKey(Element element) throws |
| XMLEncryptionException { |
| EncryptedKey result = null; |
| NodeList dataElements = element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CIPHERDATA); |
| Element dataElement = |
| (Element) dataElements.item(dataElements.getLength() - 1); |
| |
| CipherData data = newCipherData(dataElement); |
| result = newEncryptedKey(data); |
| |
| try { |
| result.setId(element.getAttributeNS( |
| null, EncryptionConstants._ATT_ID)); |
| result.setType(new URI( |
| element.getAttributeNS( |
| null, EncryptionConstants._ATT_TYPE)).toString()); |
| result.setMimeType(element.getAttributeNS( |
| null, EncryptionConstants._ATT_MIMETYPE)); |
| result.setEncoding(new URI( |
| element.getAttributeNS( |
| null, Constants._ATT_ENCODING)).toString()); |
| result.setRecipient(element.getAttributeNS( |
| null, EncryptionConstants._ATT_RECIPIENT)); |
| } catch (URI.MalformedURIException mfue) { |
| // do nothing |
| } |
| |
| Element encryptionMethodElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTIONMETHOD).item(0); |
| if (null != encryptionMethodElement) { |
| result.setEncryptionMethod(newEncryptionMethod( |
| encryptionMethodElement)); |
| } |
| |
| Element keyInfoElement = |
| (Element) element.getElementsByTagNameNS( |
| Constants.SignatureSpecNS, Constants._TAG_KEYINFO).item(0); |
| if (null != keyInfoElement) { |
| try { |
| result.setKeyInfo(new KeyInfo(keyInfoElement, null)); |
| } catch (XMLSecurityException xse) { |
| throw new XMLEncryptionException("Error loading Key Info", |
| xse); |
| } |
| } |
| |
| // TODO: Implement |
| Element encryptionPropertiesElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTIONPROPERTIES).item(0); |
| if (null != encryptionPropertiesElement) { |
| result.setEncryptionProperties( |
| newEncryptionProperties(encryptionPropertiesElement)); |
| } |
| |
| Element referenceListElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_REFERENCELIST).item(0); |
| if (null != referenceListElement) { |
| result.setReferenceList(newReferenceList(referenceListElement)); |
| } |
| |
| Element carriedNameElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CARRIEDKEYNAME).item(0); |
| if (null != carriedNameElement) { |
| result.setCarriedName(carriedNameElement.getNodeValue()); |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * |
| */ |
| // <complexType name='EncryptionMethodType' mixed='true'> |
| // <sequence> |
| // <element name='KeySize' minOccurs='0' type='xenc:KeySizeType'/> |
| // <element name='OAEPparams' minOccurs='0' type='base64Binary'/> |
| // <any namespace='##other' minOccurs='0' maxOccurs='unbounded'/> |
| // </sequence> |
| // <attribute name='Algorithm' type='anyURI' use='required'/> |
| // </complexType> |
| EncryptionMethod newEncryptionMethod(Element element) { |
| String algorithm = element.getAttributeNS( |
| null, EncryptionConstants._ATT_ALGORITHM); |
| EncryptionMethod result = newEncryptionMethod(algorithm); |
| |
| Element keySizeElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_KEYSIZE).item(0); |
| if (null != keySizeElement) { |
| result.setKeySize( |
| Integer.valueOf( |
| keySizeElement.getFirstChild().getNodeValue()).intValue()); |
| } |
| |
| Element oaepParamsElement = |
| (Element) element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_OAEPPARAMS).item(0); |
| if (null != oaepParamsElement) { |
| result.setOAEPparams( |
| oaepParamsElement.getNodeValue().getBytes()); |
| } |
| |
| // TODO: Make this mess work |
| // <any namespace='##other' minOccurs='0' maxOccurs='unbounded'/> |
| |
| return (result); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * |
| */ |
| // <element name='EncryptionProperties' type='xenc:EncryptionPropertiesType'/> |
| // <complexType name='EncryptionPropertiesType'> |
| // <sequence> |
| // <element ref='xenc:EncryptionProperty' maxOccurs='unbounded'/> |
| // </sequence> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // </complexType> |
| EncryptionProperties newEncryptionProperties(Element element) { |
| EncryptionProperties result = newEncryptionProperties(); |
| |
| result.setId(element.getAttributeNS( |
| null, EncryptionConstants._ATT_ID)); |
| |
| NodeList encryptionPropertyList = |
| element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTIONPROPERTY); |
| for(int i = 0; i < encryptionPropertyList.getLength(); i++) { |
| Node n = encryptionPropertyList.item(i); |
| if (null != n) { |
| result.addEncryptionProperty( |
| newEncryptionProperty((Element) n)); |
| } |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * |
| */ |
| // <element name='EncryptionProperty' type='xenc:EncryptionPropertyType'/> |
| // <complexType name='EncryptionPropertyType' mixed='true'> |
| // <choice maxOccurs='unbounded'> |
| // <any namespace='##other' processContents='lax'/> |
| // </choice> |
| // <attribute name='Target' type='anyURI' use='optional'/> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // <anyAttribute namespace="http://www.w3.org/XML/1998/namespace"/> |
| // </complexType> |
| EncryptionProperty newEncryptionProperty(Element element) { |
| EncryptionProperty result = newEncryptionProperty(); |
| |
| try { |
| result.setTarget(new URI( |
| element.getAttributeNS( |
| null, EncryptionConstants._ATT_TARGET)).toString()); |
| } catch (URI.MalformedURIException mfue) { |
| // do nothing |
| } |
| result.setId(element.getAttributeNS( |
| null, EncryptionConstants._ATT_ID)); |
| // TODO: Make this lot work... |
| // <anyAttribute namespace="http://www.w3.org/XML/1998/namespace"/> |
| |
| // TODO: Make this work... |
| // <any namespace='##other' processContents='lax'/> |
| |
| return (result); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * |
| */ |
| // <element name='ReferenceList'> |
| // <complexType> |
| // <choice minOccurs='1' maxOccurs='unbounded'> |
| // <element name='DataReference' type='xenc:ReferenceType'/> |
| // <element name='KeyReference' type='xenc:ReferenceType'/> |
| // </choice> |
| // </complexType> |
| // </element> |
| ReferenceList newReferenceList(Element element) { |
| int type = 0; |
| if (null != element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_DATAREFERENCE).item(0)) { |
| type = ReferenceList.DATA_REFERENCE; |
| } else if (null != element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_KEYREFERENCE).item(0)) { |
| type = ReferenceList.KEY_REFERENCE; |
| } else { |
| // complain |
| } |
| |
| ReferenceList result = new ReferenceListImpl(type); |
| NodeList list = null; |
| switch (type) { |
| case ReferenceList.DATA_REFERENCE: |
| list = element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_DATAREFERENCE); |
| for (int i = 0; i < list.getLength() ; i++) { |
| String uri = ((Element) list.item(i)).getAttribute("URI"); |
| result.add(result.newDataReference(uri)); |
| } |
| break; |
| case ReferenceList.KEY_REFERENCE: |
| list = element.getElementsByTagNameNS( |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_KEYREFERENCE); |
| for (int i = 0; i < list.getLength() ; i++) { |
| String uri = ((Element) list.item(i)).getAttribute("URI"); |
| result.add(result.newKeyReference(uri)); |
| } |
| } |
| |
| return (result); |
| } |
| |
| /** |
| * @param element |
| * @return |
| * |
| */ |
| Transforms newTransforms(Element element) { |
| return (null); |
| } |
| |
| /** |
| * @param agreementMethod |
| * @return |
| * |
| */ |
| Element toElement(AgreementMethod agreementMethod) { |
| return ((AgreementMethodImpl) agreementMethod).toElement(); |
| } |
| |
| /** |
| * @param cipherData |
| * @return |
| * |
| */ |
| Element toElement(CipherData cipherData) { |
| return ((CipherDataImpl) cipherData).toElement(); |
| } |
| |
| /** |
| * @param cipherReference |
| * @return |
| * |
| */ |
| Element toElement(CipherReference cipherReference) { |
| return ((CipherReferenceImpl) cipherReference).toElement(); |
| } |
| |
| /** |
| * @param cipherValue |
| * @return |
| * |
| */ |
| Element toElement(CipherValue cipherValue) { |
| return ((CipherValueImpl) cipherValue).toElement(); |
| } |
| |
| /** |
| * @param encryptedData |
| * @return |
| * |
| */ |
| Element toElement(EncryptedData encryptedData) { |
| return ((EncryptedDataImpl) encryptedData).toElement(); |
| } |
| |
| /** |
| * @param encryptedKey |
| * @return |
| * |
| */ |
| Element toElement(EncryptedKey encryptedKey) { |
| return ((EncryptedKeyImpl) encryptedKey).toElement(); |
| } |
| |
| /** |
| * @param encryptionMethod |
| * @return |
| * |
| */ |
| Element toElement(EncryptionMethod encryptionMethod) { |
| return ((EncryptionMethodImpl) encryptionMethod).toElement(); |
| } |
| |
| /** |
| * @param encryptionProperties |
| * @return |
| * |
| */ |
| Element toElement(EncryptionProperties encryptionProperties) { |
| return ((EncryptionPropertiesImpl) encryptionProperties).toElement(); |
| } |
| |
| /** |
| * @param encryptionProperty |
| * @return |
| * |
| */ |
| Element toElement(EncryptionProperty encryptionProperty) { |
| return ((EncryptionPropertyImpl) encryptionProperty).toElement(); |
| } |
| |
| Element toElement(ReferenceList referenceList) { |
| return ((ReferenceListImpl) referenceList).toElement(); |
| } |
| |
| /** |
| * @param transforms |
| * @return |
| * |
| */ |
| Element toElement(Transforms transforms) { |
| return ((TransformsImpl) transforms).toElement(); |
| } |
| |
| // <element name="AgreementMethod" type="xenc:AgreementMethodType"/> |
| // <complexType name="AgreementMethodType" mixed="true"> |
| // <sequence> |
| // <element name="KA-Nonce" minOccurs="0" type="base64Binary"/> |
| // <!-- <element ref="ds:DigestMethod" minOccurs="0"/> --> |
| // <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> |
| // <element name="OriginatorKeyInfo" minOccurs="0" type="ds:KeyInfoType"/> |
| // <element name="RecipientKeyInfo" minOccurs="0" type="ds:KeyInfoType"/> |
| // </sequence> |
| // <attribute name="Algorithm" type="anyURI" use="required"/> |
| // </complexType> |
| private class AgreementMethodImpl implements AgreementMethod { |
| private byte[] kaNonce = null; |
| private List agreementMethodInformation = null; |
| private KeyInfo originatorKeyInfo = null; |
| private KeyInfo recipientKeyInfo = null; |
| private String algorithmURI = null; |
| |
| /** |
| * @param algorithm |
| */ |
| public AgreementMethodImpl(String algorithm) { |
| agreementMethodInformation = new LinkedList(); |
| URI tmpAlgorithm = null; |
| try { |
| tmpAlgorithm = new URI(algorithm); |
| } catch (URI.MalformedURIException fmue) { |
| //complain? |
| } |
| algorithmURI = tmpAlgorithm.toString(); |
| } |
| |
| /** @inheritDoc */ |
| public byte[] getKANonce() { |
| return (kaNonce); |
| } |
| |
| /** @inheritDoc */ |
| public void setKANonce(byte[] kanonce) { |
| kaNonce = kanonce; |
| } |
| |
| /** @inheritDoc */ |
| public Iterator getAgreementMethodInformation() { |
| return (agreementMethodInformation.iterator()); |
| } |
| |
| /** @inheritDoc */ |
| public void addAgreementMethodInformation(Element info) { |
| agreementMethodInformation.add(info); |
| } |
| |
| /** @inheritDoc */ |
| public void revoveAgreementMethodInformation(Element info) { |
| agreementMethodInformation.remove(info); |
| } |
| |
| /** @inheritDoc */ |
| public KeyInfo getOriginatorKeyInfo() { |
| return (originatorKeyInfo); |
| } |
| |
| /** @inheritDoc */ |
| public void setOriginatorKeyInfo(KeyInfo keyInfo) { |
| originatorKeyInfo = keyInfo; |
| } |
| |
| /** @inheritDoc */ |
| public KeyInfo getRecipientKeyInfo() { |
| return (recipientKeyInfo); |
| } |
| |
| /** @inheritDoc */ |
| public void setRecipientKeyInfo(KeyInfo keyInfo) { |
| recipientKeyInfo = keyInfo; |
| } |
| |
| /** @inheritDoc */ |
| public String getAlgorithm() { |
| return (algorithmURI); |
| } |
| |
| /** @param algorithm*/ |
| public void setAlgorithm(String algorithm) { |
| URI tmpAlgorithm = null; |
| try { |
| tmpAlgorithm = new URI(algorithm); |
| } catch (URI.MalformedURIException mfue) { |
| //complain |
| } |
| algorithm = tmpAlgorithm.toString(); |
| } |
| |
| // <element name="AgreementMethod" type="xenc:AgreementMethodType"/> |
| // <complexType name="AgreementMethodType" mixed="true"> |
| // <sequence> |
| // <element name="KA-Nonce" minOccurs="0" type="base64Binary"/> |
| // <!-- <element ref="ds:DigestMethod" minOccurs="0"/> --> |
| // <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> |
| // <element name="OriginatorKeyInfo" minOccurs="0" type="ds:KeyInfoType"/> |
| // <element name="RecipientKeyInfo" minOccurs="0" type="ds:KeyInfoType"/> |
| // </sequence> |
| // <attribute name="Algorithm" type="anyURI" use="required"/> |
| // </complexType> |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_AGREEMENTMETHOD); |
| result.setAttributeNS( |
| null, EncryptionConstants._ATT_ALGORITHM, algorithmURI); |
| if (null != kaNonce) { |
| result.appendChild( |
| ElementProxy.createElementForFamily( |
| _contextDocument, |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_KA_NONCE)).appendChild( |
| _contextDocument.createTextNode(new String(kaNonce))); |
| } |
| if (!agreementMethodInformation.isEmpty()) { |
| Iterator itr = agreementMethodInformation.iterator(); |
| while (itr.hasNext()) { |
| result.appendChild((Element) itr.next()); |
| } |
| } |
| if (null != originatorKeyInfo) { |
| result.appendChild(originatorKeyInfo.getElement()); |
| } |
| if (null != recipientKeyInfo) { |
| result.appendChild(recipientKeyInfo.getElement()); |
| } |
| |
| return (result); |
| } |
| } |
| |
| // <element name='CipherData' type='xenc:CipherDataType'/> |
| // <complexType name='CipherDataType'> |
| // <choice> |
| // <element name='CipherValue' type='base64Binary'/> |
| // <element ref='xenc:CipherReference'/> |
| // </choice> |
| // </complexType> |
| private class CipherDataImpl implements CipherData { |
| private static final String valueMessage = |
| "Data type is reference type."; |
| private static final String referenceMessage = |
| "Data type is value type."; |
| private CipherValue cipherValue = null; |
| private CipherReference cipherReference = null; |
| private int cipherType = Integer.MIN_VALUE; |
| |
| /** |
| * @param type |
| */ |
| public CipherDataImpl(int type) { |
| cipherType = type; |
| } |
| |
| /** @inheritDoc */ |
| public CipherValue getCipherValue() { |
| return (cipherValue); |
| } |
| |
| /** @inheritDoc */ |
| public void setCipherValue(CipherValue value) throws |
| XMLEncryptionException { |
| |
| if (cipherType == REFERENCE_TYPE) { |
| throw new XMLEncryptionException("empty", |
| new UnsupportedOperationException(valueMessage)); |
| } |
| |
| cipherValue = value; |
| } |
| |
| /** @inheritDoc */ |
| public CipherReference getCipherReference() { |
| return (cipherReference); |
| } |
| |
| /** @inheritDoc */ |
| public void setCipherReference(CipherReference reference) throws |
| XMLEncryptionException { |
| if (cipherType == VALUE_TYPE) { |
| throw new XMLEncryptionException("empty", |
| new UnsupportedOperationException(referenceMessage)); |
| } |
| |
| cipherReference = reference; |
| } |
| |
| /** @inheritDoc */ |
| public int getDataType() { |
| return (cipherType); |
| } |
| |
| // <element name='CipherData' type='xenc:CipherDataType'/> |
| // <complexType name='CipherDataType'> |
| // <choice> |
| // <element name='CipherValue' type='base64Binary'/> |
| // <element ref='xenc:CipherReference'/> |
| // </choice> |
| // </complexType> |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CIPHERDATA); |
| if (cipherType == VALUE_TYPE) { |
| result.appendChild( |
| ((CipherValueImpl) cipherValue).toElement()); |
| } else if (cipherType == REFERENCE_TYPE) { |
| result.appendChild( |
| ((CipherReferenceImpl) cipherReference).toElement()); |
| } else { |
| // complain |
| } |
| |
| return (result); |
| } |
| } |
| |
| // <element name='CipherReference' type='xenc:CipherReferenceType'/> |
| // <complexType name='CipherReferenceType'> |
| // <sequence> |
| // <element name='Transforms' type='xenc:TransformsType' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='URI' type='anyURI' use='required'/> |
| // </complexType> |
| private class CipherReferenceImpl implements CipherReference { |
| private String referenceURI = null; |
| private Transforms referenceTransforms = null; |
| private Attr referenceNode = null; |
| |
| /** |
| * @param uri |
| */ |
| public CipherReferenceImpl(String uri) { |
| /* Don't check validity of URI as may be "" */ |
| referenceURI = uri; |
| referenceNode = null; |
| } |
| |
| /** |
| * @param uri |
| */ |
| public CipherReferenceImpl(Attr uri) { |
| referenceURI = uri.getNodeValue(); |
| referenceNode = uri; |
| } |
| |
| /** @inheritDoc */ |
| public String getURI() { |
| return (referenceURI); |
| } |
| |
| /** @inheritDoc */ |
| public Attr getURIAsAttr() { |
| return (referenceNode); |
| } |
| |
| /** @inheritDoc */ |
| public Transforms getTransforms() { |
| return (referenceTransforms); |
| } |
| |
| /** @inheritDoc */ |
| public void setTransforms(Transforms transforms) { |
| referenceTransforms = transforms; |
| } |
| |
| // <element name='CipherReference' type='xenc:CipherReferenceType'/> |
| // <complexType name='CipherReferenceType'> |
| // <sequence> |
| // <element name='Transforms' type='xenc:TransformsType' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='URI' type='anyURI' use='required'/> |
| // </complexType> |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CIPHERREFERENCE); |
| result.setAttributeNS( |
| null, EncryptionConstants._ATT_URI, referenceURI); |
| if (null != referenceTransforms) { |
| result.appendChild( |
| ((TransformsImpl) referenceTransforms).toElement()); |
| } |
| |
| return (result); |
| } |
| } |
| |
| private class CipherValueImpl implements CipherValue { |
| private String cipherValue = null; |
| |
| // public CipherValueImpl(byte[] value) { |
| // cipherValue = value; |
| // } |
| |
| /** |
| * @param value |
| */ |
| public CipherValueImpl(String value) { |
| // cipherValue = value.getBytes(); |
| cipherValue = value; |
| } |
| |
| /** @inheritDoc */ |
| public String getValue() { |
| return (cipherValue); |
| } |
| |
| // public void setValue(byte[] value) { |
| // public void setValue(String value) { |
| // cipherValue = value; |
| // } |
| /** @inheritDoc */ |
| public void setValue(String value) { |
| // cipherValue = value.getBytes(); |
| cipherValue = value; |
| } |
| |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CIPHERVALUE); |
| result.appendChild(_contextDocument.createTextNode( |
| new String(cipherValue))); |
| |
| return (result); |
| } |
| } |
| |
| // <complexType name='EncryptedType' abstract='true'> |
| // <sequence> |
| // <element name='EncryptionMethod' type='xenc:EncryptionMethodType' |
| // minOccurs='0'/> |
| // <element ref='ds:KeyInfo' minOccurs='0'/> |
| // <element ref='xenc:CipherData'/> |
| // <element ref='xenc:EncryptionProperties' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // <attribute name='Type' type='anyURI' use='optional'/> |
| // <attribute name='MimeType' type='string' use='optional'/> |
| // <attribute name='Encoding' type='anyURI' use='optional'/> |
| // </complexType> |
| // <element name='EncryptedData' type='xenc:EncryptedDataType'/> |
| // <complexType name='EncryptedDataType'> |
| // <complexContent> |
| // <extension base='xenc:EncryptedType'/> |
| // </complexContent> |
| // </complexType> |
| private class EncryptedDataImpl extends EncryptedTypeImpl implements |
| EncryptedData { |
| /** |
| * @param data |
| */ |
| public EncryptedDataImpl(CipherData data) { |
| super(data); |
| } |
| |
| // <complexType name='EncryptedType' abstract='true'> |
| // <sequence> |
| // <element name='EncryptionMethod' type='xenc:EncryptionMethodType' |
| // minOccurs='0'/> |
| // <element ref='ds:KeyInfo' minOccurs='0'/> |
| // <element ref='xenc:CipherData'/> |
| // <element ref='xenc:EncryptionProperties' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // <attribute name='Type' type='anyURI' use='optional'/> |
| // <attribute name='MimeType' type='string' use='optional'/> |
| // <attribute name='Encoding' type='anyURI' use='optional'/> |
| // </complexType> |
| // <element name='EncryptedData' type='xenc:EncryptedDataType'/> |
| // <complexType name='EncryptedDataType'> |
| // <complexContent> |
| // <extension base='xenc:EncryptedType'/> |
| // </complexContent> |
| // </complexType> |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTEDDATA); |
| |
| if (null != super.getId()) { |
| result.setAttributeNS( |
| null, EncryptionConstants._ATT_ID, super.getId()); |
| } |
| if (null != super.getType()) { |
| result.setAttributeNS( |
| null, EncryptionConstants._ATT_TYPE, |
| super.getType().toString()); |
| } |
| if (null != super.getMimeType()) { |
| result.setAttributeNS( |
| null, EncryptionConstants._ATT_MIMETYPE, |
| super.getMimeType()); |
| } |
| if (null != super.getEncoding()) { |
| result.setAttributeNS( |
| null, EncryptionConstants._ATT_ENCODING, |
| super.getEncoding().toString()); |
| } |
| if (null != super.getEncryptionMethod()) { |
| result.appendChild(((EncryptionMethodImpl) |
| super.getEncryptionMethod()).toElement()); |
| } |
| if (null != super.getKeyInfo()) { |
| result.appendChild(super.getKeyInfo().getElement()); |
| } |
| |
| result.appendChild( |
| ((CipherDataImpl) super.getCipherData()).toElement()); |
| if (null != super.getEncryptionProperties()) { |
| result.appendChild(((EncryptionPropertiesImpl) |
| super.getEncryptionProperties()).toElement()); |
| } |
| |
| return (result); |
| } |
| } |
| |
| // <complexType name='EncryptedType' abstract='true'> |
| // <sequence> |
| // <element name='EncryptionMethod' type='xenc:EncryptionMethodType' |
| // minOccurs='0'/> |
| // <element ref='ds:KeyInfo' minOccurs='0'/> |
| // <element ref='xenc:CipherData'/> |
| // <element ref='xenc:EncryptionProperties' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // <attribute name='Type' type='anyURI' use='optional'/> |
| // <attribute name='MimeType' type='string' use='optional'/> |
| // <attribute name='Encoding' type='anyURI' use='optional'/> |
| // </complexType> |
| // <element name='EncryptedKey' type='xenc:EncryptedKeyType'/> |
| // <complexType name='EncryptedKeyType'> |
| // <complexContent> |
| // <extension base='xenc:EncryptedType'> |
| // <sequence> |
| // <element ref='xenc:ReferenceList' minOccurs='0'/> |
| // <element name='CarriedKeyName' type='string' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='Recipient' type='string' use='optional'/> |
| // </extension> |
| // </complexContent> |
| // </complexType> |
| private class EncryptedKeyImpl extends EncryptedTypeImpl implements |
| EncryptedKey { |
| private String keyRecipient = null; |
| private ReferenceList referenceList = null; |
| private String carriedName = null; |
| |
| /** |
| * @param data |
| */ |
| public EncryptedKeyImpl(CipherData data) { |
| super(data); |
| } |
| |
| /** @inheritDoc */ |
| public String getRecipient() { |
| return (keyRecipient); |
| } |
| |
| /** @inheritDoc */ |
| public void setRecipient(String recipient) { |
| keyRecipient = recipient; |
| } |
| |
| /** @inheritDoc */ |
| public ReferenceList getReferenceList() { |
| return (referenceList); |
| } |
| |
| /** @inheritDoc */ |
| public void setReferenceList(ReferenceList list) { |
| referenceList = list; |
| } |
| |
| /** @inheritDoc */ |
| public String getCarriedName() { |
| return (carriedName); |
| } |
| |
| /** @inheritDoc */ |
| public void setCarriedName(String name) { |
| carriedName = name; |
| } |
| |
| // <complexType name='EncryptedType' abstract='true'> |
| // <sequence> |
| // <element name='EncryptionMethod' type='xenc:EncryptionMethodType' |
| // minOccurs='0'/> |
| // <element ref='ds:KeyInfo' minOccurs='0'/> |
| // <element ref='xenc:CipherData'/> |
| // <element ref='xenc:EncryptionProperties' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // <attribute name='Type' type='anyURI' use='optional'/> |
| // <attribute name='MimeType' type='string' use='optional'/> |
| // <attribute name='Encoding' type='anyURI' use='optional'/> |
| // </complexType> |
| // <element name='EncryptedKey' type='xenc:EncryptedKeyType'/> |
| // <complexType name='EncryptedKeyType'> |
| // <complexContent> |
| // <extension base='xenc:EncryptedType'> |
| // <sequence> |
| // <element ref='xenc:ReferenceList' minOccurs='0'/> |
| // <element name='CarriedKeyName' type='string' minOccurs='0'/> |
| // </sequence> |
| // <attribute name='Recipient' type='string' use='optional'/> |
| // </extension> |
| // </complexContent> |
| // </complexType> |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTEDKEY); |
| |
| if (null != super.getId()) { |
| result.setAttributeNS( |
| null, EncryptionConstants._ATT_ID, super.getId()); |
| } |
| if (null != super.getType()) { |
| result.setAttributeNS( |
| null, EncryptionConstants._ATT_TYPE, |
| super.getType().toString()); |
| } |
| if (null != super.getMimeType()) { |
| result.setAttributeNS(null, |
| EncryptionConstants._ATT_MIMETYPE, super.getMimeType()); |
| } |
| if (null != super.getEncoding()) { |
| result.setAttributeNS(null, Constants._ATT_ENCODING, |
| super.getEncoding().toString()); |
| } |
| if (null != getRecipient()) { |
| result.setAttributeNS(null, |
| EncryptionConstants._ATT_RECIPIENT, getRecipient()); |
| } |
| if (null != super.getEncryptionMethod()) { |
| result.appendChild(((EncryptionMethodImpl) |
| super.getEncryptionMethod()).toElement()); |
| } |
| if (null != super.getKeyInfo()) { |
| result.appendChild(super.getKeyInfo().getElement()); |
| } |
| result.appendChild( |
| ((CipherDataImpl) super.getCipherData()).toElement()); |
| if (null != super.getEncryptionProperties()) { |
| result.appendChild(((EncryptionPropertiesImpl) |
| super.getEncryptionProperties()).toElement()); |
| } |
| if (referenceList != null && !referenceList.isEmpty()) { |
| result.appendChild(((ReferenceListImpl) |
| getReferenceList()).toElement()); |
| } |
| if (null != carriedName) { |
| Element element = ElementProxy.createElementForFamily( |
| _contextDocument, |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_CARRIEDKEYNAME); |
| Node node = _contextDocument.createTextNode(carriedName); |
| element.appendChild(node); |
| result.appendChild(element); |
| } |
| |
| return (result); |
| } |
| } |
| |
| private abstract class EncryptedTypeImpl { |
| private String id = null; |
| private String type = null; |
| private String mimeType = null; |
| private String encoding = null; |
| private EncryptionMethod encryptionMethod = null; |
| private KeyInfo keyInfo = null; |
| private CipherData cipherData = null; |
| private EncryptionProperties encryptionProperties = null; |
| |
| protected EncryptedTypeImpl(CipherData data) { |
| cipherData = data; |
| } |
| /** |
| * |
| * @return |
| */ |
| public String getId() { |
| return (id); |
| } |
| /** |
| * |
| * @param id |
| */ |
| public void setId(String id) { |
| this.id = id; |
| } |
| /** |
| * |
| * @return |
| */ |
| public String getType() { |
| return (type); |
| } |
| /** |
| * |
| * @param type |
| */ |
| public void setType(String type) { |
| URI tmpType = null; |
| try { |
| tmpType = new URI(type); |
| } catch (URI.MalformedURIException mfue) { |
| // complain |
| } |
| this.type = tmpType.toString(); |
| } |
| /** |
| * |
| * @return |
| */ |
| public String getMimeType() { |
| return (mimeType); |
| } |
| /** |
| * |
| * @param type |
| */ |
| public void setMimeType(String type) { |
| mimeType = type; |
| } |
| /** |
| * |
| * @return |
| */ |
| public String getEncoding() { |
| return (encoding); |
| } |
| /** |
| * |
| * @param encoding |
| */ |
| public void setEncoding(String encoding) { |
| URI tmpEncoding = null; |
| try { |
| tmpEncoding = new URI(encoding); |
| } catch (URI.MalformedURIException mfue) { |
| // complain |
| } |
| this.encoding = tmpEncoding.toString(); |
| } |
| /** |
| * |
| * @return |
| */ |
| public EncryptionMethod getEncryptionMethod() { |
| return (encryptionMethod); |
| } |
| /** |
| * |
| * @param method |
| */ |
| public void setEncryptionMethod(EncryptionMethod method) { |
| encryptionMethod = method; |
| } |
| /** |
| * |
| * @return |
| */ |
| public KeyInfo getKeyInfo() { |
| return (keyInfo); |
| } |
| /** |
| * |
| * @param info |
| */ |
| public void setKeyInfo(KeyInfo info) { |
| keyInfo = info; |
| } |
| /** |
| * |
| * @return |
| */ |
| public CipherData getCipherData() { |
| return (cipherData); |
| } |
| /** |
| * |
| * @return |
| */ |
| public EncryptionProperties getEncryptionProperties() { |
| return (encryptionProperties); |
| } |
| /** |
| * |
| * @param properties |
| */ |
| public void setEncryptionProperties( |
| EncryptionProperties properties) { |
| encryptionProperties = properties; |
| } |
| } |
| |
| // <complexType name='EncryptionMethodType' mixed='true'> |
| // <sequence> |
| // <element name='KeySize' minOccurs='0' type='xenc:KeySizeType'/> |
| // <element name='OAEPparams' minOccurs='0' type='base64Binary'/> |
| // <any namespace='##other' minOccurs='0' maxOccurs='unbounded'/> |
| // </sequence> |
| // <attribute name='Algorithm' type='anyURI' use='required'/> |
| // </complexType> |
| private class EncryptionMethodImpl implements EncryptionMethod { |
| private String algorithm = null; |
| private int keySize = Integer.MIN_VALUE; |
| private byte[] oaepParams = null; |
| private List encryptionMethodInformation = null; |
| /** |
| * |
| * @param algorithm |
| */ |
| public EncryptionMethodImpl(String algorithm) { |
| URI tmpAlgorithm = null; |
| try { |
| tmpAlgorithm = new URI(algorithm); |
| } catch (URI.MalformedURIException mfue) { |
| // complain |
| } |
| this.algorithm = tmpAlgorithm.toString(); |
| encryptionMethodInformation = new LinkedList(); |
| } |
| /** @inheritDoc */ |
| public String getAlgorithm() { |
| return (algorithm); |
| } |
| /** @inheritDoc */ |
| public int getKeySize() { |
| return (keySize); |
| } |
| /** @inheritDoc */ |
| public void setKeySize(int size) { |
| keySize = size; |
| } |
| /** @inheritDoc */ |
| public byte[] getOAEPparams() { |
| return (oaepParams); |
| } |
| /** @inheritDoc */ |
| public void setOAEPparams(byte[] params) { |
| oaepParams = params; |
| } |
| /** @inheritDoc */ |
| public Iterator getEncryptionMethodInformation() { |
| return (encryptionMethodInformation.iterator()); |
| } |
| /** @inheritDoc */ |
| public void addEncryptionMethodInformation(Element info) { |
| encryptionMethodInformation.add(info); |
| } |
| /** @inheritDoc */ |
| public void removeEncryptionMethodInformation(Element info) { |
| encryptionMethodInformation.remove(info); |
| } |
| |
| // <complexType name='EncryptionMethodType' mixed='true'> |
| // <sequence> |
| // <element name='KeySize' minOccurs='0' type='xenc:KeySizeType'/> |
| // <element name='OAEPparams' minOccurs='0' type='base64Binary'/> |
| // <any namespace='##other' minOccurs='0' maxOccurs='unbounded'/> |
| // </sequence> |
| // <attribute name='Algorithm' type='anyURI' use='required'/> |
| // </complexType> |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTIONMETHOD); |
| result.setAttributeNS(null, EncryptionConstants._ATT_ALGORITHM, |
| algorithm.toString()); |
| if (keySize > 0) { |
| result.appendChild( |
| ElementProxy.createElementForFamily(_contextDocument, |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_KEYSIZE).appendChild( |
| _contextDocument.createTextNode( |
| String.valueOf(keySize)))); |
| } |
| if (null != oaepParams) { |
| result.appendChild( |
| ElementProxy.createElementForFamily(_contextDocument, |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_OAEPPARAMS).appendChild( |
| _contextDocument.createTextNode( |
| new String(oaepParams)))); |
| } |
| if (!encryptionMethodInformation.isEmpty()) { |
| Iterator itr = encryptionMethodInformation.iterator(); |
| result.appendChild((Element) itr.next()); |
| } |
| |
| return (result); |
| } |
| } |
| |
| // <element name='EncryptionProperties' type='xenc:EncryptionPropertiesType'/> |
| // <complexType name='EncryptionPropertiesType'> |
| // <sequence> |
| // <element ref='xenc:EncryptionProperty' maxOccurs='unbounded'/> |
| // </sequence> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // </complexType> |
| private class EncryptionPropertiesImpl implements EncryptionProperties { |
| private String id = null; |
| private List encryptionProperties = null; |
| /** |
| * |
| * |
| */ |
| public EncryptionPropertiesImpl() { |
| encryptionProperties = new LinkedList(); |
| } |
| /** @inheritDoc */ |
| public String getId() { |
| return (id); |
| } |
| /** @inheritDoc */ |
| public void setId(String id) { |
| this.id = id; |
| } |
| /** @inheritDoc */ |
| public Iterator getEncryptionProperties() { |
| return (encryptionProperties.iterator()); |
| } |
| /** @inheritDoc */ |
| public void addEncryptionProperty(EncryptionProperty property) { |
| encryptionProperties.add(property); |
| } |
| /** @inheritDoc */ |
| public void removeEncryptionProperty(EncryptionProperty property) { |
| encryptionProperties.remove(property); |
| } |
| |
| // <element name='EncryptionProperties' type='xenc:EncryptionPropertiesType'/> |
| // <complexType name='EncryptionPropertiesType'> |
| // <sequence> |
| // <element ref='xenc:EncryptionProperty' maxOccurs='unbounded'/> |
| // </sequence> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // </complexType> |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTIONPROPERTIES); |
| if (null != id) { |
| result.setAttributeNS(null, EncryptionConstants._ATT_ID, id); |
| } |
| Iterator itr = getEncryptionProperties(); |
| while (itr.hasNext()) { |
| result.appendChild(((EncryptionPropertyImpl) |
| itr.next()).toElement()); |
| } |
| |
| return (result); |
| } |
| } |
| |
| // <element name='EncryptionProperty' type='xenc:EncryptionPropertyType'/> |
| // <complexType name='EncryptionPropertyType' mixed='true'> |
| // <choice maxOccurs='unbounded'> |
| // <any namespace='##other' processContents='lax'/> |
| // </choice> |
| // <attribute name='Target' type='anyURI' use='optional'/> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // <anyAttribute namespace="http://www.w3.org/XML/1998/namespace"/> |
| // </complexType> |
| private class EncryptionPropertyImpl implements EncryptionProperty { |
| private String target = null; |
| private String id = null; |
| private String attributeName = null; |
| private String attributeValue = null; |
| private List encryptionInformation = null; |
| |
| /** |
| * |
| * |
| */ |
| public EncryptionPropertyImpl() { |
| encryptionInformation = new LinkedList(); |
| } |
| /** @inheritDoc */ |
| public String getTarget() { |
| return (target); |
| } |
| /** @inheritDoc */ |
| public void setTarget(String target) { |
| URI tmpTarget = null; |
| try { |
| tmpTarget = new URI(target); |
| } catch (URI.MalformedURIException mfue) { |
| // complain |
| } |
| this.target = tmpTarget.toString(); |
| } |
| /** @inheritDoc */ |
| public String getId() { |
| return (id); |
| } |
| /** @inheritDoc */ |
| public void setId(String id) { |
| this.id = id; |
| } |
| /** @inheritDoc */ |
| public String getAttribute(String attribute) { |
| return (attributeValue); |
| } |
| /** @inheritDoc */ |
| public void setAttribute(String attribute, String value) { |
| attributeName = attribute; |
| attributeValue = value; |
| } |
| /** @inheritDoc */ |
| public Iterator getEncryptionInformation() { |
| return (encryptionInformation.iterator()); |
| } |
| /** @inheritDoc */ |
| public void addEncryptionInformation(Element info) { |
| encryptionInformation.add(info); |
| } |
| /** @inheritDoc */ |
| public void removeEncryptionInformation(Element info) { |
| encryptionInformation.remove(info); |
| } |
| |
| // <element name='EncryptionProperty' type='xenc:EncryptionPropertyType'/> |
| // <complexType name='EncryptionPropertyType' mixed='true'> |
| // <choice maxOccurs='unbounded'> |
| // <any namespace='##other' processContents='lax'/> |
| // </choice> |
| // <attribute name='Target' type='anyURI' use='optional'/> |
| // <attribute name='Id' type='ID' use='optional'/> |
| // <anyAttribute namespace="http://www.w3.org/XML/1998/namespace"/> |
| // </complexType> |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_ENCRYPTIONPROPERTY); |
| if (null != target) { |
| result.setAttributeNS(null, EncryptionConstants._ATT_TARGET, |
| target.toString()); |
| } |
| if (null != id) { |
| result.setAttributeNS(null, EncryptionConstants._ATT_ID, |
| id); |
| } |
| // TODO: figure out the anyAttribyte stuff... |
| // TODO: figure out the any stuff... |
| |
| return (result); |
| } |
| } |
| |
| // <complexType name='TransformsType'> |
| // <sequence> |
| // <element ref='ds:Transform' maxOccurs='unbounded'/> |
| // </sequence> |
| // </complexType> |
| private class TransformsImpl extends |
| com.sun.org.apache.xml.internal.security.transforms.Transforms |
| implements Transforms { |
| |
| /** |
| * Construct Transforms |
| */ |
| |
| public TransformsImpl() { |
| super(_contextDocument); |
| } |
| /** |
| * |
| * @param doc |
| */ |
| public TransformsImpl(Document doc) { |
| super(doc); |
| } |
| /** |
| * |
| * @param element |
| * @throws XMLSignatureException |
| * @throws InvalidTransformException |
| * @throws XMLSecurityException |
| * @throws TransformationException |
| */ |
| public TransformsImpl(Element element) |
| throws XMLSignatureException, |
| InvalidTransformException, |
| XMLSecurityException, |
| TransformationException { |
| |
| super(element, ""); |
| |
| } |
| |
| /** |
| * |
| * @return |
| */ |
| public Element toElement() { |
| |
| if (_doc == null) |
| _doc = _contextDocument; |
| |
| return getElement(); |
| } |
| |
| /** @inheritDoc */ |
| public com.sun.org.apache.xml.internal.security.transforms.Transforms getDSTransforms() { |
| return (this); |
| } |
| |
| |
| // Over-ride the namespace |
| /** @inheritDoc */ |
| public String getBaseNamespace() { |
| return EncryptionConstants.EncryptionSpecNS; |
| } |
| |
| } |
| |
| //<element name='ReferenceList'> |
| // <complexType> |
| // <choice minOccurs='1' maxOccurs='unbounded'> |
| // <element name='DataReference' type='xenc:ReferenceType'/> |
| // <element name='KeyReference' type='xenc:ReferenceType'/> |
| // </choice> |
| // </complexType> |
| //</element> |
| private class ReferenceListImpl implements ReferenceList { |
| private Class sentry; |
| private List references; |
| /** |
| * |
| * @param type |
| */ |
| public ReferenceListImpl(int type) { |
| if (type == ReferenceList.DATA_REFERENCE) { |
| sentry = DataReference.class; |
| } else if (type == ReferenceList.KEY_REFERENCE) { |
| sentry = KeyReference.class; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| references = new LinkedList(); |
| } |
| /** @inheritDoc */ |
| public void add(Reference reference) { |
| if (!reference.getClass().equals(sentry)) { |
| throw new IllegalArgumentException(); |
| } |
| references.add(reference); |
| } |
| /** @inheritDoc */ |
| public void remove(Reference reference) { |
| if (!reference.getClass().equals(sentry)) { |
| throw new IllegalArgumentException(); |
| } |
| references.remove(reference); |
| } |
| /** @inheritDoc */ |
| public int size() { |
| return (references.size()); |
| } |
| /** @inheritDoc */ |
| public boolean isEmpty() { |
| return (references.isEmpty()); |
| } |
| /** @inheritDoc */ |
| public Iterator getReferences() { |
| return (references.iterator()); |
| } |
| |
| Element toElement() { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, |
| EncryptionConstants.EncryptionSpecNS, |
| EncryptionConstants._TAG_REFERENCELIST); |
| Iterator eachReference = references.iterator(); |
| while (eachReference.hasNext()) { |
| Reference reference = (Reference) eachReference.next(); |
| result.appendChild( |
| ((ReferenceImpl) reference).toElement()); |
| } |
| return (result); |
| } |
| /** @inheritDoc */ |
| public Reference newDataReference(String uri) { |
| return (new DataReference(uri)); |
| } |
| /** @inheritDoc */ |
| public Reference newKeyReference(String uri) { |
| return (new KeyReference(uri)); |
| } |
| |
| /** |
| * <code>ReferenceImpl</code> is an implementation of |
| * <code>Reference</code>. |
| * |
| * @see Reference |
| */ |
| private abstract class ReferenceImpl implements Reference { |
| private String uri; |
| private List referenceInformation; |
| |
| ReferenceImpl(String _uri) { |
| this.uri = _uri; |
| referenceInformation = new LinkedList(); |
| } |
| /** @inheritDoc */ |
| public String getURI() { |
| return (uri); |
| } |
| /** @inheritDoc */ |
| public Iterator getElementRetrievalInformation() { |
| return (referenceInformation.iterator()); |
| } |
| /** @inheritDoc */ |
| public void setURI(String _uri) { |
| this.uri = _uri; |
| } |
| /** @inheritDoc */ |
| public void removeElementRetrievalInformation(Element node) { |
| referenceInformation.remove(node); |
| } |
| /** @inheritDoc */ |
| public void addElementRetrievalInformation(Element node) { |
| referenceInformation.add(node); |
| } |
| /** |
| * |
| * @return |
| */ |
| public abstract Element toElement(); |
| |
| Element toElement(String tagName) { |
| Element result = ElementProxy.createElementForFamily( |
| _contextDocument, |
| EncryptionConstants.EncryptionSpecNS, |
| tagName); |
| result.setAttribute(EncryptionConstants._ATT_URI, uri); |
| |
| // TODO: Need to martial referenceInformation |
| // Figure out how to make this work.. |
| // <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> |
| |
| return (result); |
| } |
| } |
| |
| private class DataReference extends ReferenceImpl { |
| DataReference(String uri) { |
| super(uri); |
| } |
| /** @inheritDoc */ |
| public Element toElement() { |
| return super.toElement(EncryptionConstants._TAG_DATAREFERENCE); |
| } |
| } |
| |
| private class KeyReference extends ReferenceImpl { |
| KeyReference(String uri) { |
| super (uri); |
| } |
| /** @inheritDoc */ |
| public Element toElement() { |
| return super.toElement(EncryptionConstants._TAG_KEYREFERENCE); |
| } |
| } |
| } |
| } |
| } |