You are viewing a plain text version of this content. The canonical link for it is here.
Posted to wss4j-dev@ws.apache.org by fa...@apache.org on 2008/04/11 19:28:46 UTC

svn commit: r647232 [1/4] - in /webservices/wss4j/trunk: src/org/apache/ws/security/ src/org/apache/ws/security/message/ src/org/apache/ws/security/processor/ test/wssec/

Author: fadushin
Date: Fri Apr 11 10:28:39 2008
New Revision: 647232

URL: http://svn.apache.org/viewvc?rev=647232&view=rev
Log:
WSS-109 Error Handling improvements

 * Applied Colm's error handling fixes

Note: In order to get this patch to work, I had to change a lot
of the files that were affected to use UNIX line ending conventions
(I am developing on a UNIX machine).  Many files seem to have been
committed with Windows (CRLF) line endings, perhaps using a UNIX
subversion client.  


Added:
    webservices/wss4j/trunk/test/wssec/TestWSSecurityFaultCodes.java   (with props)
Modified:
    webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java
    webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java
    webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties
    webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
    webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java
    webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java
    webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncryptedKey.java
    webservices/wss4j/trunk/src/org/apache/ws/security/processor/DerivedKeyTokenProcessor.java
    webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedDataProcessor.java
    webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java
    webservices/wss4j/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java
    webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
    webservices/wss4j/trunk/src/org/apache/ws/security/processor/TimestampProcessor.java
    webservices/wss4j/trunk/test/wssec/PackageTests.java
    webservices/wss4j/trunk/test/wssec/TestWSSecurityNew14.java

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java Fri Apr 11 10:28:39 2008
@@ -428,7 +428,9 @@
     
     public final static String WSC_SCT = "http://schemas.xmlsoap.org/ws/2005/02/sc/sct";
     
-    // Fault codes defined in the WSS 1.0 spec under section 6, Error handling
+    //
+    // Fault codes defined in the WSS 1.1 spec under section 12, Error handling
+    //
     
     /**
      * An unsupported token was provided
@@ -464,6 +466,11 @@
      * Referenced security token could not be retrieved
      */
     public static final QName SECURITY_TOKEN_UNAVAILABLE = new QName (WSSE_NS, "SecurityTokenUnavailable");
+    
+    /** 
+     * The message has expired
+     */
+    public static final QName MESSAGE_EXPIRED = new QName (WSSE_NS, "MessageExpired");
     
     /**
      * Header type in <code>org.apache.ws.security.WSEncryptionPart</code>

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java Fri Apr 11 10:28:39 2008
@@ -37,9 +37,18 @@
     public static final int FAILED_AUTHENTICATION = 5;
     public static final int FAILED_CHECK = 6;
     public static final int SECURITY_TOKEN_UNAVAILABLE = 7;
-    public static final int FAILED_ENC_DEC = 8;
-    public static final int FAILED_SIGNATURE = 9;
+    public static final int MESSAGE_EXPIRED = 8;
+    public static final int FAILED_ENCRYPTION = 9;
+    public static final int FAILED_SIGNATURE = 10;
     private static ResourceBundle resources;
+    /*
+     * This is an Integer -> QName map. Its function is to map the integer error codes
+     * given above to the QName fault codes as defined in the SOAP Message Security 1.1
+     * specification. A client application can simply call getFaultCode rather than do
+     * any parsing of the error code. Note that there are no mappings for "FAILURE", 
+     * "FAILED_ENCRYPTION" and "FAILED_SIGNATURE" as these are not standard error messages.
+     */
+    private static final java.util.Map FAULT_CODE_MAP = new java.util.HashMap();
 
     static {
         try {
@@ -47,6 +56,39 @@
         } catch (MissingResourceException e) {
             throw new RuntimeException(e.getMessage());
         }
+        
+        FAULT_CODE_MAP.put(
+            new Integer(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN), 
+            WSConstants.UNSUPPORTED_SECURITY_TOKEN
+        );
+        FAULT_CODE_MAP.put(
+            new Integer(UNSUPPORTED_ALGORITHM), 
+            WSConstants.UNSUPPORTED_ALGORITHM
+        );
+        FAULT_CODE_MAP.put(
+            new Integer(INVALID_SECURITY), 
+            WSConstants.INVALID_SECURITY
+        );
+        FAULT_CODE_MAP.put(
+            new Integer(INVALID_SECURITY_TOKEN), 
+            WSConstants.INVALID_SECURITY_TOKEN
+        );
+        FAULT_CODE_MAP.put(
+            new Integer(FAILED_AUTHENTICATION), 
+            WSConstants.FAILED_AUTHENTICATION
+         );
+        FAULT_CODE_MAP.put(
+            new Integer(FAILED_CHECK), 
+            WSConstants.FAILED_CHECK
+         );
+        FAULT_CODE_MAP.put(
+            new Integer(SECURITY_TOKEN_UNAVAILABLE),
+            WSConstants.SECURITY_TOKEN_UNAVAILABLE
+         );
+        FAULT_CODE_MAP.put(
+            new Integer(MESSAGE_EXPIRED), 
+            WSConstants.MESSAGE_EXPIRED
+        );
     }
 
     private int errorCode;
@@ -127,6 +169,20 @@
      */
     public int getErrorCode() {
         return this.errorCode;
+    }
+    
+    /**
+     * Get the fault code QName for this associated error code.
+     * <p/>
+     * 
+     * @return the fault code QName of this exception
+     */
+    public javax.xml.namespace.QName getFaultCode() {
+        Object ret = FAULT_CODE_MAP.get(new Integer(this.errorCode));
+        if (ret != null) {
+            return (javax.xml.namespace.QName)ret;
+        }
+        return null;
     }
 
     /**

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties Fri Apr 11 10:28:39 2008
@@ -2,13 +2,14 @@
 0 = General security error
 1 = An unsupported token was provided
 2 = An unsupported signature or encryption algorithm was used
-3 = An error was discovered processing the <wsse:Security> header.
+3 = An error was discovered processing the <wsse:Security> header
 4 = An invalid security token was provided
 5 = The security token could not be authenticated or authorized
-6 = The signature verification failed
-7 = Referenced security token could not be retrieved.
-8 = Cannot encrypt/decrypt data
-9 = Signature creation failed
+6 = The signature or decryption was invalid
+7 = Referenced security token could not be retrieved
+8 = The message has expired
+9 = Cannot encrypt data
+10 = Signature creation failed
 
 ## detailed error msgs
 noToken = Reference \"{0}\"

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java Fri Apr 11 10:28:39 2008
@@ -353,7 +353,7 @@
         try {
             cipher.init(Cipher.ENCRYPT_MODE, remoteCert);
         } catch (InvalidKeyException e) {
-            throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e);
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e);
         }
         byte[] encKey = this.encryptionKey.getEncoded();
         if (doDebug) {
@@ -371,11 +371,11 @@
         try {
             encryptedKey = cipher.doFinal(encKey);
         } catch (IllegalStateException e1) {
-            throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e1);
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e1);
         } catch (IllegalBlockSizeException e1) {
-            throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e1);
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e1);
         } catch (BadPaddingException e1) {
-            throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e1);
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e1);
         }
         Text keyText =
                 WSSecurityUtil.createBase64EncodedTextNode(doc, encryptedKey);
@@ -542,7 +542,7 @@
                 encData.setKeyInfo(keyInfo);
                 xmlCipher.doFinal(doc, body, content);
             } catch (Exception e2) {
-                throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e2);
+                throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e2);
             }
             encDataRefs.add(new String("#" + xencEncryptedDataId));
         }

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java Fri Apr 11 10:28:39 2008
@@ -1,248 +1,248 @@
-/*
- * 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 org.apache.ws.security.message;
-
-import org.apache.ws.security.SOAPConstants;
-import org.apache.ws.security.WSConstants;
-import org.apache.ws.security.WSEncryptionPart;
-import org.apache.ws.security.WSSecurityException;
-import org.apache.ws.security.conversation.ConversationException;
-import org.apache.ws.security.message.token.Reference;
-import org.apache.ws.security.message.token.SecurityTokenReference;
-import org.apache.ws.security.util.WSSecurityUtil;
-import org.apache.xml.security.encryption.EncryptedData;
-import org.apache.xml.security.encryption.XMLCipher;
-import org.apache.xml.security.encryption.XMLEncryptionException;
-import org.apache.xml.security.keys.KeyInfo;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import javax.crypto.SecretKey;
-
-import java.util.Vector;
-
-/**
- * Encrypts and signs parts of a message with derived keys derived from a
- * symmetric key. This symmetric key will be included as an EncryptedKey
- * 
- * @author Ruchith Fernando (ruchith.fernando@gmail.com)
- */
-public class WSSecDKEncrypt extends WSSecDerivedKeyBase {
-
-    protected String symEncAlgo = WSConstants.AES_128;
-    
-    public Document build(Document doc, WSSecHeader secHeader)
-            throws WSSecurityException, ConversationException {
-        
-        /*
-         * Setup the encrypted key
-         */
-        prepare(doc);
-        
-        this.envelope =  doc.getDocumentElement();
-        /*
-         * prepend elements in the right order to the security header
-         */
-        prependDKElementToHeader(secHeader);
-                
-        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
-        if (parts == null) {
-            parts = new Vector();
-            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
-                    .getBodyQName().getLocalPart(), soapConstants
-                    .getEnvelopeURI(), "Content");
-            parts.add(encP);
-        }
-        Element externRefList = encryptForExternalRef(null, parts);
-        addExternalRefElement(externRefList, secHeader);
-
-        return doc;
-    }
-
-    private Vector doEncryption(Document doc, byte[] secretKey, Vector references) throws WSSecurityException {
-
-        SecretKey key = WSSecurityUtil.prepareSecretKey(this.symEncAlgo, secretKey);
-        
-        
-        XMLCipher xmlCipher = null;
-        try {
-            xmlCipher = XMLCipher.getInstance(symEncAlgo);
-        } catch (XMLEncryptionException e3) {
-            throw new WSSecurityException(
-                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
-        }
-
-        Vector encDataRefs = new Vector();
-        
-        if(envelope == null) {
-            envelope = doc.getDocumentElement();
-        }
-        
-        for (int part = 0; part < references.size(); part++) {
-            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
-
-            String idToEnc = encPart.getId();
-            
-            String elemName = encPart.getName();
-            String nmSpace = encPart.getNamespace();
-            String modifier = encPart.getEncModifier();
-            /*
-             * Third step: get the data to encrypt.
-             */
-            Element body = null;
-            if (idToEnc != null) {
-                body = WSSecurityUtil.findElementById(document
-                        .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
-                if (body == null) {
-                    body = WSSecurityUtil.findElementById(document
-                            .getDocumentElement(), idToEnc, null);
-                }
-            } else {
-                body = (Element) WSSecurityUtil.findElement(envelope, elemName,
-                        nmSpace);
-            }
-            if (body == null) {
-                throw new WSSecurityException(WSSecurityException.FAILURE,
-                        "noEncElement", new Object[] { "{" + nmSpace + "}"
-                                + elemName });
-            }
-
-            boolean content = modifier.equals("Content") ? true : false;
-            String xencEncryptedDataId = "EncDataId-" + body.hashCode();
-
-            /*
-             * Forth step: encrypt data, and set necessary attributes in
-             * xenc:EncryptedData
-             */
-            try {
-                //Create the SecurityTokenRef to the DKT
-                KeyInfo keyInfo = new KeyInfo(document);
-                SecurityTokenReference secToken = new SecurityTokenReference(document);
-                Reference ref = new Reference(document);
-                ref.setURI("#" + dktId);
-                secToken.setReference(ref);
-
-                keyInfo.addUnknownElement(secToken.getElement());
-
-                xmlCipher.init(XMLCipher.ENCRYPT_MODE, key);
-                EncryptedData encData = xmlCipher.getEncryptedData();
-                encData.setId(xencEncryptedDataId);
-                encData.setKeyInfo(keyInfo);
-                xmlCipher.doFinal(doc, body, content);
-            } catch (Exception e2) {
-                throw new WSSecurityException(
-                        WSSecurityException.FAILED_ENC_DEC, null, null, e2);
-            }
-            encDataRefs.add(new String("#" + xencEncryptedDataId));
-        }
-        return encDataRefs;
-    }
-    
-    /**
-     * Encrypt one or more parts or elements of the message (external).
-     * 
-     * This method takes a vector of <code>WSEncryptionPart</code> object that
-     * contain information about the elements to encrypt. The method call the
-     * encryption method, takes the reference information generated during
-     * encryption and add this to the <code>xenc:Reference</code> element.
-     * This method can be called after <code>prepare()</code> and can be
-     * called multiple times to encrypt a number of parts or elements.
-     * 
-     * </p>
-     * 
-     * The method generates a <code>xenc:Reference</code> element that <i>must</i>
-     * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
-     * 
-     * </p>
-     * 
-     * If the <code>dataRef</code> parameter is <code>null</code> the method
-     * creates and initializes a new Reference element.
-     * 
-     * @param dataRef
-     *            A <code>xenc:Reference</code> element or <code>null</code>
-     * @param references
-     *            A vector containing WSEncryptionPart objects
-     * @return Returns the updated <code>xenc:Reference</code> element
-     * @throws WSSecurityException
-     */
-    public Element encryptForExternalRef(Element dataRef, Vector references)
-            throws WSSecurityException {
-
-
-        Vector encDataRefs = doEncryption(document, derivedKeyBytes,
-                references);
-        Element referenceList = dataRef;
-        if (referenceList == null) {
-            referenceList = document.createElementNS(WSConstants.ENC_NS,
-                    WSConstants.ENC_PREFIX + ":ReferenceList");
-        }
-        createDataRefList(document, referenceList, encDataRefs);
-        return referenceList;
-    }
-    
-    /**
-     * Adds (prepends) the external Reference element to the Security header.
-     * 
-     * The reference element <i>must</i> be created by the
-     * <code>encryptForExternalRef() </code> method. The method adds the
-     * reference element in the SecurityHeader.
-     * 
-     * @param dataRef
-     *            The external <code>enc:Reference</code> element
-     * @param secHeader
-     *            The security header.
-     */
-    public void addExternalRefElement(Element referenceList, WSSecHeader secHeader) {
-        Node node = dkt.getElement().getNextSibling();
-        if(node == null || (node != null && !(node instanceof Element))) {
-            //If (at this moment) DerivedKeyToken is the LAST element of 
-            //the security header 
-            secHeader.getSecurityHeader().appendChild(referenceList);
-        } else {
-            secHeader.getSecurityHeader().insertBefore(referenceList, node);
-        }
-        
-    }
-
-    public static Element createDataRefList(Document doc,
-            Element referenceList, Vector encDataRefs) {
-        for (int i = 0; i < encDataRefs.size(); i++) {
-            String dataReferenceUri = (String) encDataRefs.get(i);
-            Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
-                    WSConstants.ENC_PREFIX + ":DataReference");
-            dataReference.setAttributeNS(null, "URI", dataReferenceUri);
-            referenceList.appendChild(dataReference);
-        }
-        return referenceList;
-    }
-
-    
-    public void setSymmetricEncAlgorithm(String algo) {
-        symEncAlgo = algo;
-    }
-
-    /**
-     * @see org.apache.ws.security.message.WSSecDerivedKeyBase#getDerivedKeyLength()
-     */
-    protected int getDerivedKeyLength() throws WSSecurityException{
-        return (this.derivedKeyLength > 0) ? this.derivedKeyLength : 
-            WSSecurityUtil.getKeyLength(this.symEncAlgo);
-    }
-    
-}
+/*
+ * 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 org.apache.ws.security.message;
+
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.conversation.ConversationException;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.EncryptedData;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.crypto.SecretKey;
+
+import java.util.Vector;
+
+/**
+ * Encrypts and signs parts of a message with derived keys derived from a
+ * symmetric key. This symmetric key will be included as an EncryptedKey
+ * 
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public class WSSecDKEncrypt extends WSSecDerivedKeyBase {
+
+    protected String symEncAlgo = WSConstants.AES_128;
+    
+    public Document build(Document doc, WSSecHeader secHeader)
+            throws WSSecurityException, ConversationException {
+        
+        /*
+         * Setup the encrypted key
+         */
+        prepare(doc);
+        
+        this.envelope =  doc.getDocumentElement();
+        /*
+         * prepend elements in the right order to the security header
+         */
+        prependDKElementToHeader(secHeader);
+                
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+        Element externRefList = encryptForExternalRef(null, parts);
+        addExternalRefElement(externRefList, secHeader);
+
+        return doc;
+    }
+
+    private Vector doEncryption(Document doc, byte[] secretKey, Vector references) throws WSSecurityException {
+
+        SecretKey key = WSSecurityUtil.prepareSecretKey(this.symEncAlgo, secretKey);
+        
+        
+        XMLCipher xmlCipher = null;
+        try {
+            xmlCipher = XMLCipher.getInstance(symEncAlgo);
+        } catch (XMLEncryptionException e3) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
+        }
+
+        Vector encDataRefs = new Vector();
+        
+        if(envelope == null) {
+            envelope = doc.getDocumentElement();
+        }
+        
+        for (int part = 0; part < references.size(); part++) {
+            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
+
+            String idToEnc = encPart.getId();
+            
+            String elemName = encPart.getName();
+            String nmSpace = encPart.getNamespace();
+            String modifier = encPart.getEncModifier();
+            /*
+             * Third step: get the data to encrypt.
+             */
+            Element body = null;
+            if (idToEnc != null) {
+                body = WSSecurityUtil.findElementById(document
+                        .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
+                if (body == null) {
+                    body = WSSecurityUtil.findElementById(document
+                            .getDocumentElement(), idToEnc, null);
+                }
+            } else {
+                body = (Element) WSSecurityUtil.findElement(envelope, elemName,
+                        nmSpace);
+            }
+            if (body == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noEncElement", new Object[] { "{" + nmSpace + "}"
+                                + elemName });
+            }
+
+            boolean content = modifier.equals("Content") ? true : false;
+            String xencEncryptedDataId = "EncDataId-" + body.hashCode();
+
+            /*
+             * Forth step: encrypt data, and set necessary attributes in
+             * xenc:EncryptedData
+             */
+            try {
+                //Create the SecurityTokenRef to the DKT
+                KeyInfo keyInfo = new KeyInfo(document);
+                SecurityTokenReference secToken = new SecurityTokenReference(document);
+                Reference ref = new Reference(document);
+                ref.setURI("#" + dktId);
+                secToken.setReference(ref);
+
+                keyInfo.addUnknownElement(secToken.getElement());
+
+                xmlCipher.init(XMLCipher.ENCRYPT_MODE, key);
+                EncryptedData encData = xmlCipher.getEncryptedData();
+                encData.setId(xencEncryptedDataId);
+                encData.setKeyInfo(keyInfo);
+                xmlCipher.doFinal(doc, body, content);
+            } catch (Exception e2) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_ENCRYPTION, null, null, e2);
+            }
+            encDataRefs.add(new String("#" + xencEncryptedDataId));
+        }
+        return encDataRefs;
+    }
+    
+    /**
+     * Encrypt one or more parts or elements of the message (external).
+     * 
+     * This method takes a vector of <code>WSEncryptionPart</code> object that
+     * contain information about the elements to encrypt. The method call the
+     * encryption method, takes the reference information generated during
+     * encryption and add this to the <code>xenc:Reference</code> element.
+     * This method can be called after <code>prepare()</code> and can be
+     * called multiple times to encrypt a number of parts or elements.
+     * 
+     * </p>
+     * 
+     * The method generates a <code>xenc:Reference</code> element that <i>must</i>
+     * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
+     * 
+     * </p>
+     * 
+     * If the <code>dataRef</code> parameter is <code>null</code> the method
+     * creates and initializes a new Reference element.
+     * 
+     * @param dataRef
+     *            A <code>xenc:Reference</code> element or <code>null</code>
+     * @param references
+     *            A vector containing WSEncryptionPart objects
+     * @return Returns the updated <code>xenc:Reference</code> element
+     * @throws WSSecurityException
+     */
+    public Element encryptForExternalRef(Element dataRef, Vector references)
+            throws WSSecurityException {
+
+
+        Vector encDataRefs = doEncryption(document, derivedKeyBytes,
+                references);
+        Element referenceList = dataRef;
+        if (referenceList == null) {
+            referenceList = document.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":ReferenceList");
+        }
+        createDataRefList(document, referenceList, encDataRefs);
+        return referenceList;
+    }
+    
+    /**
+     * Adds (prepends) the external Reference element to the Security header.
+     * 
+     * The reference element <i>must</i> be created by the
+     * <code>encryptForExternalRef() </code> method. The method adds the
+     * reference element in the SecurityHeader.
+     * 
+     * @param dataRef
+     *            The external <code>enc:Reference</code> element
+     * @param secHeader
+     *            The security header.
+     */
+    public void addExternalRefElement(Element referenceList, WSSecHeader secHeader) {
+        Node node = dkt.getElement().getNextSibling();
+        if(node == null || (node != null && !(node instanceof Element))) {
+            //If (at this moment) DerivedKeyToken is the LAST element of 
+            //the security header 
+            secHeader.getSecurityHeader().appendChild(referenceList);
+        } else {
+            secHeader.getSecurityHeader().insertBefore(referenceList, node);
+        }
+        
+    }
+
+    public static Element createDataRefList(Document doc,
+            Element referenceList, Vector encDataRefs) {
+        for (int i = 0; i < encDataRefs.size(); i++) {
+            String dataReferenceUri = (String) encDataRefs.get(i);
+            Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":DataReference");
+            dataReference.setAttributeNS(null, "URI", dataReferenceUri);
+            referenceList.appendChild(dataReference);
+        }
+        return referenceList;
+    }
+
+    
+    public void setSymmetricEncAlgorithm(String algo) {
+        symEncAlgo = algo;
+    }
+
+    /**
+     * @see org.apache.ws.security.message.WSSecDerivedKeyBase#getDerivedKeyLength()
+     */
+    protected int getDerivedKeyLength() throws WSSecurityException{
+        return (this.derivedKeyLength > 0) ? this.derivedKeyLength : 
+            WSSecurityUtil.getKeyLength(this.symEncAlgo);
+    }
+    
+}

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java Fri Apr 11 10:28:39 2008
@@ -1,743 +1,743 @@
-/*
- * 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 org.apache.ws.security.message;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.ws.security.SOAPConstants;
-import org.apache.ws.security.WSConstants;
-import org.apache.ws.security.WSEncryptionPart;
-import org.apache.ws.security.WSSecurityException;
-import org.apache.ws.security.components.crypto.Crypto;
-import org.apache.ws.security.message.token.Reference;
-import org.apache.ws.security.message.token.SecurityTokenReference;
-import org.apache.ws.security.util.Base64;
-import org.apache.ws.security.util.WSSecurityUtil;
-import org.apache.xml.security.encryption.EncryptedData;
-import org.apache.xml.security.encryption.XMLCipher;
-import org.apache.xml.security.encryption.XMLEncryptionException;
-import org.apache.xml.security.keys.KeyInfo;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.X509Certificate;
-import java.util.Vector;
-
-/**
- * Encrypts a parts of a message according to WS Specification, X509 profile,
- * and adds the encryption data.
- * 
- * @author Davanum Srinivas (dims@yahoo.com).
- * @author Werner Dittmann (Werner.Dittmann@apache.org).
- */
-public class WSSecEncrypt extends WSSecEncryptedKey {
-    private static Log log = LogFactory.getLog(WSSecEncrypt.class.getName());
-
-    private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
-
-    protected String symEncAlgo = WSConstants.AES_128;
-
-    protected String encCanonAlgo = null;
-
-    protected byte[] embeddedKey = null;
-
-    protected String embeddedKeyName = null;
-
-    /**
-     * Symmetric key used in the EncrytpedKey.
-     */
-    protected SecretKey symmetricKey = null;
-
-    /**
-     * SecurityTokenReference to be inserted into EncryptedData/keyInfo element.
-     */
-    protected SecurityTokenReference securityTokenReference = null;
-
-    /**
-     * Indicates whether to encrypt the symmetric key into an EncryptedKey 
-     * or not.
-     */
-    private boolean encryptSymmKey = true;
-    
-    /**
-     * Custom reference value
-     */
-    private String customReferenceValue;
-
-    /**
-     * Constructor.
-     */
-    public WSSecEncrypt() {
-    }
-
-    /**
-     * Sets the key to use during embedded encryption.
-     * 
-     * <p/>
-     * 
-     * @param key
-     *            to use during encryption. The key must fit the selected
-     *            symmetrical encryption algorithm
-     */
-    public void setKey(byte[] key) {
-        this.embeddedKey = key;
-    }
-
-    /**
-     * Sets the algorithm to encode the symmetric key.
-     * 
-     * Default is the <code>WSConstants.KEYTRANSPORT_RSA15</code> algorithm.
-     * 
-     * @param keyEnc
-     *            specifies the key encoding algorithm.
-     * @see WSConstants#KEYTRANSPORT_RSA15
-     * @see WSConstants#KEYTRANSPORT_RSAOEP
-     */
-    public void setKeyEnc(String keyEnc) {
-        keyEncAlgo = keyEnc;
-    }
-
-    /**
-     * Set the key name for EMBEDDED_KEYNAME
-     * 
-     * @param embeddedKeyName
-     */
-    public void setEmbeddedKeyName(String embeddedKeyName) {
-        this.embeddedKeyName = embeddedKeyName;
-    }
-    
-    /**
-     * Set the name of the symmetric encryption algorithm to use.
-     * 
-     * This encryption algorithm is used to encrypt the data. If the algorithm
-     * is not set then AES128 is used. Refer to WSConstants which algorithms are
-     * supported.
-     * 
-     * @param algo
-     *            Is the name of the encryption algorithm
-     * @see WSConstants#TRIPLE_DES
-     * @see WSConstants#AES_128
-     * @see WSConstants#AES_192
-     * @see WSConstants#AES_256
-     */
-    public void setSymmetricEncAlgorithm(String algo) {
-        symEncAlgo = algo;
-    }
-
-    /**
-     * Set the name of an optional canonicalization algorithm to use before
-     * encryption.
-     * 
-     * This c14n algorithm is used to serialize the data before encryption. If
-     * the algorithm is not set then a standard serialization is used (provided
-     * by XMLCipher, usually a XMLSerializer according to DOM 3 specification).
-     * 
-     * @param algo
-     *            Is the name of the canonicalization algorithm
-     */
-    public void setEncCanonicalization(String algo) {
-        encCanonAlgo = algo;
-    }
-    
-    /**
-     * Get the name of symmetric encryption algorithm to use.
-     * 
-     * The name of the encryption algorithm to encrypt the data, i.e. the SOAP
-     * Body. Refer to WSConstants which algorithms are supported.
-     * 
-     * @return the name of the currently selected symmetric encryption algorithm
-     * @see WSConstants#TRIPLE_DES
-     * @see WSConstants#AES_128
-     * @see WSConstants#AES_192
-     * @see WSConstants#AES_256
-     */
-    public String getSymmetricEncAlgorithm() {
-        return symEncAlgo;
-    }
-    
-    /**
-     * Initialize a WSSec Encrypt.
-     * 
-     * The method prepares and initializes a WSSec Encrypt structure after the
-     * relevant information was set. After preparation of the token references
-     * can be added and encrypted.
-     * 
-     * </p>
-     * 
-     * This method does not add any element to the security header. This must be
-     * done explicitly.
-     * 
-     * @param doc
-     *            The SOAP envelope as <code>Document</code>
-     * @param crypto
-     *            An instance of the Crypto API to handle keystore and
-     *            certificates
-     * @throws WSSecurityException
-     */
-    public void prepare(Document doc, Crypto crypto) throws WSSecurityException {
-
-        document = doc;
-
-        /*
-         * If no external key (symmetricalKey) was set generate an encryption
-         * key (session key) for this Encrypt element. This key will be
-         * encrypted using the public key of the receiver
-         */
-        
-        
-        if(this.ephemeralKey == null) {
-            if (symmetricKey == null) {
-                KeyGenerator keyGen = getKeyGenerator();
-                this.symmetricKey = keyGen.generateKey();
-            } 
-            this.ephemeralKey = this.symmetricKey.getEncoded();
-        }
-        
-        if (this.symmetricKey == null) {
-
-            this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
-                    this.ephemeralKey);
-        }
-        
-        /*
-         * Get the certificate that contains the public key for the public key
-         * algorithm that will encrypt the generated symmetric (session) key.
-         */
-        if(this.encryptSymmKey) {
-            X509Certificate remoteCert = null;
-            if (useThisCert != null) {
-                remoteCert = useThisCert;
-            } else {
-                X509Certificate[] certs = crypto.getCertificates(user);
-                if (certs == null || certs.length <= 0) {
-                    throw new WSSecurityException(WSSecurityException.FAILURE,
-                            "invalidX509Data", new Object[] { "for Encryption" });
-                }
-                remoteCert = certs[0];
-            }
-            prepareInternal(this.ephemeralKey, remoteCert, crypto);
-        }
-    }
-
-    /**
-     * Builds the SOAP envelope with encrypted Body and adds encrypted key.
-     * 
-     * This is a convenience method and for backward compatibility. The method
-     * calls the single function methods in order to perform a <i>one shot
-     * encryption</i>. This method is compatible with the build method of the
-     * previous version with the exception of the additional WSSecHeader
-     * parameter.
-     * 
-     * @param doc
-     *            the SOAP envelope as <code>Document</code> with plain text
-     *            Body
-     * @param crypto
-     *            an instance of the Crypto API to handle keystore and
-     *            Certificates
-     * @param secHeader
-     *            the security header element to hold the encrypted key element.
-     * @return the SOAP envelope with encrypted Body as <code>Document
-     *         </code>
-     * @throws WSSecurityException
-     */
-    public Document build(Document doc, Crypto crypto, WSSecHeader secHeader)
-            throws WSSecurityException {
-        doDebug = log.isDebugEnabled();
-
-        if (keyIdentifierType == WSConstants.EMBEDDED_KEYNAME
-                || keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
-            return buildEmbedded(doc, crypto, secHeader);
-        }
-
-        if (doDebug) {
-            log.debug("Beginning Encryption...");
-        }
-
-        prepare(doc, crypto);
-
-        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
-        if (parts == null) {
-            parts = new Vector();
-            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
-                    .getBodyQName().getLocalPart(), soapConstants
-                    .getEnvelopeURI(), "Content");
-            parts.add(encP);
-        }
-
-        Element refs = encryptForInternalRef(null, parts);
-        addInternalRefElement(refs);
-
-        prependToHeader(secHeader);
-
-        if (bstToken != null) {
-            prependBSTElementToHeader(secHeader);
-        }
-
-        log.debug("Encryption complete.");
-        return doc;
-    }
-
-    /**
-     * Encrypt one or more parts or elements of the message (internal).
-     * 
-     * This method takes a vector of <code>WSEncryptionPart</code> object that
-     * contain information about the elements to encrypt. The method call the
-     * encryption method, takes the reference information generated during
-     * encryption and add this to the <code>xenc:Reference</code> element.
-     * This method can be called after <code>prepare()</code> and can be
-     * called multiple times to encrypt a number of parts or elements.
-     * 
-     * </p>
-     * 
-     * The method generates a <code>xenc:Reference</code> element that <i>must</i>
-     * be added to this token. See <code>addInternalRefElement()</code>.
-     * 
-     * </p>
-     * 
-     * If the <code>dataRef</code> parameter is <code>null</code> the method
-     * creates and initializes a new Reference element.
-     * 
-     * @param dataRef
-     *            A <code>xenc:Reference</code> element or <code>null</code>
-     * @param references
-     *            A vector containing WSEncryptionPart objects
-     * @return Returns the updated <code>xenc:Reference</code> element
-     * @throws WSSecurityException
-     */
-    public Element encryptForInternalRef(Element dataRef, Vector references)
-            throws WSSecurityException {
-        Vector encDataRefs = doEncryption(document, this.symmetricKey,
-                references);
-        Element referenceList = dataRef;
-        if (referenceList == null) {
-            referenceList = document.createElementNS(WSConstants.ENC_NS,
-                    WSConstants.ENC_PREFIX + ":ReferenceList");
-        }
-        createDataRefList(document, referenceList, encDataRefs);
-        return referenceList;
-    }
-
-    /**
-     * Encrypt one or more parts or elements of the message (external).
-     * 
-     * This method takes a vector of <code>WSEncryptionPart</code> object that
-     * contain information about the elements to encrypt. The method call the
-     * encryption method, takes the reference information generated during
-     * encryption and add this to the <code>xenc:Reference</code> element.
-     * This method can be called after <code>prepare()</code> and can be
-     * called multiple times to encrypt a number of parts or elements.
-     * 
-     * </p>
-     * 
-     * The method generates a <code>xenc:Reference</code> element that <i>must</i>
-     * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
-     * 
-     * </p>
-     * 
-     * If the <code>dataRef</code> parameter is <code>null</code> the method
-     * creates and initializes a new Reference element.
-     * 
-     * @param dataRef
-     *            A <code>xenc:Reference</code> element or <code>null</code>
-     * @param references
-     *            A vector containing WSEncryptionPart objects
-     * @return Returns the updated <code>xenc:Reference</code> element
-     * @throws WSSecurityException
-     */
-    public Element encryptForExternalRef(Element dataRef, Vector references)
-            throws WSSecurityException {
-
-        Vector encDataRefs = doEncryption(document, this.symmetricKey,
-                references);
-        Element referenceList = dataRef;
-        if (referenceList == null) {
-            referenceList = document.createElementNS(WSConstants.ENC_NS,
-                    WSConstants.ENC_PREFIX + ":ReferenceList");
-        }
-        createDataRefList(document, referenceList, encDataRefs);
-        return referenceList;
-    }
-
-    /**
-     * Adds the internal Reference element to this Encrypt data.
-     * 
-     * The reference element <i>must</i> be created by the
-     * <code>encryptForInternalRef()</code> method. The reference element is
-     * added to the <code>EncryptedKey</code> element of this encrypt block.
-     * 
-     * @param dataRef
-     *            The internal <code>enc:Reference</code> element
-     */
-    public void addInternalRefElement(Element dataRef) {
-        WSSecurityUtil.appendChildElement(document, encryptedKeyElement, dataRef);
-    }
-
-    /**
-     * Adds (prepends) the external Reference element to the Security header.
-     * 
-     * The reference element <i>must</i> be created by the
-     * <code>encryptForExternalRef() </code> method. The method prepends the
-     * reference element in the SecurityHeader.
-     * 
-     * @param dataRef
-     *            The external <code>enc:Reference</code> element
-     * @param secHeader
-     *            The security header.
-     */
-    public void addExternalRefElement(Element dataRef, WSSecHeader secHeader) {
-        WSSecurityUtil.prependChildElement(document, secHeader
-                .getSecurityHeader(), dataRef, false);
-    }
-
-    private Vector doEncryption(Document doc, SecretKey secretKey,
-            Vector references) throws WSSecurityException {
-        
-        KeyInfo keyInfo = null;
-        
-        // Prepare KeyInfo if useKeyIdentifier is set
-        if (keyIdentifierType == WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER) {
-            keyInfo = new KeyInfo(document);
-            SecurityTokenReference secToken = new SecurityTokenReference(document);
-            if(this.customReferenceValue != null) {
-                secToken.setKeyIdentifierEncKeySHA1(this.customReferenceValue);
-            } else {
-                secToken.setKeyIdentifierEncKeySHA1(getSHA1(encryptedEphemeralKey));
-            }
-            
-
-            keyInfo.addUnknownElement(secToken.getElement());
-        } 
-        
-        return doEncryption(doc, secretKey, keyInfo, references);
-    }
-
-    private Vector doEncryption(Document doc, SecretKey secretKey,
-            KeyInfo keyInfo, Vector references) throws WSSecurityException {
-
-        XMLCipher xmlCipher = null;
-        try {
-            xmlCipher = XMLCipher.getInstance(symEncAlgo);
-        } catch (XMLEncryptionException e3) {
-            throw new WSSecurityException(
-                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
-        }
-
-        Vector encDataRef = new Vector();
-
-        boolean cloneKeyInfo = false;
-        for (int part = 0; part < references.size(); part++) {
-            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
-
-            String idToEnc = encPart.getId();
-
-            String elemName = encPart.getName();
-            String nmSpace = encPart.getNamespace();
-            String modifier = encPart.getEncModifier();
-            /*
-             * Third step: get the data to encrypt.
-             * 
-             */
-            Element body = null;
-            if (idToEnc != null) {
-                body = WSSecurityUtil.findElementById(document
-                        .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
-                if (body == null) {
-                    body = WSSecurityUtil.findElementById(document
-                            .getDocumentElement(), idToEnc, null);
-                }
-            } else {
-                body = (Element) WSSecurityUtil.findElement(document, elemName,
-                        nmSpace);
-            }
-            if (body == null) {
-                throw new WSSecurityException(WSSecurityException.FAILURE,
-                        "noEncElement", new Object[] { "{" + nmSpace + "}"
-                                + elemName });
-            }
-
-            boolean content = modifier.equals("Content") ? true : false;
-            String xencEncryptedDataId = "EncDataId-" + body.hashCode();
-            encPart.setEncId(xencEncryptedDataId);
-
-            cloneKeyInfo = true;
-            
-            if(keyInfo == null) {
-                keyInfo = new KeyInfo(document);
-                SecurityTokenReference secToken = new SecurityTokenReference(document);
-                Reference ref = new Reference(document);
-                ref.setURI("#" + encKeyId);
-                secToken.setReference(ref);
-                keyInfo.addUnknownElement(secToken.getElement());
-            }
-            /*
-             * Forth step: encrypt data, and set necessary attributes in
-             * xenc:EncryptedData
-             */
-            try {
-                
-                if (modifier.equals("Header")) {
-                    
-                    Element elem = doc.createElementNS(WSConstants.WSSE11_NS,"wsse11:"+WSConstants.ENCRYPTED_HEADER);
-                    WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
-                    String wsuPrefix = WSSecurityUtil.setNamespace(elem,
-                            WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
-                    elem.setAttributeNS(WSConstants.WSU_NS, wsuPrefix + ":Id", "EncHeader-" + body.hashCode());
-                    
-                    
-                    NamedNodeMap map = body.getAttributes();
-                    
-                    for (int i = 0 ; i < map.getLength() ; i++) {
-                        Attr attr = (Attr)map.item(i);
-                        if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)
-                                || attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {                         
-                            String soapEnvPrefix = WSSecurityUtil.setNamespace(elem,
-                                    attr.getNamespaceURI(), "soapevn");
-                            elem.setAttributeNS(attr.getNamespaceURI(), soapEnvPrefix +":"+attr.getLocalName(), attr.getValue());
-                        }
-                    }
-                    
-                    xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
-                    EncryptedData encData = xmlCipher.getEncryptedData();
-                    encData.setId(xencEncryptedDataId);
-                    encData.setKeyInfo(keyInfo);
-                    xmlCipher.doFinal(doc, body, content);
-                    
-                    Element encDataElem = WSSecurityUtil.findElementById(document
-                            .getDocumentElement(), xencEncryptedDataId, null);
-                    Node clone = encDataElem.cloneNode(true);
-                    elem.appendChild(clone);
-                    encDataElem.getParentNode().appendChild(elem);
-                    encDataElem.getParentNode().removeChild(encDataElem); 
-                    
-                } else {
-                    xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
-                    EncryptedData encData = xmlCipher.getEncryptedData();
-                    encData.setId(xencEncryptedDataId);
-                    encData.setKeyInfo(keyInfo);
-                    xmlCipher.doFinal(doc, body, content);          
-                }
-                if(cloneKeyInfo) {
-                    keyInfo = new KeyInfo((Element) keyInfo.getElement()
-                            .cloneNode(true), null);
-                }
-            } catch (Exception e2) {
-                throw new WSSecurityException(
-                        WSSecurityException.FAILED_ENC_DEC, null, null, e2);
-            }
-            encDataRef.add(new String("#" + xencEncryptedDataId));
-        }
-        return encDataRef;
-    }
-
-    private Document buildEmbedded(Document doc, Crypto crypto,
-            WSSecHeader secHeader) throws WSSecurityException {
-        doDebug = log.isDebugEnabled();
-
-        if (doDebug) {
-            log.debug("Beginning Encryption embedded...");
-        }
-        envelope = doc.getDocumentElement();
-        envelope.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
-                + WSConstants.ENC_PREFIX, WSConstants.ENC_NS);
-
-        /*
-         * Second step: generate a symmetric key from the specified key
-         * (password) for this algorithm, and set the cipher into encryption
-         * mode.
-         */
-        if (this.symmetricKey == null) {
-            if (embeddedKey == null) {
-                throw new WSSecurityException(WSSecurityException.FAILURE,
-                        "noKeySupplied");
-            }
-            this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
-                    embeddedKey);
-        }
-
-        KeyInfo keyInfo = null;
-        if (this.keyIdentifierType == WSConstants.EMBEDDED_KEYNAME) {
-            keyInfo = new KeyInfo(doc);
-            keyInfo
-                    .addKeyName(embeddedKeyName == null ? user
-                            : embeddedKeyName);
-        } else if (this.keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
-            /*
-             * This means that we want to embed a <wsse:SecurityTokenReference>
-             * into keyInfo element. If we need this functionality, this.secRef
-             * MUST be set before calling the build(doc, crypto) method. So if
-             * secRef is null then throw an exception.
-             */
-            if (this.securityTokenReference == null) {
-                throw new WSSecurityException(
-                        WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
-                        "You must set keyInfo element, if the keyIdentifier "
-                                + "== EMBED_SECURITY_TOKEN_REF");
-            } else {
-                keyInfo = new KeyInfo(doc);
-                Element tmpE = securityTokenReference.getElement();
-                tmpE.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
-                        + tmpE.getPrefix(), tmpE.getNamespaceURI());
-                keyInfo.addUnknownElement(securityTokenReference.getElement());
-            }
-        }
-
-        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
-        if (parts == null) {
-            parts = new Vector();
-            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
-                    .getBodyQName().getLocalPart(), soapConstants
-                    .getEnvelopeURI(), "Content");
-            parts.add(encP);
-        }
-        Vector encDataRefs = doEncryption(doc, this.symmetricKey, keyInfo,
-                parts);
-
-        /*
-         * At this point data is encrypted with the symmetric key and can be
-         * referenced via the above Id
-         */
-
-        /*
-         * Now we need to setup the wsse:Security header block 1) get (or
-         * create) the wsse:Security header block 2) The last step sets up the
-         * reference list that pints to the encrypted data
-         */
-        Element wsseSecurity = secHeader.getSecurityHeader();
-
-        Element referenceList = doc.createElementNS(WSConstants.ENC_NS,
-                WSConstants.ENC_PREFIX + ":ReferenceList");
-        referenceList = createDataRefList(doc, referenceList, encDataRefs);
-        WSSecurityUtil.prependChildElement(doc, wsseSecurity, referenceList,
-                true);
-
-        return doc;
-    }
-
-    private KeyGenerator getKeyGenerator() throws WSSecurityException {
-        KeyGenerator keyGen = null;
-        try {
-            /*
-             * Assume AES as default, so initialize it
-             */
-            keyGen = KeyGenerator.getInstance("AES");
-            if (symEncAlgo.equalsIgnoreCase(WSConstants.TRIPLE_DES)) {
-                keyGen = KeyGenerator.getInstance("DESede");
-            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_128)) {
-                keyGen.init(128);
-            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_192)) {
-                keyGen.init(192);
-            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_256)) {
-                keyGen.init(256);
-            } else {
-                return null;
-            }
-        } catch (NoSuchAlgorithmException e) {
-            throw new WSSecurityException(
-                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
-        }
-        return keyGen;
-    }
-
-    /**
-     * Create DOM subtree for <code>xenc:EncryptedKey</code>
-     * 
-     * @param doc
-     *            the SOAP envelope parent document
-     * @param keyTransportAlgo
-     *            specifies which algorithm to use to encrypt the symmetric key
-     * @return an <code>xenc:EncryptedKey</code> element
-     */
-
-    public static Element createDataRefList(Document doc,
-            Element referenceList, Vector encDataRefs) {
-        for (int i = 0; i < encDataRefs.size(); i++) {
-            String dataReferenceUri = (String) encDataRefs.get(i);
-            Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
-                    WSConstants.ENC_PREFIX + ":DataReference");
-            dataReference.setAttributeNS(null, "URI", dataReferenceUri);
-            referenceList.appendChild(dataReference);
-        }
-        return referenceList;
-    }
-
-    /**
-     * @return The symmetric key
-     */
-    public SecretKey getSymmetricKey() {
-        return symmetricKey;
-    }
-
-    /**
-     * Set the symmetric key to be used for encryption
-     * 
-     * @param key
-     */
-    public void setSymmetricKey(SecretKey key) {
-        this.symmetricKey = key;
-    }
-
-    /**
-     * @return Return the SecurityTokenRefernce
-     */
-    public SecurityTokenReference getSecurityTokenReference() {
-        return securityTokenReference;
-    }
-
-    /**
-     * @param reference
-     */
-    public void setSecurityTokenReference(SecurityTokenReference reference) {
-        securityTokenReference = reference;
-    }
-
-    public boolean isEncryptSymmKey() {
-        return encryptSymmKey;
-    }
-
-    public void setEncryptSymmKey(boolean encryptSymmKey) {
-        this.encryptSymmKey = encryptSymmKey;
-    }
-
-    private String getSHA1(byte[] input) throws WSSecurityException {
-        try {
-            MessageDigest sha = null;
-            sha = MessageDigest.getInstance("SHA-1");
-            sha.reset();
-            sha.update(input);
-            byte[] data = sha.digest();
-            
-            return Base64.encode(data);
-        } catch (NoSuchAlgorithmException e) {
-            throw new WSSecurityException(
-                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
-        }
-    }
-
-    public void setCustomReferenceValue(String customReferenceValue) {
-        this.customReferenceValue = customReferenceValue;
-    }
-    
-}
+/*
+ * 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 org.apache.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.util.Base64;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.EncryptedData;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.Vector;
+
+/**
+ * Encrypts a parts of a message according to WS Specification, X509 profile,
+ * and adds the encryption data.
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com).
+ * @author Werner Dittmann (Werner.Dittmann@apache.org).
+ */
+public class WSSecEncrypt extends WSSecEncryptedKey {
+    private static Log log = LogFactory.getLog(WSSecEncrypt.class.getName());
+
+    private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
+
+    protected String symEncAlgo = WSConstants.AES_128;
+
+    protected String encCanonAlgo = null;
+
+    protected byte[] embeddedKey = null;
+
+    protected String embeddedKeyName = null;
+
+    /**
+     * Symmetric key used in the EncrytpedKey.
+     */
+    protected SecretKey symmetricKey = null;
+
+    /**
+     * SecurityTokenReference to be inserted into EncryptedData/keyInfo element.
+     */
+    protected SecurityTokenReference securityTokenReference = null;
+
+    /**
+     * Indicates whether to encrypt the symmetric key into an EncryptedKey 
+     * or not.
+     */
+    private boolean encryptSymmKey = true;
+    
+    /**
+     * Custom reference value
+     */
+    private String customReferenceValue;
+
+    /**
+     * Constructor.
+     */
+    public WSSecEncrypt() {
+    }
+
+    /**
+     * Sets the key to use during embedded encryption.
+     * 
+     * <p/>
+     * 
+     * @param key
+     *            to use during encryption. The key must fit the selected
+     *            symmetrical encryption algorithm
+     */
+    public void setKey(byte[] key) {
+        this.embeddedKey = key;
+    }
+
+    /**
+     * Sets the algorithm to encode the symmetric key.
+     * 
+     * Default is the <code>WSConstants.KEYTRANSPORT_RSA15</code> algorithm.
+     * 
+     * @param keyEnc
+     *            specifies the key encoding algorithm.
+     * @see WSConstants#KEYTRANSPORT_RSA15
+     * @see WSConstants#KEYTRANSPORT_RSAOEP
+     */
+    public void setKeyEnc(String keyEnc) {
+        keyEncAlgo = keyEnc;
+    }
+
+    /**
+     * Set the key name for EMBEDDED_KEYNAME
+     * 
+     * @param embeddedKeyName
+     */
+    public void setEmbeddedKeyName(String embeddedKeyName) {
+        this.embeddedKeyName = embeddedKeyName;
+    }
+    
+    /**
+     * Set the name of the symmetric encryption algorithm to use.
+     * 
+     * This encryption algorithm is used to encrypt the data. If the algorithm
+     * is not set then AES128 is used. Refer to WSConstants which algorithms are
+     * supported.
+     * 
+     * @param algo
+     *            Is the name of the encryption algorithm
+     * @see WSConstants#TRIPLE_DES
+     * @see WSConstants#AES_128
+     * @see WSConstants#AES_192
+     * @see WSConstants#AES_256
+     */
+    public void setSymmetricEncAlgorithm(String algo) {
+        symEncAlgo = algo;
+    }
+
+    /**
+     * Set the name of an optional canonicalization algorithm to use before
+     * encryption.
+     * 
+     * This c14n algorithm is used to serialize the data before encryption. If
+     * the algorithm is not set then a standard serialization is used (provided
+     * by XMLCipher, usually a XMLSerializer according to DOM 3 specification).
+     * 
+     * @param algo
+     *            Is the name of the canonicalization algorithm
+     */
+    public void setEncCanonicalization(String algo) {
+        encCanonAlgo = algo;
+    }
+    
+    /**
+     * Get the name of symmetric encryption algorithm to use.
+     * 
+     * The name of the encryption algorithm to encrypt the data, i.e. the SOAP
+     * Body. Refer to WSConstants which algorithms are supported.
+     * 
+     * @return the name of the currently selected symmetric encryption algorithm
+     * @see WSConstants#TRIPLE_DES
+     * @see WSConstants#AES_128
+     * @see WSConstants#AES_192
+     * @see WSConstants#AES_256
+     */
+    public String getSymmetricEncAlgorithm() {
+        return symEncAlgo;
+    }
+    
+    /**
+     * Initialize a WSSec Encrypt.
+     * 
+     * The method prepares and initializes a WSSec Encrypt structure after the
+     * relevant information was set. After preparation of the token references
+     * can be added and encrypted.
+     * 
+     * </p>
+     * 
+     * This method does not add any element to the security header. This must be
+     * done explicitly.
+     * 
+     * @param doc
+     *            The SOAP envelope as <code>Document</code>
+     * @param crypto
+     *            An instance of the Crypto API to handle keystore and
+     *            certificates
+     * @throws WSSecurityException
+     */
+    public void prepare(Document doc, Crypto crypto) throws WSSecurityException {
+
+        document = doc;
+
+        /*
+         * If no external key (symmetricalKey) was set generate an encryption
+         * key (session key) for this Encrypt element. This key will be
+         * encrypted using the public key of the receiver
+         */
+        
+        
+        if(this.ephemeralKey == null) {
+            if (symmetricKey == null) {
+                KeyGenerator keyGen = getKeyGenerator();
+                this.symmetricKey = keyGen.generateKey();
+            } 
+            this.ephemeralKey = this.symmetricKey.getEncoded();
+        }
+        
+        if (this.symmetricKey == null) {
+
+            this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
+                    this.ephemeralKey);
+        }
+        
+        /*
+         * Get the certificate that contains the public key for the public key
+         * algorithm that will encrypt the generated symmetric (session) key.
+         */
+        if(this.encryptSymmKey) {
+            X509Certificate remoteCert = null;
+            if (useThisCert != null) {
+                remoteCert = useThisCert;
+            } else {
+                X509Certificate[] certs = crypto.getCertificates(user);
+                if (certs == null || certs.length <= 0) {
+                    throw new WSSecurityException(WSSecurityException.FAILURE,
+                            "invalidX509Data", new Object[] { "for Encryption" });
+                }
+                remoteCert = certs[0];
+            }
+            prepareInternal(this.ephemeralKey, remoteCert, crypto);
+        }
+    }
+
+    /**
+     * Builds the SOAP envelope with encrypted Body and adds encrypted key.
+     * 
+     * This is a convenience method and for backward compatibility. The method
+     * calls the single function methods in order to perform a <i>one shot
+     * encryption</i>. This method is compatible with the build method of the
+     * previous version with the exception of the additional WSSecHeader
+     * parameter.
+     * 
+     * @param doc
+     *            the SOAP envelope as <code>Document</code> with plain text
+     *            Body
+     * @param crypto
+     *            an instance of the Crypto API to handle keystore and
+     *            Certificates
+     * @param secHeader
+     *            the security header element to hold the encrypted key element.
+     * @return the SOAP envelope with encrypted Body as <code>Document
+     *         </code>
+     * @throws WSSecurityException
+     */
+    public Document build(Document doc, Crypto crypto, WSSecHeader secHeader)
+            throws WSSecurityException {
+        doDebug = log.isDebugEnabled();
+
+        if (keyIdentifierType == WSConstants.EMBEDDED_KEYNAME
+                || keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
+            return buildEmbedded(doc, crypto, secHeader);
+        }
+
+        if (doDebug) {
+            log.debug("Beginning Encryption...");
+        }
+
+        prepare(doc, crypto);
+
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+
+        Element refs = encryptForInternalRef(null, parts);
+        addInternalRefElement(refs);
+
+        prependToHeader(secHeader);
+
+        if (bstToken != null) {
+            prependBSTElementToHeader(secHeader);
+        }
+
+        log.debug("Encryption complete.");
+        return doc;
+    }
+
+    /**
+     * Encrypt one or more parts or elements of the message (internal).
+     * 
+     * This method takes a vector of <code>WSEncryptionPart</code> object that
+     * contain information about the elements to encrypt. The method call the
+     * encryption method, takes the reference information generated during
+     * encryption and add this to the <code>xenc:Reference</code> element.
+     * This method can be called after <code>prepare()</code> and can be
+     * called multiple times to encrypt a number of parts or elements.
+     * 
+     * </p>
+     * 
+     * The method generates a <code>xenc:Reference</code> element that <i>must</i>
+     * be added to this token. See <code>addInternalRefElement()</code>.
+     * 
+     * </p>
+     * 
+     * If the <code>dataRef</code> parameter is <code>null</code> the method
+     * creates and initializes a new Reference element.
+     * 
+     * @param dataRef
+     *            A <code>xenc:Reference</code> element or <code>null</code>
+     * @param references
+     *            A vector containing WSEncryptionPart objects
+     * @return Returns the updated <code>xenc:Reference</code> element
+     * @throws WSSecurityException
+     */
+    public Element encryptForInternalRef(Element dataRef, Vector references)
+            throws WSSecurityException {
+        Vector encDataRefs = doEncryption(document, this.symmetricKey,
+                references);
+        Element referenceList = dataRef;
+        if (referenceList == null) {
+            referenceList = document.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":ReferenceList");
+        }
+        createDataRefList(document, referenceList, encDataRefs);
+        return referenceList;
+    }
+
+    /**
+     * Encrypt one or more parts or elements of the message (external).
+     * 
+     * This method takes a vector of <code>WSEncryptionPart</code> object that
+     * contain information about the elements to encrypt. The method call the
+     * encryption method, takes the reference information generated during
+     * encryption and add this to the <code>xenc:Reference</code> element.
+     * This method can be called after <code>prepare()</code> and can be
+     * called multiple times to encrypt a number of parts or elements.
+     * 
+     * </p>
+     * 
+     * The method generates a <code>xenc:Reference</code> element that <i>must</i>
+     * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
+     * 
+     * </p>
+     * 
+     * If the <code>dataRef</code> parameter is <code>null</code> the method
+     * creates and initializes a new Reference element.
+     * 
+     * @param dataRef
+     *            A <code>xenc:Reference</code> element or <code>null</code>
+     * @param references
+     *            A vector containing WSEncryptionPart objects
+     * @return Returns the updated <code>xenc:Reference</code> element
+     * @throws WSSecurityException
+     */
+    public Element encryptForExternalRef(Element dataRef, Vector references)
+            throws WSSecurityException {
+
+        Vector encDataRefs = doEncryption(document, this.symmetricKey,
+                references);
+        Element referenceList = dataRef;
+        if (referenceList == null) {
+            referenceList = document.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":ReferenceList");
+        }
+        createDataRefList(document, referenceList, encDataRefs);
+        return referenceList;
+    }
+
+    /**
+     * Adds the internal Reference element to this Encrypt data.
+     * 
+     * The reference element <i>must</i> be created by the
+     * <code>encryptForInternalRef()</code> method. The reference element is
+     * added to the <code>EncryptedKey</code> element of this encrypt block.
+     * 
+     * @param dataRef
+     *            The internal <code>enc:Reference</code> element
+     */
+    public void addInternalRefElement(Element dataRef) {
+        WSSecurityUtil.appendChildElement(document, encryptedKeyElement, dataRef);
+    }
+
+    /**
+     * Adds (prepends) the external Reference element to the Security header.
+     * 
+     * The reference element <i>must</i> be created by the
+     * <code>encryptForExternalRef() </code> method. The method prepends the
+     * reference element in the SecurityHeader.
+     * 
+     * @param dataRef
+     *            The external <code>enc:Reference</code> element
+     * @param secHeader
+     *            The security header.
+     */
+    public void addExternalRefElement(Element dataRef, WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader
+                .getSecurityHeader(), dataRef, false);
+    }
+
+    private Vector doEncryption(Document doc, SecretKey secretKey,
+            Vector references) throws WSSecurityException {
+        
+        KeyInfo keyInfo = null;
+        
+        // Prepare KeyInfo if useKeyIdentifier is set
+        if (keyIdentifierType == WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER) {
+            keyInfo = new KeyInfo(document);
+            SecurityTokenReference secToken = new SecurityTokenReference(document);
+            if(this.customReferenceValue != null) {
+                secToken.setKeyIdentifierEncKeySHA1(this.customReferenceValue);
+            } else {
+                secToken.setKeyIdentifierEncKeySHA1(getSHA1(encryptedEphemeralKey));
+            }
+            
+
+            keyInfo.addUnknownElement(secToken.getElement());
+        } 
+        
+        return doEncryption(doc, secretKey, keyInfo, references);
+    }
+
+    private Vector doEncryption(Document doc, SecretKey secretKey,
+            KeyInfo keyInfo, Vector references) throws WSSecurityException {
+
+        XMLCipher xmlCipher = null;
+        try {
+            xmlCipher = XMLCipher.getInstance(symEncAlgo);
+        } catch (XMLEncryptionException e3) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
+        }
+
+        Vector encDataRef = new Vector();
+
+        boolean cloneKeyInfo = false;
+        for (int part = 0; part < references.size(); part++) {
+            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
+
+            String idToEnc = encPart.getId();
+
+            String elemName = encPart.getName();
+            String nmSpace = encPart.getNamespace();
+            String modifier = encPart.getEncModifier();
+            /*
+             * Third step: get the data to encrypt.
+             * 
+             */
+            Element body = null;
+            if (idToEnc != null) {
+                body = WSSecurityUtil.findElementById(document
+                        .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
+                if (body == null) {
+                    body = WSSecurityUtil.findElementById(document
+                            .getDocumentElement(), idToEnc, null);
+                }
+            } else {
+                body = (Element) WSSecurityUtil.findElement(document, elemName,
+                        nmSpace);
+            }
+            if (body == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noEncElement", new Object[] { "{" + nmSpace + "}"
+                                + elemName });
+            }
+
+            boolean content = modifier.equals("Content") ? true : false;
+            String xencEncryptedDataId = "EncDataId-" + body.hashCode();
+            encPart.setEncId(xencEncryptedDataId);
+
+            cloneKeyInfo = true;
+            
+            if(keyInfo == null) {
+                keyInfo = new KeyInfo(document);
+                SecurityTokenReference secToken = new SecurityTokenReference(document);
+                Reference ref = new Reference(document);
+                ref.setURI("#" + encKeyId);
+                secToken.setReference(ref);
+                keyInfo.addUnknownElement(secToken.getElement());
+            }
+            /*
+             * Forth step: encrypt data, and set necessary attributes in
+             * xenc:EncryptedData
+             */
+            try {
+                
+                if (modifier.equals("Header")) {
+                    
+                    Element elem = doc.createElementNS(WSConstants.WSSE11_NS,"wsse11:"+WSConstants.ENCRYPTED_HEADER);
+                    WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
+                    String wsuPrefix = WSSecurityUtil.setNamespace(elem,
+                            WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+                    elem.setAttributeNS(WSConstants.WSU_NS, wsuPrefix + ":Id", "EncHeader-" + body.hashCode());
+                    
+                    
+                    NamedNodeMap map = body.getAttributes();
+                    
+                    for (int i = 0 ; i < map.getLength() ; i++) {
+                        Attr attr = (Attr)map.item(i);
+                        if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)
+                                || attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {                         
+                            String soapEnvPrefix = WSSecurityUtil.setNamespace(elem,
+                                    attr.getNamespaceURI(), "soapevn");
+                            elem.setAttributeNS(attr.getNamespaceURI(), soapEnvPrefix +":"+attr.getLocalName(), attr.getValue());
+                        }
+                    }
+                    
+                    xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
+                    EncryptedData encData = xmlCipher.getEncryptedData();
+                    encData.setId(xencEncryptedDataId);
+                    encData.setKeyInfo(keyInfo);
+                    xmlCipher.doFinal(doc, body, content);
+                    
+                    Element encDataElem = WSSecurityUtil.findElementById(document
+                            .getDocumentElement(), xencEncryptedDataId, null);
+                    Node clone = encDataElem.cloneNode(true);
+                    elem.appendChild(clone);
+                    encDataElem.getParentNode().appendChild(elem);
+                    encDataElem.getParentNode().removeChild(encDataElem); 
+                    
+                } else {
+                    xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
+                    EncryptedData encData = xmlCipher.getEncryptedData();
+                    encData.setId(xencEncryptedDataId);
+                    encData.setKeyInfo(keyInfo);
+                    xmlCipher.doFinal(doc, body, content);          
+                }
+                if(cloneKeyInfo) {
+                    keyInfo = new KeyInfo((Element) keyInfo.getElement()
+                            .cloneNode(true), null);
+                }
+            } catch (Exception e2) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_ENCRYPTION, null, null, e2);
+            }
+            encDataRef.add(new String("#" + xencEncryptedDataId));
+        }
+        return encDataRef;
+    }
+
+    private Document buildEmbedded(Document doc, Crypto crypto,
+            WSSecHeader secHeader) throws WSSecurityException {
+        doDebug = log.isDebugEnabled();
+
+        if (doDebug) {
+            log.debug("Beginning Encryption embedded...");
+        }
+        envelope = doc.getDocumentElement();
+        envelope.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                + WSConstants.ENC_PREFIX, WSConstants.ENC_NS);
+
+        /*
+         * Second step: generate a symmetric key from the specified key
+         * (password) for this algorithm, and set the cipher into encryption
+         * mode.
+         */
+        if (this.symmetricKey == null) {
+            if (embeddedKey == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noKeySupplied");
+            }
+            this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
+                    embeddedKey);
+        }
+
+        KeyInfo keyInfo = null;
+        if (this.keyIdentifierType == WSConstants.EMBEDDED_KEYNAME) {
+            keyInfo = new KeyInfo(doc);
+            keyInfo
+                    .addKeyName(embeddedKeyName == null ? user
+                            : embeddedKeyName);
+        } else if (this.keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
+            /*
+             * This means that we want to embed a <wsse:SecurityTokenReference>
+             * into keyInfo element. If we need this functionality, this.secRef
+             * MUST be set before calling the build(doc, crypto) method. So if
+             * secRef is null then throw an exception.
+             */
+            if (this.securityTokenReference == null) {
+                throw new WSSecurityException(
+                        WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+                        "You must set keyInfo element, if the keyIdentifier "
+                                + "== EMBED_SECURITY_TOKEN_REF");
+            } else {
+                keyInfo = new KeyInfo(doc);
+                Element tmpE = securityTokenReference.getElement();
+                tmpE.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                        + tmpE.getPrefix(), tmpE.getNamespaceURI());
+                keyInfo.addUnknownElement(securityTokenReference.getElement());
+            }
+        }
+
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+        Vector encDataRefs = doEncryption(doc, this.symmetricKey, keyInfo,
+                parts);
+
+        /*
+         * At this point data is encrypted with the symmetric key and can be
+         * referenced via the above Id
+         */
+
+        /*
+         * Now we need to setup the wsse:Security header block 1) get (or
+         * create) the wsse:Security header block 2) The last step sets up the
+         * reference list that pints to the encrypted data
+         */
+        Element wsseSecurity = secHeader.getSecurityHeader();
+
+        Element referenceList = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":ReferenceList");
+        referenceList = createDataRefList(doc, referenceList, encDataRefs);
+        WSSecurityUtil.prependChildElement(doc, wsseSecurity, referenceList,
+                true);
+
+        return doc;
+    }
+
+    private KeyGenerator getKeyGenerator() throws WSSecurityException {
+        KeyGenerator keyGen = null;
+        try {
+            /*
+             * Assume AES as default, so initialize it
+             */
+            keyGen = KeyGenerator.getInstance("AES");
+            if (symEncAlgo.equalsIgnoreCase(WSConstants.TRIPLE_DES)) {
+                keyGen = KeyGenerator.getInstance("DESede");
+            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_128)) {
+                keyGen.init(128);
+            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_192)) {
+                keyGen.init(192);
+            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_256)) {
+                keyGen.init(256);
+            } else {
+                return null;
+            }
+        } catch (NoSuchAlgorithmException e) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
+        }
+        return keyGen;
+    }
+
+    /**
+     * Create DOM subtree for <code>xenc:EncryptedKey</code>
+     * 
+     * @param doc
+     *            the SOAP envelope parent document
+     * @param keyTransportAlgo
+     *            specifies which algorithm to use to encrypt the symmetric key
+     * @return an <code>xenc:EncryptedKey</code> element
+     */
+
+    public static Element createDataRefList(Document doc,
+            Element referenceList, Vector encDataRefs) {
+        for (int i = 0; i < encDataRefs.size(); i++) {
+            String dataReferenceUri = (String) encDataRefs.get(i);
+            Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":DataReference");
+            dataReference.setAttributeNS(null, "URI", dataReferenceUri);
+            referenceList.appendChild(dataReference);
+        }
+        return referenceList;
+    }
+
+    /**
+     * @return The symmetric key
+     */
+    public SecretKey getSymmetricKey() {
+        return symmetricKey;
+    }
+
+    /**
+     * Set the symmetric key to be used for encryption
+     * 
+     * @param key
+     */
+    public void setSymmetricKey(SecretKey key) {
+        this.symmetricKey = key;
+    }
+
+    /**
+     * @return Return the SecurityTokenRefernce
+     */
+    public SecurityTokenReference getSecurityTokenReference() {
+        return securityTokenReference;
+    }
+
+    /**
+     * @param reference
+     */
+    public void setSecurityTokenReference(SecurityTokenReference reference) {
+        securityTokenReference = reference;
+    }
+
+    public boolean isEncryptSymmKey() {
+        return encryptSymmKey;
+    }
+
+    public void setEncryptSymmKey(boolean encryptSymmKey) {
+        this.encryptSymmKey = encryptSymmKey;
+    }
+
+    private String getSHA1(byte[] input) throws WSSecurityException {
+        try {
+            MessageDigest sha = null;
+            sha = MessageDigest.getInstance("SHA-1");
+            sha.reset();
+            sha.update(input);
+            byte[] data = sha.digest();
+            
+            return Base64.encode(data);
+        } catch (NoSuchAlgorithmException e) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
+        }
+    }
+
+    public void setCustomReferenceValue(String customReferenceValue) {
+        this.customReferenceValue = customReferenceValue;
+    }
+    
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: wss4j-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: wss4j-dev-help@ws.apache.org