You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by gi...@apache.org on 2011/10/11 20:03:15 UTC

svn commit: r1181995 [8/26] - in /webservices/wss4j/branches/swssf: ./ cxf-integration/ cxf-integration/src/main/java/org/swssf/cxfIntegration/ cxf-integration/src/main/java/org/swssf/cxfIntegration/interceptor/ cxf-integration/src/main/java/org/swssf/...

Modified: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/DerivedKeyTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/DerivedKeyTokenOutputProcessor.java?rev=1181995&r1=1179730&r2=1181995&view=diff
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/DerivedKeyTokenOutputProcessor.java (original)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/DerivedKeyTokenOutputProcessor.java Tue Oct 11 18:03:00 2011
@@ -16,16 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.swssf.impl.processor.output;
+package org.swssf.wss.impl.processor.output;
 
 import org.apache.commons.codec.binary.Base64;
-import org.swssf.config.JCEAlgorithmMapper;
-import org.swssf.crypto.Crypto;
-import org.swssf.ext.*;
-import org.swssf.impl.derivedKey.AlgoFactory;
-import org.swssf.impl.derivedKey.ConversationException;
-import org.swssf.impl.derivedKey.DerivationAlgorithm;
-import org.swssf.impl.securityToken.ProcessorInfoSecurityToken;
+import org.swssf.wss.ext.*;
+import org.swssf.wss.impl.derivedKey.AlgoFactory;
+import org.swssf.wss.impl.derivedKey.ConversationException;
+import org.swssf.wss.impl.derivedKey.DerivationAlgorithm;
+import org.swssf.wss.impl.securityToken.ProcessorInfoSecurityToken;
+import org.swssf.xmlsec.config.JCEAlgorithmMapper;
+import org.swssf.xmlsec.crypto.Crypto;
+import org.swssf.xmlsec.crypto.Merlin;
+import org.swssf.xmlsec.ext.*;
 
 import javax.crypto.spec.SecretKeySpec;
 import javax.xml.namespace.QName;
@@ -33,13 +35,12 @@ import javax.xml.stream.XMLStreamExcepti
 import javax.xml.stream.events.StartElement;
 import javax.xml.stream.events.XMLEvent;
 import java.io.UnsupportedEncodingException;
-import java.security.Key;
-import java.security.PublicKey;
+import java.security.*;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.UUID;
+import java.util.*;
 
 /**
  * @author $Author$
@@ -47,15 +48,15 @@ import java.util.UUID;
  */
 public class DerivedKeyTokenOutputProcessor extends AbstractOutputProcessor {
 
-    public DerivedKeyTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+    public DerivedKeyTokenOutputProcessor(WSSSecurityProperties securityProperties, XMLSecurityConstants.Action action) throws XMLSecurityException {
         super(securityProperties, action);
     }
 
     @Override
-    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
         try {
 
-            String tokenId = outputProcessorChain.getSecurityContext().get(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY);
+            String tokenId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY);
             if (tokenId == null) {
                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
             }
@@ -72,24 +73,23 @@ public class DerivedKeyTokenOutputProces
 
             int offset = 0;
             int length = 0;
-            switch (getAction()) {
-                case SIGNATURE_WITH_DERIVED_KEY:
-                    length = JCEAlgorithmMapper.getAlgorithmMapping(getSecurityProperties().getSignatureAlgorithm()).getKeyLength() / 8;
-                    break;
-                case ENCRYPT_WITH_DERIVED_KEY:
-                    length = JCEAlgorithmMapper.getAlgorithmMapping(getSecurityProperties().getEncryptionSymAlgorithm()).getKeyLength() / 8;
-                    break;
+
+            XMLSecurityConstants.Action action = getAction();
+            if (action.equals(WSSConstants.SIGNATURE_WITH_DERIVED_KEY)) {
+                length = JCEAlgorithmMapper.getAlgorithmMapping(getSecurityProperties().getSignatureAlgorithm()).getKeyLength() / 8;
+            } else if (action.equals(WSSConstants.ENCRYPT_WITH_DERIVED_KEY)) {
+                length = JCEAlgorithmMapper.getAlgorithmMapping(getSecurityProperties().getEncryptionSymAlgorithm()).getKeyLength() / 8;
             }
 
             byte[] label;
             try {
-                label = (Constants.WS_SecureConversation_DEFAULT_LABEL + Constants.WS_SecureConversation_DEFAULT_LABEL).getBytes("UTF-8");
+                label = (WSSConstants.WS_SecureConversation_DEFAULT_LABEL + WSSConstants.WS_SecureConversation_DEFAULT_LABEL).getBytes("UTF-8");
             } catch (UnsupportedEncodingException e) {
                 throw new WSSecurityException("UTF-8 encoding is not supported", e);
             }
 
             byte[] nonce = new byte[16];
-            Constants.secureRandom.nextBytes(nonce);
+            WSSConstants.secureRandom.nextBytes(nonce);
 
             byte[] seed = new byte[label.length + nonce.length];
             System.arraycopy(label, 0, seed, 0, label.length);
@@ -97,7 +97,7 @@ public class DerivedKeyTokenOutputProces
 
             DerivationAlgorithm derivationAlgorithm;
             try {
-                derivationAlgorithm = AlgoFactory.getInstance(Constants.P_SHA_1);
+                derivationAlgorithm = AlgoFactory.getInstance(WSSConstants.P_SHA_1);
             } catch (ConversationException e) {
                 throw new WSSecurityException(e.getMessage(), e);
             }
@@ -105,9 +105,9 @@ public class DerivedKeyTokenOutputProces
             final byte[] derivedKeyBytes;
             try {
                 byte[] secret;
-                if (wrappingSecurityToken.getTokenType() == Constants.TokenType.SecurityContextToken) {
+                if (wrappingSecurityToken.getTokenType() == WSSConstants.SecurityContextToken) {
                     WSPasswordCallback passwordCallback = new WSPasswordCallback(wsuIdDKT, WSPasswordCallback.Usage.SECRET_KEY);
-                    Utils.doSecretKeyCallback(securityProperties.getCallbackHandler(), passwordCallback, wsuIdDKT);
+                    WSSUtils.doSecretKeyCallback(securityProperties.getCallbackHandler(), passwordCallback, wsuIdDKT);
                     if (passwordCallback.getKey() == null) {
                         throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noKey", wsuIdDKT);
                     }
@@ -142,7 +142,7 @@ public class DerivedKeyTokenOutputProces
                     return false;
                 }
 
-                public Key getSecretKey(String algorithmURI, Constants.KeyUsage keyUsage) throws WSSecurityException {
+                public Key getSecretKey(String algorithmURI, XMLSecurityConstants.KeyUsage keyUsage) throws WSSecurityException {
                     if (keyTable.containsKey(algorithmURI)) {
                         return keyTable.get(algorithmURI);
                     } else {
@@ -153,7 +153,7 @@ public class DerivedKeyTokenOutputProces
                     }
                 }
 
-                public PublicKey getPublicKey(Constants.KeyUsage keyUsage) throws WSSecurityException {
+                public PublicKey getPublicKey(XMLSecurityConstants.KeyUsage keyUsage) throws WSSecurityException {
                     return null;
                 }
 
@@ -172,7 +172,7 @@ public class DerivedKeyTokenOutputProces
                     return null;
                 }
 
-                public Constants.TokenType getTokenType() {
+                public WSSConstants.TokenType getTokenType() {
                     return null;
                 }
             };
@@ -187,17 +187,17 @@ public class DerivedKeyTokenOutputProces
                 }
             };
 
-            switch (getAction()) {
-                case SIGNATURE_WITH_DERIVED_KEY:
-                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, wsuIdDKT);
-                    outputProcessorChain.getSecurityContext().put(Constants.PROP_APPEND_SIGNATURE_ON_THIS_ID, wsuIdDKT);
-                    break;
-                case ENCRYPT_WITH_DERIVED_KEY:
-                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, wsuIdDKT);
-                    break;
+            if (action.equals(WSSConstants.SIGNATURE_WITH_DERIVED_KEY)) {
+                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, wsuIdDKT);
+                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_APPEND_SIGNATURE_ON_THIS_ID, wsuIdDKT);
+            } else if (action.equals(WSSConstants.ENCRYPT_WITH_DERIVED_KEY)) {
+                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, wsuIdDKT);
             }
             outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(wsuIdDKT, derivedKeysecurityTokenProvider);
-            FinalDerivedKeyTokenOutputProcessor finalDerivedKeyTokenOutputProcessor = new FinalDerivedKeyTokenOutputProcessor(getSecurityProperties(), getAction(), derivedKeySecurityToken, offset, length, new String(Base64.encodeBase64(nonce)));
+            FinalDerivedKeyTokenOutputProcessor finalDerivedKeyTokenOutputProcessor =
+                    new FinalDerivedKeyTokenOutputProcessor(
+                            getSecurityProperties(), getAction(), derivedKeySecurityToken,
+                            offset, length, new String(Base64.encodeBase64(nonce)));
             finalDerivedKeyTokenOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
             derivedKeySecurityToken.setProcessor(finalDerivedKeyTokenOutputProcessor);
             outputProcessorChain.addProcessor(finalDerivedKeyTokenOutputProcessor);
@@ -214,7 +214,10 @@ public class DerivedKeyTokenOutputProces
         private int length;
         private String nonce;
 
-        FinalDerivedKeyTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken, int offset, int length, String nonce) throws WSSecurityException {
+        FinalDerivedKeyTokenOutputProcessor(XMLSecurityProperties securityProperties, XMLSecurityConstants.Action action,
+                                            SecurityToken securityToken, int offset, int length, String nonce)
+                throws XMLSecurityException {
+
             super(securityProperties, action);
             this.securityToken = securityToken;
             this.offset = offset;
@@ -223,32 +226,187 @@ public class DerivedKeyTokenOutputProces
         }
 
         @Override
-        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
             outputProcessorChain.processEvent(xmlEvent);
             if (xmlEvent.isStartElement()) {
                 StartElement startElement = xmlEvent.asStartElement();
-                if (outputProcessorChain.getDocumentContext().isInSecurityHeader() && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+                if (((WSSDocumentContext) outputProcessorChain.getDocumentContext()).isInSecurityHeader() && startElement.getName().equals(WSSConstants.TAG_wsse_Security)) {
                     OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
 
                     Map<QName, String> attributes = new HashMap<QName, String>();
-                    attributes.put(Constants.ATT_wsu_Id, securityToken.getId());
-                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_DerivedKeyToken, attributes);
+                    attributes.put(WSSConstants.ATT_wsu_Id, securityToken.getId());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsc0502_DerivedKeyToken, attributes);
 
-                    createSecurityTokenReferenceStructureForDerivedKey(subOutputProcessorChain, securityToken, getSecurityProperties().getDerivedKeyKeyIdentifierType(), getSecurityProperties().getDerivedKeyTokenReference(), getSecurityProperties().isUseSingleCert());
-                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Offset, null);
+                    createSecurityTokenReferenceStructureForDerivedKey(subOutputProcessorChain, securityToken,
+                            ((WSSSecurityProperties) getSecurityProperties()).getDerivedKeyKeyIdentifierType(),
+                            ((WSSSecurityProperties) getSecurityProperties()).getDerivedKeyTokenReference(), getSecurityProperties().isUseSingleCert());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsc0502_Offset, null);
                     createCharactersAndOutputAsEvent(subOutputProcessorChain, "" + offset);
-                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Offset);
-                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Length, null);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsc0502_Offset);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsc0502_Length, null);
                     createCharactersAndOutputAsEvent(subOutputProcessorChain, "" + length);
-                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Length);
-                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Nonce, null);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsc0502_Length);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsc0502_Nonce, null);
                     createCharactersAndOutputAsEvent(subOutputProcessorChain, nonce);
-                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Nonce);
-                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_DerivedKeyToken);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsc0502_Nonce);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_wsc0502_DerivedKeyToken);
 
                     outputProcessorChain.removeProcessor(this);
                 }
             }
         }
+
+        protected void createSecurityTokenReferenceStructureForDerivedKey(
+                OutputProcessorChain outputProcessorChain,
+                SecurityToken securityToken,
+                WSSConstants.KeyIdentifierType keyIdentifierType,
+                WSSConstants.DerivedKeyTokenReference derivedKeyTokenReference,
+                boolean useSingleCertificate)
+                throws XMLStreamException, XMLSecurityException {
+
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_wsu_Id, "STRId-" + UUID.randomUUID().toString());
+            if ((keyIdentifierType == WSSConstants.KeyIdentifierType.BST_DIRECT_REFERENCE
+                    || keyIdentifierType == WSSConstants.KeyIdentifierType.BST_EMBEDDED)
+                    && !useSingleCertificate) {
+                attributes.put(WSSConstants.ATT_wsse11_TokenType, WSSConstants.NS_X509PKIPathv1);
+            } else if (derivedKeyTokenReference == WSSConstants.DerivedKeyTokenReference.EncryptedKey) {
+                attributes.put(WSSConstants.ATT_wsse11_TokenType, WSSConstants.NS_WSS_ENC_KEY_VALUE_TYPE);
+            }
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_SecurityTokenReference, attributes);
+
+            X509Certificate[] x509Certificates = securityToken.getKeyWrappingToken().getX509Certificates();
+            String tokenId = securityToken.getKeyWrappingToken().getId();
+
+            if (keyIdentifierType == WSSConstants.KeyIdentifierType.ISSUER_SERIAL) {
+                createX509IssuerSerialStructure(outputProcessorChain, x509Certificates);
+            } else if (keyIdentifierType == WSSConstants.KeyIdentifierType.SKI_KEY_IDENTIFIER) {
+                createX509SubjectKeyIdentifierStructure(outputProcessorChain, x509Certificates);
+            } else if (keyIdentifierType == WSSConstants.KeyIdentifierType.X509_KEY_IDENTIFIER) {
+                createX509KeyIdentifierStructure(outputProcessorChain, x509Certificates);
+            } else if (keyIdentifierType == WSSConstants.KeyIdentifierType.THUMBPRINT_IDENTIFIER) {
+                createThumbprintKeyIdentifierStructure(outputProcessorChain, x509Certificates);
+            } else if (keyIdentifierType == WSSConstants.KeyIdentifierType.BST_EMBEDDED) {
+                createBSTReferenceStructure(outputProcessorChain, tokenId, x509Certificates, useSingleCertificate, true);
+            } else if (keyIdentifierType == WSSConstants.KeyIdentifierType.BST_DIRECT_REFERENCE) {
+                createBSTReferenceStructure(outputProcessorChain, tokenId, x509Certificates, useSingleCertificate, false);
+            } else if (keyIdentifierType == WSSConstants.KeyIdentifierType.EMBEDDED_SECURITY_TOKEN_REF) {
+                createEmbeddedSecurityTokenReferenceStructure(outputProcessorChain, tokenId);
+            } else {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_ENCRYPTION, "unsupportedSecurityToken", keyIdentifierType.name());
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_SecurityTokenReference);
+        }
+
+        //todo common method
+        protected void createX509SubjectKeyIdentifierStructure(OutputProcessorChain outputProcessorChain, X509Certificate[] x509Certificates) throws XMLSecurityException, XMLStreamException {
+            // As per the 1.1 specification, SKI can only be used for a V3 certificate
+            if (x509Certificates[0].getVersion() != 3) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, "invalidCertForSKI");
+            }
+
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_NULL_EncodingType, WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, WSSConstants.NS_X509SubjectKeyIdentifier);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier, attributes);
+            byte data[] = new Merlin().getSKIBytesFromCert(x509Certificates[0]);
+            createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(data));
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier);
+        }
+
+        //todo common method
+        protected void createX509KeyIdentifierStructure(OutputProcessorChain outputProcessorChain, X509Certificate[] x509Certificates) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_NULL_EncodingType, WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, WSSConstants.NS_X509_V3_TYPE);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier, attributes);
+            try {
+                createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(x509Certificates[0].getEncoded()));
+            } catch (CertificateEncodingException e) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier);
+        }
+
+        //todo common methdod
+        protected void createThumbprintKeyIdentifierStructure(OutputProcessorChain outputProcessorChain, X509Certificate[] x509Certificates) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_NULL_EncodingType, WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, WSSConstants.NS_THUMBPRINT);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier, attributes);
+            try {
+                MessageDigest sha;
+                sha = MessageDigest.getInstance("SHA-1");
+                sha.reset();
+                sha.update(x509Certificates[0].getEncoded());
+                byte[] data = sha.digest();
+
+                createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(data));
+            } catch (CertificateEncodingException e) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+            } catch (NoSuchAlgorithmException e) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier);
+        }
+
+        //todo common method
+        protected void createBSTReferenceStructure(OutputProcessorChain outputProcessorChain, String referenceId, X509Certificate[] x509Certificates, boolean useSingleCertificate, boolean embed) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            String valueType;
+            if (useSingleCertificate) {
+                valueType = WSSConstants.NS_X509_V3_TYPE;
+            } else {
+                valueType = WSSConstants.NS_X509PKIPathv1;
+            }
+            attributes.put(WSSConstants.ATT_NULL_URI, "#" + referenceId);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, valueType);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference, attributes);
+            if (embed) {
+                createBinarySecurityTokenStructure(outputProcessorChain, referenceId, x509Certificates, useSingleCertificate);
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference);
+        }
+
+        //todo common method
+        protected void createEmbeddedSecurityTokenReferenceStructure(OutputProcessorChain outputProcessorChain, String referenceId) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_NULL_URI, "#" + referenceId);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference, attributes);
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference);
+        }
+
+        //todo common method
+        protected void createBinarySecurityTokenStructure(OutputProcessorChain outputProcessorChain, String referenceId, X509Certificate[] x509Certificates, boolean useSingleCertificate) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            String valueType;
+            if (useSingleCertificate) {
+                valueType = WSSConstants.NS_X509_V3_TYPE;
+            } else {
+                valueType = WSSConstants.NS_X509PKIPathv1;
+            }
+            attributes.put(WSSConstants.ATT_NULL_EncodingType, WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, valueType);
+            attributes.put(WSSConstants.ATT_wsu_Id, referenceId);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_BinarySecurityToken, attributes);
+            try {
+                if (useSingleCertificate) {
+                    createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(x509Certificates[0].getEncoded()));
+                } else {
+                    try {
+                        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC");
+                        List<X509Certificate> certificates = Arrays.asList(x509Certificates);
+                        createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(certificateFactory.generateCertPath(certificates).getEncoded()));
+                    } catch (CertificateException e) {
+                        throw new XMLSecurityException(XMLSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, e);
+                    } catch (NoSuchProviderException e) {
+                        throw new XMLSecurityException(XMLSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, e);
+                    }
+                }
+            } catch (CertificateEncodingException e) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_BinarySecurityToken);
+        }
     }
 }

Modified: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptEndingOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptEndingOutputProcessor.java?rev=1181995&r1=1179730&r2=1181995&view=diff
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptEndingOutputProcessor.java (original)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptEndingOutputProcessor.java Tue Oct 11 18:03:00 2011
@@ -16,11 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.swssf.impl.processor.output;
+package org.swssf.wss.impl.processor.output;
 
-import org.swssf.ext.*;
+import org.swssf.wss.ext.WSSConstants;
+import org.swssf.wss.ext.WSSDocumentContext;
+import org.swssf.wss.ext.WSSSecurityProperties;
+import org.swssf.wss.ext.WSSUtils;
+import org.swssf.xmlsec.ext.OutputProcessorChain;
+import org.swssf.xmlsec.ext.XMLSecurityConstants;
+import org.swssf.xmlsec.ext.XMLSecurityException;
+import org.swssf.xmlsec.impl.processor.output.AbstractEncryptEndingOutputProcessor;
 
+import javax.xml.namespace.QName;
 import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.util.Iterator;
 
 /**
  * Processor buffers encrypted XMLEvents and forwards them when final is called
@@ -28,19 +41,128 @@ import javax.xml.stream.XMLStreamExcepti
  * @author $Author$
  * @version $Revision$ $Date$
  */
-public class EncryptEndingOutputProcessor extends AbstractBufferingOutputProcessor {
+public class EncryptEndingOutputProcessor extends AbstractEncryptEndingOutputProcessor {
 
-    public EncryptEndingOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+    public EncryptEndingOutputProcessor(WSSSecurityProperties securityProperties, XMLSecurityConstants.Action action) throws XMLSecurityException {
         super(securityProperties, action);
         this.getAfterProcessors().add(EncryptOutputProcessor.class.getName());
         this.getAfterProcessors().add(UsernameTokenOutputProcessor.class.getName());
     }
 
     @Override
-    protected void processHeaderEvent(OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+    protected void processHeaderEvent(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
         OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
-        if (getAction() == Constants.Action.ENCRYPT_WITH_DERIVED_KEY) {
+        if (getAction() == WSSConstants.ENCRYPT_WITH_DERIVED_KEY) {
             createReferenceListStructure(subOutputProcessorChain);
         }
     }
+
+    @Override
+    public void doFinal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
+
+        //todo replace this and in EncryptEndingOutputProcessor with a common method somewhere
+        OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+
+        //loop until we reach our security header and set flag
+        Iterator<XMLEvent> xmlEventIterator = getXmlEventBuffer().descendingIterator();
+        while (xmlEventIterator.hasNext()) {
+            XMLEvent xmlEvent = xmlEventIterator.next();
+            if (xmlEvent.isStartElement()) {
+                StartElement startElement = xmlEvent.asStartElement();
+                if (startElement.getName().equals(WSSConstants.TAG_wsse_Security)
+                        && WSSUtils.isResponsibleActorOrRole(
+                        startElement,
+                        ((WSSDocumentContext) subOutputProcessorChain.getDocumentContext()).getSOAPMessageVersionNamespace(),
+                        ((WSSSecurityProperties) getSecurityProperties()).getActor())) {
+                    ((WSSDocumentContext) subOutputProcessorChain.getDocumentContext()).setInSecurityHeader(true);
+                    subOutputProcessorChain.reset();
+                    subOutputProcessorChain.processEvent(xmlEvent);
+                    break;
+                }
+            }
+            subOutputProcessorChain.reset();
+            subOutputProcessorChain.processEvent(xmlEvent);
+        }
+
+        //append current header
+        if (getAppendAfterThisTokenId() == null) {
+            processHeaderEvent(subOutputProcessorChain);
+        } else {
+            //we have a dependent token. so we have to append the current header after the token
+            boolean found = false;
+            while (xmlEventIterator.hasNext() && !found) {
+                XMLEvent xmlEvent = xmlEventIterator.next();
+
+                subOutputProcessorChain.reset();
+                subOutputProcessorChain.processEvent(xmlEvent);
+
+                //search for an element with a matching wsu:Id. this is our token
+                if (xmlEvent.isStartElement()) {
+                    StartElement startElement = xmlEvent.asStartElement();
+                    QName matchingElementName;
+
+                    @SuppressWarnings("unchecked")
+                    Iterator<Attribute> attributeIterator = startElement.getAttributes();
+                    while (attributeIterator.hasNext() && !found) {
+                        Attribute attribute = attributeIterator.next();
+                        final QName attributeName = attribute.getName();
+                        final String attributeValue = attribute.getValue();
+                        if ((WSSConstants.ATT_wsu_Id.equals(attributeName) && getAppendAfterThisTokenId().equals(attributeValue))
+                                || (WSSConstants.ATT_NULL_Id.equals(attributeName) && getAppendAfterThisTokenId().equals(attributeValue))
+                                || (WSSConstants.ATT_NULL_AssertionID.equals(attributeName) && getAppendAfterThisTokenId().equals(attributeValue))
+                                || (WSSConstants.ATT_NULL_ID.equals(attributeName) && getAppendAfterThisTokenId().endsWith(attributeValue))) {
+                            matchingElementName = startElement.getName();
+                            //we found the token and...
+                            int level = 0;
+                            while (xmlEventIterator.hasNext() && !found) {
+                                xmlEvent = xmlEventIterator.next();
+
+                                subOutputProcessorChain.reset();
+                                subOutputProcessorChain.processEvent(xmlEvent);
+
+                                //loop until we reach the token end element
+                                if (xmlEvent.isEndElement()) {
+                                    EndElement endElement = xmlEvent.asEndElement();
+                                    if (level == 0 && endElement.getName().equals(matchingElementName)) {
+                                        found = true;
+                                        //output now the current header
+                                        processHeaderEvent(subOutputProcessorChain);
+                                    }
+                                    level--;
+                                } else if (xmlEvent.isStartElement()) {
+                                    level++;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        //loop until our security header end element and unset the flag
+        while (xmlEventIterator.hasNext()) {
+            XMLEvent xmlEvent = xmlEventIterator.next();
+            if (xmlEvent.isEndElement()) {
+                EndElement endElement = xmlEvent.asEndElement();
+                if (endElement.getName().equals(WSSConstants.TAG_wsse_Security)) {
+                    ((WSSDocumentContext) subOutputProcessorChain.getDocumentContext()).setInSecurityHeader(false);
+                    subOutputProcessorChain.reset();
+                    subOutputProcessorChain.processEvent(xmlEvent);
+                    break;
+                }
+            }
+            subOutputProcessorChain.reset();
+            subOutputProcessorChain.processEvent(xmlEvent);
+        }
+        //loop throug the rest of the document
+        while (xmlEventIterator.hasNext()) {
+            XMLEvent xmlEvent = xmlEventIterator.next();
+            subOutputProcessorChain.reset();
+            subOutputProcessorChain.processEvent(xmlEvent);
+        }
+        subOutputProcessorChain.reset();
+        //call final on the rest of the chain
+        subOutputProcessorChain.doFinal();
+        //this processor is now finished and we can remove it now
+        subOutputProcessorChain.removeProcessor(this);
+    }
 }

Modified: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptOutputProcessor.java?rev=1181995&r1=1179730&r2=1181995&view=diff
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptOutputProcessor.java (original)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptOutputProcessor.java Tue Oct 11 18:03:00 2011
@@ -16,29 +16,28 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.swssf.impl.processor.output;
+package org.swssf.wss.impl.processor.output;
 
-import org.apache.commons.codec.binary.Base64OutputStream;
-import org.swssf.config.JCEAlgorithmMapper;
-import org.swssf.ext.*;
-import org.swssf.impl.EncryptionPartDef;
-import org.swssf.impl.util.TrimmerOutputStream;
+import org.swssf.wss.ext.WSSConstants;
+import org.swssf.wss.ext.WSSDocumentContext;
+import org.swssf.wss.ext.WSSSecurityProperties;
+import org.swssf.xmlsec.ext.*;
+import org.swssf.xmlsec.impl.EncryptionPartDef;
+import org.swssf.xmlsec.impl.processor.output.AbstractEncryptOutputProcessor;
 
-import javax.crypto.Cipher;
-import javax.crypto.CipherOutputStream;
 import javax.crypto.NoSuchPaddingException;
 import javax.xml.namespace.QName;
-import javax.xml.stream.XMLEventFactory;
-import javax.xml.stream.XMLEventWriter;
-import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.*;
-import java.io.BufferedOutputStream;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
 import java.io.IOException;
-import java.io.OutputStream;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.UUID;
 
 /**
  * Processor to encrypt XML structures
@@ -46,66 +45,53 @@ import java.util.*;
  * @author $Author$
  * @version $Revision$ $Date$
  */
-public class EncryptOutputProcessor extends AbstractOutputProcessor {
+public class EncryptOutputProcessor extends AbstractEncryptOutputProcessor {
 
-    private List<SecurePart> secureParts;
-    private InternalEncryptionOutputProcessor activeInternalEncryptionOutputProcessor = null;
-
-    public EncryptOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+    public EncryptOutputProcessor(WSSSecurityProperties securityProperties, XMLSecurityConstants.Action action) throws XMLSecurityException {
         super(securityProperties, action);
-        secureParts = securityProperties.getEncryptionSecureParts();
     }
 
     @Override
-    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
 
         if (xmlEvent.isStartElement()) {
             StartElement startElement = xmlEvent.asStartElement();
 
             //avoid double encryption when child elements matches too
-            if (activeInternalEncryptionOutputProcessor == null) {
-                //find an element which matches a user configured securePart
-                Iterator<SecurePart> securePartIterator = secureParts.iterator();
-                while (securePartIterator.hasNext()) {
-                    SecurePart securePart = securePartIterator.next();
-                    if (securePart.getIdToSign() == null) {
-                        if (startElement.getName().getLocalPart().equals(securePart.getName())
-                                && startElement.getName().getNamespaceURI().equals(securePart.getNamespace())) {
-
-                            logger.debug("Matched securePart for encryption");
-                            InternalEncryptionOutputProcessor internalEncryptionOutputProcessor = null;
-                            try {
-                                String tokenId = outputProcessorChain.getSecurityContext().get(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION);
-                                SecurityTokenProvider securityTokenProvider = outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
-                                EncryptionPartDef encryptionPartDef = new EncryptionPartDef();
-                                encryptionPartDef.setModifier(securePart.getModifier());
-                                encryptionPartDef.setEncRefId("ED-" + UUID.randomUUID().toString());
-                                encryptionPartDef.setKeyId(securityTokenProvider.getId());
-                                encryptionPartDef.setSymmetricKey(securityTokenProvider.getSecurityToken(null).getSecretKey(getSecurityProperties().getEncryptionSymAlgorithm(), null));
-                                outputProcessorChain.getSecurityContext().putAsList(EncryptionPartDef.class, encryptionPartDef);
-                                internalEncryptionOutputProcessor =
-                                        new InternalEncryptionOutputProcessor(
-                                                getSecurityProperties(),
-                                                getAction(),
-                                                encryptionPartDef,
-                                                startElement,
-                                                outputProcessorChain.getDocumentContext().getEncoding()
-                                        );
-                            } catch (NoSuchAlgorithmException e) {
-                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
-                            } catch (NoSuchPaddingException e) {
-                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
-                            } catch (InvalidKeyException e) {
-                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
-                            } catch (IOException e) {
-                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
-                            }
-
-                            activeInternalEncryptionOutputProcessor = internalEncryptionOutputProcessor;
-                            outputProcessorChain.addProcessor(internalEncryptionOutputProcessor);
-                            break;
-                        }
+            if (getActiveInternalEncryptionOutputProcessor() == null) {
+                SecurePart securePart = securePartMatches(startElement, outputProcessorChain);
+                if (securePart != null) {
+                    logger.debug("Matched securePart for encryption");
+                    InternalEncryptionOutputProcessor internalEncryptionOutputProcessor = null;
+                    try {
+                        String tokenId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION);
+                        SecurityTokenProvider securityTokenProvider = outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
+                        EncryptionPartDef encryptionPartDef = new EncryptionPartDef();
+                        encryptionPartDef.setModifier(securePart.getModifier());
+                        encryptionPartDef.setEncRefId("ED-" + UUID.randomUUID().toString());
+                        encryptionPartDef.setKeyId(securityTokenProvider.getId());
+                        encryptionPartDef.setSymmetricKey(securityTokenProvider.getSecurityToken(null).getSecretKey(getSecurityProperties().getEncryptionSymAlgorithm(), null));
+                        outputProcessorChain.getSecurityContext().putAsList(EncryptionPartDef.class, encryptionPartDef);
+                        internalEncryptionOutputProcessor =
+                                new InternalEncryptionOutputProcessor(
+                                        ((WSSSecurityProperties) getSecurityProperties()),
+                                        getAction(),
+                                        encryptionPartDef,
+                                        startElement,
+                                        outputProcessorChain.getDocumentContext().getEncoding()
+                                );
+                    } catch (NoSuchAlgorithmException e) {
+                        throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                    } catch (NoSuchPaddingException e) {
+                        throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                    } catch (InvalidKeyException e) {
+                        throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                    } catch (IOException e) {
+                        throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
                     }
+
+                    setActiveInternalEncryptionOutputProcessor(internalEncryptionOutputProcessor);
+                    outputProcessorChain.addProcessor(internalEncryptionOutputProcessor);
                 }
             }
         }
@@ -116,168 +102,61 @@ public class EncryptOutputProcessor exte
     /**
      * Processor which handles the effective enryption of the data
      */
-    class InternalEncryptionOutputProcessor extends AbstractOutputProcessor {
-
-        private EncryptionPartDef encryptionPartDef;
-        private CharacterEventGeneratorOutputStream characterEventGeneratorOutputStream;
-        private XMLEventWriter xmlEventWriter;
-        private OutputStream cipherOutputStream;
+    class InternalEncryptionOutputProcessor extends AbstractInternalEncryptionOutputProcessor {
 
-        private StartElement startElement;
-        private int elementCounter = 0;
         private boolean doEncryptedHeader = false;
-        private OutputProcessorChain subOutputProcessorChain;
 
-        InternalEncryptionOutputProcessor(SecurityProperties securityProperties, Constants.Action action, EncryptionPartDef encryptionPartDef,
+        InternalEncryptionOutputProcessor(WSSSecurityProperties securityProperties, XMLSecurityConstants.Action action, EncryptionPartDef encryptionPartDef,
                                           StartElement startElement, String encoding)
                 throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, XMLStreamException {
 
-            super(securityProperties, action);
-            this.getBeforeProcessors().add(EncryptEndingOutputProcessor.class.getName());
+            super(securityProperties, action, encryptionPartDef, startElement, encoding);
+            this.getBeforeProcessors().add(org.swssf.wss.impl.processor.output.EncryptEndingOutputProcessor.class.getName());
             this.getBeforeProcessors().add(InternalEncryptionOutputProcessor.class.getName());
             this.getAfterProcessors().add(EncryptOutputProcessor.class.getName());
-            this.encryptionPartDef = encryptionPartDef;
-            this.startElement = startElement;
-
-            //initialize the cipher
-            String jceAlgorithm = JCEAlgorithmMapper.translateURItoJCEID(securityProperties.getEncryptionSymAlgorithm());
-            Cipher symmetricCipher = Cipher.getInstance(jceAlgorithm);
-
-            //Should internally generate an IV
-            symmetricCipher.init(Cipher.ENCRYPT_MODE, encryptionPartDef.getSymmetricKey());
-            byte[] iv = symmetricCipher.getIV();
-
-            characterEventGeneratorOutputStream = new CharacterEventGeneratorOutputStream(encoding);
-            //Base64EncoderStream calls write every 78byte (line breaks). So we have to buffer again to get optimal performance
-            Base64OutputStream base64EncoderStream = new Base64OutputStream(new BufferedOutputStream(characterEventGeneratorOutputStream), true, 76, new byte[]{'\n'});
-            base64EncoderStream.write(iv);
-
-            //the trimmer output stream is needed to strip away the dummy wrapping element which must be added 
-            cipherOutputStream = new TrimmerOutputStream(new CipherOutputStream(base64EncoderStream, symmetricCipher), 8192, 3, 4);
-
-            //we create a new StAX writer for optimized namespace writing.
-            XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
-            xmlOutputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
-            //spec says (4.2): "The cleartext octet sequence obtained in step 3 is interpreted as UTF-8 encoded character data."
-            xmlEventWriter = xmlOutputFactory.createXMLEventWriter(cipherOutputStream, "UTF-8");
-            //we have to output a fake element to workaround text-only encryption:
-            xmlEventWriter.add(XMLEventFactory.newFactory().createStartElement(new QName("a"), null, null));
-        }
-
-        @Override
-        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
-
-            if (xmlEvent.isStartElement()) {
-
-                StartElement startElement = xmlEvent.asStartElement();
-
-                if (startElement.getName().equals(this.startElement.getName()) && elementCounter == 0) {
-                    //if the user selected element encryption we have to encrypt the current element-event...
-                    if (encryptionPartDef.getModifier() == SecurePart.Modifier.Element) {
-                        subOutputProcessorChain = outputProcessorChain.createSubChain(this);
-                        processEventInternal(subOutputProcessorChain);
-                        //encrypt the current element event
-                        encryptEvent(xmlEvent);
-
-                    } //...the user selected content encryption, so we let pass this event as usual  
-                    else if (encryptionPartDef.getModifier() == SecurePart.Modifier.Content) {
-                        outputProcessorChain.processEvent(xmlEvent);
-                        subOutputProcessorChain = outputProcessorChain.createSubChain(this);
-                        processEventInternal(subOutputProcessorChain);
-                    }
-                } else {
-                    encryptEvent(xmlEvent);
-                }
-
-                elementCounter++;
-
-            } else if (xmlEvent.isEndElement()) {
-                elementCounter--;
-
-                EndElement endElement = xmlEvent.asEndElement();
-
-                if (endElement.getName().equals(this.startElement.getName()) && elementCounter == 0) {
-                    if (encryptionPartDef.getModifier() == SecurePart.Modifier.Element) {
-                        encryptEvent(xmlEvent);
-                        doFinalInternal(subOutputProcessorChain);
-                    } else {
-                        doFinalInternal(subOutputProcessorChain);
-                        outputAsEvent(subOutputProcessorChain, xmlEvent);
-                    }
-                    subOutputProcessorChain.removeProcessor(this);
-                    subOutputProcessorChain = null;
-                    //from now on encryption is possible again
-                    activeInternalEncryptionOutputProcessor = null;
-
-                } else {
-                    encryptEvent(xmlEvent);
-                }
-            } else {
-                //not an interesting start nor an interesting end element
-                //so encrypt this
-                encryptEvent(xmlEvent);
-
-                //push all buffered encrypted character events through the chain
-                Iterator<Characters> charactersIterator = characterEventGeneratorOutputStream.getCharactersBuffer().iterator();
-                while (charactersIterator.hasNext()) {
-                    Characters characters = charactersIterator.next();
-                    outputAsEvent(subOutputProcessorChain, characters);
-                    charactersIterator.remove();
-                }
-            }
-        }
-
-        private void encryptEvent(XMLEvent xmlEvent) throws XMLStreamException {
-            xmlEventWriter.add(xmlEvent);
         }
 
         /**
          * Creates the Data structure around the cipher data
          */
-        private void processEventInternal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        protected void processEventInternal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
             Map<QName, String> attributes = null;
 
             //WSS 1.1 EncryptedHeader Element:
             if (outputProcessorChain.getDocumentContext().getDocumentLevel() == 3
-                    && outputProcessorChain.getDocumentContext().isInSOAPHeader()) {
+                    && ((WSSDocumentContext) outputProcessorChain.getDocumentContext()).isInSOAPHeader()) {
                 doEncryptedHeader = true;
 
                 attributes = new HashMap<QName, String>();
 
                 @SuppressWarnings("unchecked")
-                Iterator<Attribute> attributeIterator = this.startElement.getAttributes();
+                Iterator<Attribute> attributeIterator = getStartElement().getAttributes();
                 while (attributeIterator.hasNext()) {
                     Attribute attribute = attributeIterator.next();
                     if (!attribute.isNamespace() &&
-                            (Constants.NS_SOAP11.equals(attribute.getName().getNamespaceURI()) ||
-                                    Constants.NS_SOAP12.equals(attribute.getName().getNamespaceURI()))) {
+                            (WSSConstants.NS_SOAP11.equals(attribute.getName().getNamespaceURI()) ||
+                                    WSSConstants.NS_SOAP12.equals(attribute.getName().getNamespaceURI()))) {
                         attributes.put(attribute.getName(), attribute.getValue());
                     }
                 }
-                createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse11_EncryptedHeader, attributes);
+                createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse11_EncryptedHeader, attributes);
             }
 
             attributes = new HashMap<QName, String>();
-            attributes.put(Constants.ATT_NULL_Id, encryptionPartDef.getEncRefId());
-            attributes.put(Constants.ATT_NULL_Type, encryptionPartDef.getModifier().getModifier());
-            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptedData, attributes);
+            attributes.put(WSSConstants.ATT_NULL_Id, getEncryptionPartDef().getEncRefId());
+            attributes.put(WSSConstants.ATT_NULL_Type, getEncryptionPartDef().getModifier().getModifier());
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_xenc_EncryptedData, attributes);
 
             attributes = new HashMap<QName, String>();
-            attributes.put(Constants.ATT_NULL_Algorithm, securityProperties.getEncryptionSymAlgorithm());
-            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptionMethod, attributes);
-
-            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptionMethod);
-            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_dsig_KeyInfo, null);
-            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference, null);
+            attributes.put(WSSConstants.ATT_NULL_Algorithm, securityProperties.getEncryptionSymAlgorithm());
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_xenc_EncryptionMethod, attributes);
 
-            attributes = new HashMap<QName, String>();
-            attributes.put(Constants.ATT_NULL_URI, "#" + encryptionPartDef.getKeyId());
-            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_Reference, attributes);
-            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_Reference);
-            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference);
-            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_dsig_KeyInfo);
-            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherData, null);
-            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherValue, null);
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_xenc_EncryptionMethod);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_dsig_KeyInfo, null);
+            createKeyInfoStructure(outputProcessorChain);
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_dsig_KeyInfo);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_xenc_CipherData, null);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_xenc_CipherValue, null);
 
             /*
             <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EncDataId-1612925417"
@@ -299,65 +178,25 @@ public class EncryptOutputProcessor exte
              */
         }
 
-        private void doFinalInternal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        @Override
+        protected void createKeyInfoStructure(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes;
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_SecurityTokenReference, null);
 
-            try {
-                xmlEventWriter.add(XMLEventFactory.newFactory().createEndElement(new QName("a"), null));
-                //close the event writer to flush all outstanding events to the encrypt stream
-                xmlEventWriter.close();
-                //call close to force a cipher.doFinal()
-                cipherOutputStream.close();
-            } catch (IOException e) {
-                throw new XMLStreamException(e);
-            }
+            attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_NULL_URI, "#" + getEncryptionPartDef().getKeyId());
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference, attributes);
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference);
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_SecurityTokenReference);
+        }
 
-            //push all buffered encrypted character events through the chain
-            Iterator<Characters> charactersIterator = characterEventGeneratorOutputStream.getCharactersBuffer().iterator();
-            while (charactersIterator.hasNext()) {
-                Characters characters = charactersIterator.next();
-                outputAsEvent(outputProcessorChain, characters);
-                charactersIterator.remove();
-            }
+        protected void doFinalInternal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
 
-            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherValue);
-            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherData);
-            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptedData);
+            super.doFinalInternal(outputProcessorChain);
 
             if (doEncryptedHeader) {
-                createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse11_EncryptedHeader);
+                createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse11_EncryptedHeader);
             }
         }
     }
-
-    /**
-     * Creates Character-XMLEvents from the byte stream
-     */
-    class CharacterEventGeneratorOutputStream extends OutputStream {
-
-        private List<Characters> charactersBuffer = new Vector<Characters>();
-        private String encoding;
-
-        CharacterEventGeneratorOutputStream(String encoding) {
-            this.encoding = encoding;
-        }
-
-        public List<Characters> getCharactersBuffer() {
-            return charactersBuffer;
-        }
-
-        @Override
-        public void write(int b) throws IOException {
-            charactersBuffer.add(createCharacters(new String(new byte[]{((byte) b)}, encoding)).asCharacters());
-        }
-
-        @Override
-        public void write(byte[] b) throws IOException {
-            charactersBuffer.add(createCharacters(new String(b, encoding)).asCharacters());
-        }
-
-        @Override
-        public void write(byte[] b, int off, int len) throws IOException {
-            charactersBuffer.add(createCharacters(new String(b, off, len, encoding)).asCharacters());
-        }
-    }
 }

Modified: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptedKeyOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptedKeyOutputProcessor.java?rev=1181995&r1=1179730&r2=1181995&view=diff
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptedKeyOutputProcessor.java (original)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/wss/impl/processor/output/EncryptedKeyOutputProcessor.java Tue Oct 11 18:03:00 2011
@@ -16,27 +16,30 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.swssf.impl.processor.output;
+package org.swssf.wss.impl.processor.output;
 
 import org.apache.commons.codec.binary.Base64;
-import org.swssf.config.JCEAlgorithmMapper;
-import org.swssf.crypto.Crypto;
-import org.swssf.ext.*;
-import org.swssf.impl.securityToken.ProcessorInfoSecurityToken;
+import org.swssf.wss.ext.WSSConstants;
+import org.swssf.wss.ext.WSSDocumentContext;
+import org.swssf.wss.ext.WSSSecurityProperties;
+import org.swssf.wss.ext.WSSecurityException;
+import org.swssf.wss.impl.securityToken.ProcessorInfoSecurityToken;
+import org.swssf.xmlsec.config.JCEAlgorithmMapper;
+import org.swssf.xmlsec.crypto.Crypto;
+import org.swssf.xmlsec.crypto.Merlin;
+import org.swssf.xmlsec.ext.*;
 
 import javax.crypto.*;
 import javax.xml.namespace.QName;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.StartElement;
 import javax.xml.stream.events.XMLEvent;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.NoSuchAlgorithmException;
-import java.security.PublicKey;
+import java.security.*;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
+import java.util.*;
 
 /**
  * @author $Author$
@@ -44,15 +47,15 @@ import java.util.UUID;
  */
 public class EncryptedKeyOutputProcessor extends AbstractOutputProcessor {
 
-    public EncryptedKeyOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+    public EncryptedKeyOutputProcessor(XMLSecurityProperties securityProperties, XMLSecurityConstants.Action action) throws XMLSecurityException {
         super(securityProperties, action);
     }
 
     @Override
-    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
         try {
 
-            String tokenId = outputProcessorChain.getSecurityContext().get(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY);
+            String tokenId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY);
             if (tokenId == null) {
                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
             }
@@ -100,19 +103,19 @@ public class EncryptedKeyOutputProcessor
                     return false;
                 }
 
-                public Key getSecretKey(String algorithmURI, Constants.KeyUsage keyUsage) throws WSSecurityException {
+                public Key getSecretKey(String algorithmURI, XMLSecurityConstants.KeyUsage keyUsage) throws XMLSecurityException {
                     return symmetricKey;
                 }
 
-                public PublicKey getPublicKey(Constants.KeyUsage keyUsage) throws WSSecurityException {
+                public PublicKey getPublicKey(XMLSecurityConstants.KeyUsage keyUsage) throws XMLSecurityException {
                     return null;
                 }
 
-                public X509Certificate[] getX509Certificates() throws WSSecurityException {
+                public X509Certificate[] getX509Certificates() throws XMLSecurityException {
                     return null;
                 }
 
-                public void verify() throws WSSecurityException {
+                public void verify() throws XMLSecurityException {
                 }
 
                 public SecurityToken getKeyWrappingToken() {
@@ -123,13 +126,13 @@ public class EncryptedKeyOutputProcessor
                     return null;
                 }
 
-                public Constants.TokenType getTokenType() {
+                public WSSConstants.TokenType getTokenType() {
                     return null;
                 }
             };
 
             final SecurityTokenProvider encryptedKeySecurityTokenProvider = new SecurityTokenProvider() {
-                public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+                public SecurityToken getSecurityToken(Crypto crypto) throws XMLSecurityException {
                     return encryptedKeySecurityToken;
                 }
 
@@ -139,31 +142,28 @@ public class EncryptedKeyOutputProcessor
             };
 
             FinalEncryptedKeyOutputProcessor finalEncryptedKeyOutputProcessor = new FinalEncryptedKeyOutputProcessor(getSecurityProperties(), getAction(), encryptedKeySecurityToken);
-            switch (getAction()) {
-                case ENCRYPT:
-                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, ekId);
-                    if (wrappingSecurityToken.getProcessor() != null) {
-                        finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
-                    } else {
-                        finalEncryptedKeyOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
-                    }
-                    break;
-                case SIGNATURE_WITH_DERIVED_KEY:
-                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
-                    if (wrappingSecurityToken.getProcessor() != null) {
-                        finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
-                    } else {
-                        finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(SignatureOutputProcessor.class.getName());
-                    }
-                    break;
-                case ENCRYPT_WITH_DERIVED_KEY:
-                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
-                    if (wrappingSecurityToken.getProcessor() != null) {
-                        finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
-                    } else {
-                        finalEncryptedKeyOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
-                    }
-                    break;
+            XMLSecurityConstants.Action action = getAction();
+            if (action.equals(WSSConstants.ENCRYPT)) {
+                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, ekId);
+                if (wrappingSecurityToken.getProcessor() != null) {
+                    finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+                } else {
+                    finalEncryptedKeyOutputProcessor.getAfterProcessors().add(org.swssf.wss.impl.processor.output.EncryptEndingOutputProcessor.class.getName());
+                }
+            } else if (action.equals(WSSConstants.SIGNATURE_WITH_DERIVED_KEY)) {
+                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
+                if (wrappingSecurityToken.getProcessor() != null) {
+                    finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+                } else {
+                    finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(org.swssf.wss.impl.processor.output.SignatureOutputProcessor.class.getName());
+                }
+            } else if (action.equals(WSSConstants.ENCRYPT_WITH_DERIVED_KEY)) {
+                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
+                if (wrappingSecurityToken.getProcessor() != null) {
+                    finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+                } else {
+                    finalEncryptedKeyOutputProcessor.getAfterProcessors().add(org.swssf.wss.impl.processor.output.EncryptEndingOutputProcessor.class.getName());
+                }
             }
             outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(ekId, encryptedKeySecurityTokenProvider);
             encryptedKeySecurityToken.setProcessor(finalEncryptedKeyOutputProcessor);
@@ -178,7 +178,7 @@ public class EncryptedKeyOutputProcessor
 
         private SecurityToken securityToken;
 
-        FinalEncryptedKeyOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken) throws WSSecurityException {
+        FinalEncryptedKeyOutputProcessor(XMLSecurityProperties securityProperties, XMLSecurityConstants.Action action, SecurityToken securityToken) throws XMLSecurityException {
             super(securityProperties, action);
             this.getAfterProcessors().add(FinalEncryptedKeyOutputProcessor.class.getName());
             this.securityToken = securityToken;
@@ -206,28 +206,28 @@ public class EncryptedKeyOutputProcessor
         */
 
         @Override
-        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
             outputProcessorChain.processEvent(xmlEvent);
             if (xmlEvent.isStartElement()) {
                 StartElement startElement = xmlEvent.asStartElement();
-                if (outputProcessorChain.getDocumentContext().isInSecurityHeader() && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+                if (((WSSDocumentContext) outputProcessorChain.getDocumentContext()).isInSecurityHeader() && startElement.getName().equals(WSSConstants.TAG_wsse_Security)) {
                     OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
 
                     X509Certificate x509Certificate = securityToken.getKeyWrappingToken().getX509Certificates()[0];
 
                     Map<QName, String> attributes = new HashMap<QName, String>();
-                    attributes.put(Constants.ATT_NULL_Id, securityToken.getId());
-                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptedKey, attributes);
+                    attributes.put(WSSConstants.ATT_NULL_Id, securityToken.getId());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_EncryptedKey, attributes);
 
                     attributes = new HashMap<QName, String>();
-                    attributes.put(Constants.ATT_NULL_Algorithm, getSecurityProperties().getEncryptionKeyTransportAlgorithm());
-                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptionMethod, attributes);
-                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptionMethod);
-                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_dsig_KeyInfo, null);
-                    createSecurityTokenReferenceStructureForEncryptedKey(subOutputProcessorChain, securityToken, getSecurityProperties().getEncryptionKeyIdentifierType(), getSecurityProperties().isUseSingleCert());
-                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_dsig_KeyInfo);
-                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherData, null);
-                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherValue, null);
+                    attributes.put(WSSConstants.ATT_NULL_Algorithm, getSecurityProperties().getEncryptionKeyTransportAlgorithm());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_EncryptionMethod, attributes);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_EncryptionMethod);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_KeyInfo, null);
+                    createSecurityTokenReferenceStructureForEncryptedKey(subOutputProcessorChain, securityToken, ((WSSSecurityProperties) getSecurityProperties()).getEncryptionKeyIdentifierType(), getSecurityProperties().isUseSingleCert());
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_KeyInfo);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_CipherData, null);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_CipherValue, null);
 
                     try {
                         //encrypt the symmetric session key with the public key from the receiver:
@@ -258,16 +258,166 @@ public class EncryptedKeyOutputProcessor
                         throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
                     }
 
-                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherValue);
-                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherData);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_CipherValue);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_CipherData);
 
-                    if (getAction() == Constants.Action.ENCRYPT) {
+                    if (getAction() == WSSConstants.ENCRYPT) {
                         createReferenceListStructure(subOutputProcessorChain);
                     }
-                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptedKey);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_xenc_EncryptedKey);
                     outputProcessorChain.removeProcessor(this);
                 }
             }
         }
+
+        protected void createSecurityTokenReferenceStructureForEncryptedKey(
+                OutputProcessorChain outputProcessorChain,
+                SecurityToken securityToken,
+                WSSConstants.KeyIdentifierType keyIdentifierType,
+                boolean useSingleCertificate)
+                throws XMLStreamException, XMLSecurityException {
+
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_wsu_Id, "STRId-" + UUID.randomUUID().toString());
+            if ((keyIdentifierType.name().equals(WSSConstants.KeyIdentifierType.BST_DIRECT_REFERENCE.name())
+                    || keyIdentifierType.name().equals(WSSConstants.KeyIdentifierType.BST_EMBEDDED.name()))
+                    && !useSingleCertificate) {
+                attributes.put(WSSConstants.ATT_wsse11_TokenType, WSSConstants.NS_X509PKIPathv1);
+            }
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_SecurityTokenReference, attributes);
+
+            X509Certificate[] x509Certificates = securityToken.getKeyWrappingToken().getX509Certificates();
+            String tokenId = securityToken.getKeyWrappingToken().getId();
+
+            if (keyIdentifierType.name().equals(WSSConstants.KeyIdentifierType.ISSUER_SERIAL.name())) {
+                createX509IssuerSerialStructure(outputProcessorChain, x509Certificates);
+            } else if (keyIdentifierType.name().equals(WSSConstants.KeyIdentifierType.SKI_KEY_IDENTIFIER.name())) {
+                createX509SubjectKeyIdentifierStructure(outputProcessorChain, x509Certificates);
+            } else if (keyIdentifierType.name().equals(WSSConstants.KeyIdentifierType.X509_KEY_IDENTIFIER.name())) {
+                createX509KeyIdentifierStructure(outputProcessorChain, x509Certificates);
+            } else if (keyIdentifierType.name().equals(WSSConstants.KeyIdentifierType.THUMBPRINT_IDENTIFIER.name())) {
+                createThumbprintKeyIdentifierStructure(outputProcessorChain, x509Certificates);
+            } else if (keyIdentifierType.name().equals(WSSConstants.KeyIdentifierType.BST_EMBEDDED.name())) {
+                createBSTReferenceStructure(outputProcessorChain, tokenId, x509Certificates, useSingleCertificate, true);
+            } else if (keyIdentifierType.name().equals(WSSConstants.KeyIdentifierType.BST_DIRECT_REFERENCE.name())) {
+                createBSTReferenceStructure(outputProcessorChain, tokenId, x509Certificates, useSingleCertificate, false);
+            } else if (keyIdentifierType.name().equals(WSSConstants.KeyIdentifierType.EMBEDDED_SECURITY_TOKEN_REF.name())) {
+                createEmbeddedSecurityTokenReferenceStructure(outputProcessorChain, tokenId);
+            } else {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_ENCRYPTION, "unsupportedSecurityToken", keyIdentifierType.name());
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_SecurityTokenReference);
+        }
+
+        //todo common method
+        protected void createX509SubjectKeyIdentifierStructure(OutputProcessorChain outputProcessorChain, X509Certificate[] x509Certificates) throws XMLSecurityException, XMLStreamException {
+            // As per the 1.1 specification, SKI can only be used for a V3 certificate
+            if (x509Certificates[0].getVersion() != 3) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, "invalidCertForSKI");
+            }
+
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_NULL_EncodingType, WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, WSSConstants.NS_X509SubjectKeyIdentifier);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier, attributes);
+            byte data[] = new Merlin().getSKIBytesFromCert(x509Certificates[0]);
+            createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(data));
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier);
+        }
+
+        //todo common method
+        protected void createX509KeyIdentifierStructure(OutputProcessorChain outputProcessorChain, X509Certificate[] x509Certificates) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_NULL_EncodingType, WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, WSSConstants.NS_X509_V3_TYPE);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier, attributes);
+            try {
+                createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(x509Certificates[0].getEncoded()));
+            } catch (CertificateEncodingException e) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier);
+        }
+
+        //todo common methdod
+        protected void createThumbprintKeyIdentifierStructure(OutputProcessorChain outputProcessorChain, X509Certificate[] x509Certificates) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_NULL_EncodingType, WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, WSSConstants.NS_THUMBPRINT);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier, attributes);
+            try {
+                MessageDigest sha;
+                sha = MessageDigest.getInstance("SHA-1");
+                sha.reset();
+                sha.update(x509Certificates[0].getEncoded());
+                byte[] data = sha.digest();
+
+                createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(data));
+            } catch (CertificateEncodingException e) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+            } catch (NoSuchAlgorithmException e) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_KeyIdentifier);
+        }
+
+        //todo common method
+        protected void createBSTReferenceStructure(OutputProcessorChain outputProcessorChain, String referenceId, X509Certificate[] x509Certificates, boolean useSingleCertificate, boolean embed) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            String valueType;
+            if (useSingleCertificate) {
+                valueType = WSSConstants.NS_X509_V3_TYPE;
+            } else {
+                valueType = WSSConstants.NS_X509PKIPathv1;
+            }
+            attributes.put(WSSConstants.ATT_NULL_URI, "#" + referenceId);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, valueType);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference, attributes);
+            if (embed) {
+                createBinarySecurityTokenStructure(outputProcessorChain, referenceId, x509Certificates, useSingleCertificate);
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference);
+        }
+
+        //todo common method
+        protected void createEmbeddedSecurityTokenReferenceStructure(OutputProcessorChain outputProcessorChain, String referenceId) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            attributes.put(WSSConstants.ATT_NULL_URI, "#" + referenceId);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference, attributes);
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_Reference);
+        }
+
+        //todo common method
+        protected void createBinarySecurityTokenStructure(OutputProcessorChain outputProcessorChain, String referenceId, X509Certificate[] x509Certificates, boolean useSingleCertificate) throws XMLStreamException, XMLSecurityException {
+            Map<QName, String> attributes = new HashMap<QName, String>();
+            String valueType;
+            if (useSingleCertificate) {
+                valueType = WSSConstants.NS_X509_V3_TYPE;
+            } else {
+                valueType = WSSConstants.NS_X509PKIPathv1;
+            }
+            attributes.put(WSSConstants.ATT_NULL_EncodingType, WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING);
+            attributes.put(WSSConstants.ATT_NULL_ValueType, valueType);
+            attributes.put(WSSConstants.ATT_wsu_Id, referenceId);
+            createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_BinarySecurityToken, attributes);
+            try {
+                if (useSingleCertificate) {
+                    createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(x509Certificates[0].getEncoded()));
+                } else {
+                    try {
+                        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC");
+                        List<X509Certificate> certificates = Arrays.asList(x509Certificates);
+                        createCharactersAndOutputAsEvent(outputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(certificateFactory.generateCertPath(certificates).getEncoded()));
+                    } catch (CertificateException e) {
+                        throw new XMLSecurityException(XMLSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, e);
+                    } catch (NoSuchProviderException e) {
+                        throw new XMLSecurityException(XMLSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, e);
+                    }
+                }
+            } catch (CertificateEncodingException e) {
+                throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+            }
+            createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_wsse_BinarySecurityToken);
+        }
     }
 }