ws-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gi...@apache.org
Subject svn commit: r1172285 [17/48] - in /webservices/wss4j/branches/swssf: ./ cxf-integration/ cxf-integration/src/ cxf-integration/src/main/ cxf-integration/src/main/java/ cxf-integration/src/main/java/org/ cxf-integration/src/main/java/org/swssf/ cxf-integ...
Date Sun, 18 Sep 2011 13:51:36 GMT
Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/XMLSecurityStreamWriter.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/XMLSecurityStreamWriter.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/XMLSecurityStreamWriter.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/XMLSecurityStreamWriter.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,254 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl;
+
+import org.swssf.ext.OutputProcessorChain;
+import org.swssf.ext.WSSecurityException;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.Namespace;
+import javax.xml.stream.events.XMLEvent;
+import java.util.*;
+
+/**
+ * Custom XMLStreamWriter to map XMLStreamWriter method calls into XMLEvent's
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class XMLSecurityStreamWriter implements XMLStreamWriter {
+
+    private XMLEventFactory xmlEventFactory = XMLEventFactory.newFactory();
+
+    private OutputProcessorChain outputProcessorChain;
+
+    public XMLSecurityStreamWriter(OutputProcessorChain outputProcessorChain) {
+        this.outputProcessorChain = outputProcessorChain;
+    }
+
+    private void chainProcessEvent(XMLEvent xmlEvent) throws XMLStreamException {
+        try {
+            outputProcessorChain.reset();
+            outputProcessorChain.processEvent(xmlEvent);
+        } catch (WSSecurityException e) {
+            throw new XMLStreamException(e);
+        }
+    }
+
+    private Deque<QName> startElementStack = new ArrayDeque<QName>();
+    private QName openStartElement = null;
+    private List<Attribute> currentAttributes = new LinkedList<Attribute>();
+    private List<Namespace> currentNamespaces = new LinkedList<Namespace>();
+
+    private void outputOpenStartElement() throws XMLStreamException {
+        if (openStartElement != null) {
+            chainProcessEvent(xmlEventFactory.createStartElement(openStartElement, currentAttributes.iterator(), currentNamespaces.iterator()));
+            currentAttributes.clear();
+            currentNamespaces.clear();
+            openStartElement = null;
+        }
+    }
+
+    public void writeStartElement(String localName) throws XMLStreamException {
+        outputOpenStartElement();
+        QName qName;
+        if (localName.contains(":")) {
+            String[] splittedName = localName.split(":");
+            qName = new QName(null, splittedName[1], splittedName[0]);
+        } else {
+            qName = new QName(localName);
+        }
+        startElementStack.push(qName);
+        openStartElement = qName;
+    }
+
+    public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
+        outputOpenStartElement();
+        QName qName;
+        if (localName.contains(":")) {
+            String[] splittedName = localName.split(":");
+            qName = new QName(null, splittedName[1], splittedName[0]);
+        } else {
+            qName = new QName(namespaceURI, localName);
+        }
+        startElementStack.push(qName);
+        openStartElement = qName;
+    }
+
+    public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
+        outputOpenStartElement();
+        QName qName = new QName(namespaceURI, localName, prefix);
+        startElementStack.push(qName);
+        openStartElement = qName;
+    }
+
+    public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
+        outputOpenStartElement();
+        chainProcessEvent(xmlEventFactory.createStartElement(null, namespaceURI, localName));
+        chainProcessEvent(xmlEventFactory.createEndElement(null, namespaceURI, localName));
+    }
+
+    public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
+        outputOpenStartElement();
+        chainProcessEvent(xmlEventFactory.createStartElement(prefix, namespaceURI, localName));
+        chainProcessEvent(xmlEventFactory.createEndElement(prefix, namespaceURI, localName));
+    }
+
+    public void writeEmptyElement(String localName) throws XMLStreamException {
+        outputOpenStartElement();
+        chainProcessEvent(xmlEventFactory.createStartElement(null, null, localName));
+        chainProcessEvent(xmlEventFactory.createEndElement(null, null, localName));
+    }
+
+    public void writeEndElement() throws XMLStreamException {
+        outputOpenStartElement();
+
+        List<Namespace> namespaceList = new LinkedList<Namespace>();
+        QName element = startElementStack.pop();
+        namespaceList.add(xmlEventFactory.createNamespace(element.getPrefix(), element.getNamespaceURI()));
+        EndElement endElement = xmlEventFactory.createEndElement(element, namespaceList.iterator());
+        chainProcessEvent(endElement);
+    }
+
+    public void writeEndDocument() throws XMLStreamException {
+        outputOpenStartElement();
+        Iterator<QName> startElements = startElementStack.iterator();
+        while (startElements.hasNext()) {
+            chainProcessEvent(xmlEventFactory.createEndElement(startElementStack.pop(), null));
+        }
+    }
+
+    public void close() throws XMLStreamException {
+        try {
+            outputProcessorChain.reset();
+            outputProcessorChain.doFinal();
+        } catch (WSSecurityException e) {
+            throw new XMLStreamException(e);
+        }
+    }
+
+    public void flush() throws XMLStreamException {
+    }
+
+    public void writeAttribute(String localName, String value) throws XMLStreamException {
+        currentAttributes.add(xmlEventFactory.createAttribute(localName, value));
+    }
+
+    public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException {
+        currentAttributes.add(xmlEventFactory.createAttribute(prefix, namespaceURI, localName, value));
+    }
+
+    public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
+        //todo: null is not correct!
+        currentAttributes.add(xmlEventFactory.createAttribute(null, namespaceURI, localName, value));
+    }
+
+    public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
+        currentNamespaces.add(xmlEventFactory.createNamespace(prefix, namespaceURI));
+    }
+
+    public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
+        currentNamespaces.add(xmlEventFactory.createNamespace(namespaceURI));
+    }
+
+    public void writeComment(String data) throws XMLStreamException {
+        outputOpenStartElement();
+        chainProcessEvent(xmlEventFactory.createComment(data));
+    }
+
+    public void writeProcessingInstruction(String target) throws XMLStreamException {
+        outputOpenStartElement();
+        //todo null correct?
+        chainProcessEvent(xmlEventFactory.createProcessingInstruction(target, null));
+    }
+
+    public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
+        outputOpenStartElement();
+        chainProcessEvent(xmlEventFactory.createProcessingInstruction(target, data));
+    }
+
+    public void writeCData(String data) throws XMLStreamException {
+        outputOpenStartElement();
+        chainProcessEvent(xmlEventFactory.createCData(data));
+    }
+
+    public void writeDTD(String dtd) throws XMLStreamException {
+        outputOpenStartElement();
+        chainProcessEvent(xmlEventFactory.createDTD(dtd));
+    }
+
+    public void writeEntityRef(String name) throws XMLStreamException {
+        outputOpenStartElement();
+        //todo null not correct
+        chainProcessEvent(xmlEventFactory.createEntityReference(name, null));
+    }
+
+    public void writeStartDocument() throws XMLStreamException {
+        chainProcessEvent(xmlEventFactory.createStartDocument());
+    }
+
+    public void writeStartDocument(String version) throws XMLStreamException {
+        chainProcessEvent(xmlEventFactory.createStartDocument("utf-8", version));
+    }
+
+    public void writeStartDocument(String encoding, String version) throws XMLStreamException {
+        chainProcessEvent(xmlEventFactory.createStartDocument(encoding, version));
+    }
+
+    public void writeCharacters(String text) throws XMLStreamException {
+        outputOpenStartElement();
+        chainProcessEvent(xmlEventFactory.createCharacters(text));
+    }
+
+    public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
+        outputOpenStartElement();
+        chainProcessEvent(xmlEventFactory.createCharacters(new String(text, start, len)));
+    }
+
+    public String getPrefix(String uri) throws XMLStreamException {
+        //todo
+        return null;
+    }
+
+    public void setPrefix(String prefix, String uri) throws XMLStreamException {
+        //todo
+    }
+
+    public void setDefaultNamespace(String uri) throws XMLStreamException {
+        //todo
+    }
+
+    public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
+        //todo
+    }
+
+    public NamespaceContext getNamespaceContext() {
+        return null;
+    }
+
+    public Object getProperty(String name) throws IllegalArgumentException {
+        return null;
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/XMLSecurityStreamWriter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/HMACSignatureAlgorithm.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/HMACSignatureAlgorithm.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/HMACSignatureAlgorithm.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/HMACSignatureAlgorithm.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.algorithms;
+
+import org.swssf.ext.WSSecurityException;
+import org.xmlsecurity.ns.configuration.AlgorithmType;
+
+import javax.crypto.Mac;
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class HMACSignatureAlgorithm implements SignatureAlgorithm {
+
+    private AlgorithmType algorithmType;
+    private Mac mac;
+
+    public HMACSignatureAlgorithm(AlgorithmType algorithmType) throws NoSuchProviderException, NoSuchAlgorithmException {
+        this.algorithmType = algorithmType;
+        mac = Mac.getInstance(algorithmType.getJCEName(), algorithmType.getJCEProvider());
+    }
+
+    public void engineUpdate(byte[] input) throws WSSecurityException {
+        mac.update(input);
+    }
+
+    public void engineUpdate(byte input) throws WSSecurityException {
+        mac.update(input);
+    }
+
+    public void engineUpdate(byte[] buf, int offset, int len) throws WSSecurityException {
+        mac.update(buf, offset, len);
+    }
+
+    public void engineInitSign(Key signingKey) throws WSSecurityException {
+        try {
+            mac.init(signingKey);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+        }
+    }
+
+    public void engineInitSign(Key signingKey, SecureRandom secureRandom) throws WSSecurityException {
+        try {
+            mac.init(signingKey);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+        }
+    }
+
+    public void engineInitSign(Key signingKey, AlgorithmParameterSpec algorithmParameterSpec) throws WSSecurityException {
+        try {
+            mac.init(signingKey, algorithmParameterSpec);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+        }
+    }
+
+    public byte[] engineSign() throws WSSecurityException {
+        return mac.doFinal();
+    }
+
+    public void engineInitVerify(Key verificationKey) throws WSSecurityException {
+        try {
+            mac.init(verificationKey);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, e);
+        }
+    }
+
+    public boolean engineVerify(byte[] signature) throws WSSecurityException {
+        byte[] completeResult = mac.doFinal();
+        return MessageDigest.isEqual(completeResult, signature);
+    }
+
+    public void engineSetParameter(AlgorithmParameterSpec params) throws WSSecurityException {
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/HMACSignatureAlgorithm.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/PKISignatureAlgorithm.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/PKISignatureAlgorithm.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/PKISignatureAlgorithm.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/PKISignatureAlgorithm.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.algorithms;
+
+import org.swssf.ext.WSSecurityException;
+import org.xmlsecurity.ns.configuration.AlgorithmType;
+
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class PKISignatureAlgorithm implements SignatureAlgorithm {
+
+    private AlgorithmType algorithmType;
+    private Signature signature;
+
+    public PKISignatureAlgorithm(AlgorithmType algorithmType) throws NoSuchProviderException, NoSuchAlgorithmException {
+        this.algorithmType = algorithmType;
+        signature = Signature.getInstance(algorithmType.getJCEName(), algorithmType.getJCEProvider());
+    }
+
+    public void engineUpdate(byte[] input) throws WSSecurityException {
+        try {
+            signature.update(input);
+        } catch (SignatureException e) {
+            throw new WSSecurityException(e.getMessage(), e);
+        }
+    }
+
+    public void engineUpdate(byte input) throws WSSecurityException {
+        try {
+            signature.update(input);
+        } catch (SignatureException e) {
+            throw new WSSecurityException(e.getMessage(), e);
+        }
+    }
+
+    public void engineUpdate(byte[] buf, int offset, int len) throws WSSecurityException {
+        try {
+            signature.update(buf, offset, len);
+        } catch (SignatureException e) {
+            throw new WSSecurityException(e.getMessage(), e);
+        }
+    }
+
+    public void engineInitSign(Key signingKey) throws WSSecurityException {
+        try {
+            signature.initSign((PrivateKey) signingKey);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+        }
+    }
+
+    public void engineInitSign(Key signingKey, SecureRandom secureRandom) throws WSSecurityException {
+        try {
+            signature.initSign((PrivateKey) signingKey, secureRandom);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+        }
+    }
+
+    public void engineInitSign(Key signingKey, AlgorithmParameterSpec algorithmParameterSpec) throws WSSecurityException {
+        try {
+            signature.initSign((PrivateKey) signingKey);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+        }
+    }
+
+    public byte[] engineSign() throws WSSecurityException {
+        try {
+            return signature.sign();
+        } catch (SignatureException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, e);
+        }
+    }
+
+    public void engineInitVerify(Key verificationKey) throws WSSecurityException {
+        try {
+            signature.initVerify((PublicKey) verificationKey);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, e);
+        }
+    }
+
+    public boolean engineVerify(byte[] signature) throws WSSecurityException {
+        try {
+            return this.signature.verify(signature);
+        } catch (SignatureException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, e);
+        }
+    }
+
+    public void engineSetParameter(AlgorithmParameterSpec params) throws WSSecurityException {
+        try {
+            signature.setParameter(params);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new WSSecurityException(e.getMessage(), e);
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/PKISignatureAlgorithm.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithm.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithm.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithm.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithm.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.algorithms;
+
+import org.swssf.ext.WSSecurityException;
+
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public interface SignatureAlgorithm {
+
+    public void engineUpdate(byte[] input) throws WSSecurityException;
+
+    public void engineUpdate(byte input) throws WSSecurityException;
+
+    public void engineUpdate(byte buf[], int offset, int len) throws WSSecurityException;
+
+    public void engineInitSign(Key signingKey) throws WSSecurityException;
+
+    public void engineInitSign(Key signingKey, SecureRandom secureRandom) throws WSSecurityException;
+
+    public void engineInitSign(Key signingKey, AlgorithmParameterSpec algorithmParameterSpec) throws WSSecurityException;
+
+    public byte[] engineSign() throws WSSecurityException;
+
+    public void engineInitVerify(Key verificationKey) throws WSSecurityException;
+
+    public boolean engineVerify(byte[] signature) throws WSSecurityException;
+
+    public void engineSetParameter(AlgorithmParameterSpec params) throws WSSecurityException;
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithm.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithmFactory.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithmFactory.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithmFactory.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithmFactory.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.algorithms;
+
+import org.swssf.config.JCEAlgorithmMapper;
+import org.swssf.ext.WSSecurityException;
+import org.xmlsecurity.ns.configuration.AlgorithmType;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SignatureAlgorithmFactory {
+
+    private static SignatureAlgorithmFactory instance = null;
+
+    private SignatureAlgorithmFactory() {
+    }
+
+    public static synchronized SignatureAlgorithmFactory getInstance() {
+        if (instance == null) {
+            instance = new SignatureAlgorithmFactory();
+        }
+        return instance;
+    }
+
+    public SignatureAlgorithm getSignatureAlgorithm(String algoURI) throws WSSecurityException, NoSuchProviderException, NoSuchAlgorithmException {
+        AlgorithmType algorithmType = JCEAlgorithmMapper.getAlgorithmMapping(algoURI);
+        if (algorithmType == null) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "unknownSignatureAlgorithm", algoURI);
+        }
+        String algorithmClass = algorithmType.getAlgorithmClass();
+        if ("MAC".equalsIgnoreCase(algorithmClass)) {
+            return new HMACSignatureAlgorithm(algorithmType);
+        } else if ("Signature".equalsIgnoreCase(algorithmClass)) {
+            return new PKISignatureAlgorithm(algorithmType);
+        } else {
+            return null;
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/algorithms/SignatureAlgorithmFactory.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/AlgoFactory.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/AlgoFactory.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/AlgoFactory.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/AlgoFactory.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.swssf.impl.derivedKey;
+
+import org.swssf.ext.Constants;
+
+/**
+ * @author Ruchith Fernando
+ */
+
+public class AlgoFactory {
+
+    /**
+     * This gives a DerivationAlgorithm instance from the default set of algorithms provided
+     *
+     * @param algorithm The algo identifier @see DeivationAlgorithm
+     * @return A derivation algorithm
+     * @throws ConversationException If the specified algorithm is not available
+     *                               in default implementations
+     */
+    public static DerivationAlgorithm getInstance(String algorithm) throws
+            ConversationException {
+        if ((Constants.P_SHA_1_2005_12).equals(algorithm) || (Constants.P_SHA_1).equals(algorithm)) {
+            return new P_SHA1();
+        } else {
+            throw new ConversationException("No such algorithm");
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/AlgoFactory.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/ConversationException.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/ConversationException.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/ConversationException.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/ConversationException.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,121 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.swssf.impl.derivedKey;
+
+import org.swssf.ext.Constants;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class ConversationException extends Exception {
+
+    private static final long serialVersionUID = 970894530660804319L;
+
+    public final static String BAD_CONTEXT_TOKEN = "BadContextToken";
+    public final static String UNSUPPORTED_CONTEXT_TOKEN = "UnsupportedContextToken";
+    public final static String UNKNOWN_DERIVATION_SOURCE = "UnknownDerivationSource";
+    public final static String RENEW_NEEDED = "RenewNeeded";
+    public final static String UNABLE_TO_REVIEW = "UnableToRenew";
+
+    private static ResourceBundle resources;
+
+    private String faultCode;
+    private String faultString;
+
+    static {
+        try {
+            resources = ResourceBundle.getBundle("org.apache.ws.security.conversation.errors");
+        } catch (MissingResourceException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    public ConversationException(String faultCode, Object... args) {
+        super(getMessage(faultCode, args));
+        this.faultCode = getFaultCode(faultCode);
+        this.faultString = getMessage(faultCode, args);
+    }
+
+    /**
+     * Construct the fault properly code for the standard faults
+     *
+     * @return
+     */
+    private String getFaultCode(String code) {
+        if (BAD_CONTEXT_TOKEN.equals(code) ||
+                UNABLE_TO_REVIEW.equals(code) ||
+                UNKNOWN_DERIVATION_SOURCE.equals(code) ||
+                UNSUPPORTED_CONTEXT_TOKEN.equals(code) ||
+                RENEW_NEEDED.equals(code)) {
+            return Constants.PREFIX_WSC + ":" + code;
+        } else {
+            return code;
+        }
+    }
+
+    public ConversationException(String faultCode) {
+        this(faultCode, (Object[]) null);
+    }
+
+    public ConversationException(String faultCode, Throwable e, Object... arguments) {
+        super(getMessage(faultCode, arguments), e);
+        this.faultCode = faultCode;
+        this.faultString = getMessage(faultCode, arguments);
+    }
+
+    public ConversationException(String faultCode, Throwable e) {
+        this(faultCode, e, null);
+    }
+
+    /**
+     * get the message from resource bundle.
+     * <p/>
+     *
+     * @return the message translated from the property (message) file.
+     */
+    protected static String getMessage(String faultCode, Object... args) {
+        String msg = null;
+        try {
+            msg = MessageFormat.format(resources.getString(faultCode), args);
+        } catch (MissingResourceException e) {
+            throw new RuntimeException("Undefined '" + faultCode + "' resource property", e);
+        }
+        if (msg != null) {
+            return msg;
+        } else {
+            return faultCode;
+        }
+    }
+
+    /**
+     * @return Returns the faultCode.
+     */
+    protected String getFaultCode() {
+        return faultCode;
+    }
+
+    /**
+     * @return Returns the faultString.
+     */
+    protected String getFaultString() {
+        return faultString;
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/ConversationException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivationAlgorithm.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivationAlgorithm.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivationAlgorithm.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivationAlgorithm.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.swssf.impl.derivedKey;
+
+
+/**
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public interface DerivationAlgorithm {
+
+    public byte[] createKey(byte[] secret, byte[] seed, int offset, long length) throws ConversationException;
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivationAlgorithm.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivedKeyUtils.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivedKeyUtils.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivedKeyUtils.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivedKeyUtils.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.derivedKey;
+
+import org.apache.commons.codec.binary.Base64;
+import org.swssf.ext.Constants;
+import org.swssf.ext.WSSecurityException;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class DerivedKeyUtils {
+
+    /**
+     * Derive a key from this DerivedKeyToken instance
+     *
+     * @param length
+     * @param secret
+     * @throws org.swssf.ext.WSSecurityException
+     *
+     */
+    public static byte[] deriveKey(String algorithm, String label, int length, byte[] secret, byte[] nonce, int offset) throws WSSecurityException {
+        try {
+            if (algorithm == null || algorithm.equals("")) {
+                algorithm = Constants.P_SHA_1;
+            }
+            DerivationAlgorithm algo = AlgoFactory.getInstance(algorithm);
+            byte[] labelBytes;
+            if (label == null || label.length() == 0) {
+                labelBytes = (Constants.WS_SecureConversation_DEFAULT_LABEL + Constants.WS_SecureConversation_DEFAULT_LABEL).getBytes("UTF-8");
+            } else {
+                labelBytes = label.getBytes("UTF-8");
+            }
+
+            nonce = Base64.decodeBase64(nonce);
+            byte[] seed = new byte[labelBytes.length + nonce.length];
+            System.arraycopy(labelBytes, 0, seed, 0, labelBytes.length);
+            System.arraycopy(nonce, 0, seed, labelBytes.length, nonce.length);
+
+            if (length <= 0) {
+                length = 32;
+            }
+            return algo.createKey(secret, seed, offset, length);
+
+        } catch (Exception e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/DerivedKeyUtils.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/P_SHA1.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/P_SHA1.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/P_SHA1.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/P_SHA1.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,105 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.swssf.impl.derivedKey;
+
+/**
+ *
+ <pre>
+ P_SHA-1 DEFINITION
+ ==================
+ <b>P_SHA-1(secret, seed)</b> =
+ HMAC_SHA-1(secret, A(1) + seed) +
+ HMAC_SHA-1(secret, A(2) + seed) +
+ HMAC_SHA-1(secret, A(3) + seed) + ...
+ <i>Where + indicates concatenation.</i>
+ <br>
+ A() is defined as:
+ A(0) = seed
+ A(i) = HMAC_SHA-1(secret, A(i-1))
+ <br>
+ <i>Source : RFC 2246 - The TLS Protocol Version 1.0
+ Section 5. HMAC and the pseudorandom function</i>
+ </pre>
+ *
+ * @author Ruchith Fernando
+ */
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+public class P_SHA1
+        implements DerivationAlgorithm {
+
+    public byte[] createKey(byte[] secret, byte[] seed, int offset,
+                            long length) throws ConversationException {
+        try {
+            Mac mac = Mac.getInstance("HmacSHA1");
+
+            byte[] tempBytes = P_hash(secret, seed, mac,
+                    (offset + (int) length));
+
+            byte[] key = new byte[(int) length];
+
+            System.arraycopy(tempBytes, 0 + offset, key, 0, key.length);
+
+            return key;
+        } catch (Exception ex) {
+            throw new ConversationException("errorInKeyDerivation", ex, null);
+        }
+    }
+
+    /**
+     * From WSUsernameToken  :-)
+     *
+     * @param secret
+     * @param seed
+     * @param mac
+     * @param required
+     * @return
+     * @throws Exception
+     */
+    private static byte[] P_hash(byte[] secret, byte[] seed, Mac mac,
+                                 int required) throws Exception {
+        byte[] out = new byte[required];
+        int offset = 0, tocpy;
+        byte[] A, tmp;
+        A = seed;
+        while (required > 0) {
+            SecretKeySpec key = new SecretKeySpec(secret, "HMACSHA1");
+            mac.init(key);
+            mac.update(A);
+            A = mac.doFinal();
+            mac.reset();
+            mac.init(key);
+            mac.update(A);
+            mac.update(seed);
+            tmp = mac.doFinal();
+            tocpy = min(required, tmp.length);
+            System.arraycopy(tmp, 0, out, offset, tocpy);
+            offset += tocpy;
+            required -= tocpy;
+        }
+        return out;
+    }
+
+    private static int min(int a, int b) {
+        return (a > b) ? b : a;
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/derivedKey/P_SHA1.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/BinarySecurityTokenInputHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/BinarySecurityTokenInputHandler.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/BinarySecurityTokenInputHandler.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/BinarySecurityTokenInputHandler.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.processor.input;
+
+import org.oasis_open.docs.wss._2004._01.oasis_200401_wss_wssecurity_secext_1_0.BinarySecurityTokenType;
+import org.swssf.crypto.Crypto;
+import org.swssf.ext.*;
+import org.swssf.impl.securityToken.SecurityTokenFactory;
+
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Processor for the BinarySecurityToken XML Structure
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class BinarySecurityTokenInputHandler extends AbstractInputSecurityHeaderHandler {
+
+    public BinarySecurityTokenInputHandler(final InputProcessorChain inputProcessorChain, final SecurityProperties securityProperties, Deque<XMLEvent> eventQueue, Integer index) throws WSSecurityException {
+
+        final BinarySecurityTokenType binarySecurityTokenType = (BinarySecurityTokenType) parseStructure(eventQueue, index);
+
+        if (binarySecurityTokenType.getId() == null) {
+            binarySecurityTokenType.setId(UUID.randomUUID().toString());
+        }
+
+        SecurityTokenProvider securityTokenProvider = new SecurityTokenProvider() {
+
+            private Map<Crypto, SecurityToken> securityTokens = new HashMap<Crypto, SecurityToken>();
+
+            public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+                SecurityToken securityToken = securityTokens.get(crypto);
+                if (securityToken != null) {
+                    return securityToken;
+                }
+                securityToken = SecurityTokenFactory.newInstance().getSecurityToken(binarySecurityTokenType, inputProcessorChain.getSecurityContext(), crypto, securityProperties.getCallbackHandler(), null);
+                securityTokens.put(crypto, securityToken);
+                return securityToken;
+            }
+
+            public String getId() {
+                return binarySecurityTokenType.getId();
+            }
+        };
+
+        inputProcessorChain.getSecurityContext().registerSecurityTokenProvider(binarySecurityTokenType.getId(), securityTokenProvider);
+
+    }
+
+    @Override
+    protected Parseable getParseable(StartElement startElement) {
+        return new BinarySecurityTokenType(startElement);
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/BinarySecurityTokenInputHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/DecryptInputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/DecryptInputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/DecryptInputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/DecryptInputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,669 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.processor.input;
+
+import org.apache.commons.codec.binary.Base64OutputStream;
+import org.swssf.config.JCEAlgorithmMapper;
+import org.swssf.ext.*;
+import org.swssf.impl.securityToken.SecurityTokenFactory;
+import org.swssf.impl.util.IVSplittingOutputStream;
+import org.swssf.impl.util.ReplaceableOuputStream;
+import org.swssf.securityEvent.ContentEncryptedElementSecurityEvent;
+import org.swssf.securityEvent.EncryptedElementSecurityEvent;
+import org.swssf.securityEvent.EncryptedPartSecurityEvent;
+import org.swssf.securityEvent.SecurityEvent;
+import org.w3._2000._09.xmldsig_.KeyInfoType;
+import org.w3._2001._04.xmlenc_.EncryptedDataType;
+import org.w3._2001._04.xmlenc_.ReferenceList;
+import org.w3._2001._04.xmlenc_.ReferenceType;
+import org.xmlsecurity.ns.configuration.AlgorithmType;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.NoSuchPaddingException;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.io.*;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.*;
+
+/**
+ * Processor for decryption of EncryptedData XML structures
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class DecryptInputProcessor extends AbstractInputProcessor {
+
+    private ReferenceList referenceList;
+    private KeyInfoType keyInfoType;
+
+    //the prefix must start with a letter by spec!:
+    private final String uuid = "a" + UUID.randomUUID().toString().replaceAll("-", "");
+    private final QName wrapperElementName = new QName("http://dummy", "dummy", uuid);
+
+    private ArrayDeque<XMLEvent> tmpXmlEventList = new ArrayDeque<XMLEvent>();
+
+    public DecryptInputProcessor(ReferenceList referenceList, SecurityProperties securityProperties) {
+        super(securityProperties);
+        this.referenceList = referenceList;
+    }
+
+    public DecryptInputProcessor(KeyInfoType keyInfoType, ReferenceList referenceList, SecurityProperties securityProperties) {
+        super(securityProperties);
+        this.keyInfoType = keyInfoType;
+        this.referenceList = referenceList;
+    }
+
+    /*
+    <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EncDataId-1612925417" Type="http://www.w3.org/2001/04/xmlenc#Content">
+        <xenc:EncryptionMethod xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
+        <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+            <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+                <wsse:Reference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" URI="#EncKeyId-1483925398" />
+            </wsse:SecurityTokenReference>
+        </ds:KeyInfo>
+        <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
+            <xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
+            ...
+            </xenc:CipherValue>
+        </xenc:CipherData>
+    </xenc:EncryptedData>
+     */
+
+    @Override
+    public XMLEvent processNextHeaderEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+        return processEvent(inputProcessorChain, true);
+        //return xmlEvent;
+    }
+
+    @Override
+    public XMLEvent processNextEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+        return processEvent(inputProcessorChain, false);
+    }
+
+    private XMLEvent processEvent(InputProcessorChain inputProcessorChain, boolean isSecurityHeaderEvent) throws XMLStreamException, WSSecurityException {
+
+        if (!tmpXmlEventList.isEmpty()) {
+            XMLEvent xmlEvent = tmpXmlEventList.pollLast();
+            if (xmlEvent.isStartElement()) {
+                inputProcessorChain.getDocumentContext().addPathElement(xmlEvent.asStartElement().getName());
+            } else if (xmlEvent.isEndElement()) {
+                inputProcessorChain.getDocumentContext().removePathElement();
+            }
+            return xmlEvent;
+        }
+
+        XMLEvent xmlEvent = isSecurityHeaderEvent ? inputProcessorChain.processHeaderEvent() : inputProcessorChain.processEvent();
+
+        boolean encryptedHeader = false;
+
+        if (xmlEvent.isStartElement()) {
+            StartElement startElement = xmlEvent.asStartElement();
+
+            //buffer the events until the EncryptedData Element appears and discard it if we found the reference inside it
+            //otherwise replay it
+            if (startElement.getName().equals(Constants.TAG_wsse11_EncryptedHeader)) {
+
+                InputProcessorChain subInputProcessorChain = inputProcessorChain.createSubChain(this);
+                do {
+                    tmpXmlEventList.push(xmlEvent);
+
+                    subInputProcessorChain.reset();
+                    if (isSecurityHeaderEvent) {
+                        xmlEvent = subInputProcessorChain.processHeaderEvent();
+                    } else {
+                        xmlEvent = subInputProcessorChain.processEvent();
+                    }
+                }
+                while (!(xmlEvent.isStartElement() && xmlEvent.asStartElement().getName().equals(Constants.TAG_xenc_EncryptedData)));
+
+                tmpXmlEventList.push(xmlEvent);
+                startElement = xmlEvent.asStartElement();
+
+                encryptedHeader = true;
+            }
+
+            //check if the current start-element has the name EncryptedData and an Id attribute
+            if (startElement.getName().equals(Constants.TAG_xenc_EncryptedData)) {
+                Attribute refId = startElement.getAttributeByName(Constants.ATT_NULL_Id);
+                if (refId != null) {
+                    //exists the id in the referenceList? 
+                    List<ReferenceType> references = referenceList.getDataReferenceOrKeyReference();
+                    Iterator<ReferenceType> referenceTypeIterator = references.iterator();
+                    while (referenceTypeIterator.hasNext()) {
+                        ReferenceType referenceType = referenceTypeIterator.next();
+                        if (refId.getValue().equals(referenceType.getURI())) {
+                            logger.debug("Found encryption reference: " + refId.getValue() + " on element" + startElement.getName());
+                            //duplicate id's are forbidden
+                            if (referenceType.isProcessed()) {
+                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, "duplicateId");
+                            }
+
+                            XMLEventNS xmlEventNS = (XMLEventNS) xmlEvent;
+                            List<ComparableNamespace>[] comparableNamespaceList;
+                            List<ComparableAttribute>[] comparableAttributeList;
+
+                            if (encryptedHeader) {
+                                tmpXmlEventList.clear();
+                                inputProcessorChain.getDocumentContext().removePathElement();
+
+                                comparableNamespaceList = Arrays.copyOfRange(xmlEventNS.getNamespaceList(), 2, xmlEventNS.getNamespaceList().length);
+                                comparableAttributeList = Arrays.copyOfRange(xmlEventNS.getAttributeList(), 2, xmlEventNS.getNamespaceList().length);
+                            } else {
+                                comparableNamespaceList = Arrays.copyOfRange(xmlEventNS.getNamespaceList(), 1, xmlEventNS.getNamespaceList().length);
+                                comparableAttributeList = Arrays.copyOfRange(xmlEventNS.getAttributeList(), 1, xmlEventNS.getNamespaceList().length);
+                            }
+
+                            EncryptedDataType currentEncryptedDataType = new EncryptedDataType(startElement);
+
+                            referenceType.setProcessed(true);
+                            inputProcessorChain.getDocumentContext().setIsInEncryptedContent();
+
+                            //only fire here ContentEncryptedElementEvents
+                            //the other ones will be fired later, because we don't know the encrypted element name yet
+                            if (SecurePart.Modifier.Content.getModifier().equals(currentEncryptedDataType.getType())) {
+                                QName parentElement = inputProcessorChain.getDocumentContext().getParentElement(xmlEvent.getEventType());
+                                if (inputProcessorChain.getDocumentContext().getDocumentLevel() == 3
+                                        && inputProcessorChain.getDocumentContext().isInSOAPBody()) {
+                                    //soap:body content encryption counts as EncryptedPart
+                                    EncryptedPartSecurityEvent encryptedPartSecurityEvent =
+                                            new EncryptedPartSecurityEvent(SecurityEvent.Event.EncryptedPart, false);
+                                    encryptedPartSecurityEvent.setElement(parentElement);
+                                    inputProcessorChain.getSecurityContext().registerSecurityEvent(encryptedPartSecurityEvent);
+                                } else {
+                                    ContentEncryptedElementSecurityEvent contentEncryptedElementSecurityEvent =
+                                            new ContentEncryptedElementSecurityEvent(SecurityEvent.Event.ContentEncrypted, false);
+                                    contentEncryptedElementSecurityEvent.setElement(parentElement);
+                                    inputProcessorChain.getSecurityContext().registerSecurityEvent(contentEncryptedElementSecurityEvent);
+                                }
+                            }
+
+                            //the following logic reads the encryptedData structure and doesn't pass them further
+                            //through the chain
+                            InputProcessorChain subInputProcessorChain = inputProcessorChain.createSubChain(this);
+
+                            XMLEvent encryptedDataXMLEvent;
+                            do {
+                                subInputProcessorChain.reset();
+                                if (isSecurityHeaderEvent) {
+                                    encryptedDataXMLEvent = subInputProcessorChain.processHeaderEvent();
+                                } else {
+                                    encryptedDataXMLEvent = subInputProcessorChain.processEvent();
+                                }
+
+                                //todo this self made parsing is ugly as hell. An idea would be to use JAXB with a custom WS-Security schema.
+                                //todo the schema would have only the declared the elements which we are supporting.
+                                try {
+                                    currentEncryptedDataType.parseXMLEvent(encryptedDataXMLEvent);
+                                } catch (ParseException e) {
+                                    throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
+                                }
+                            }
+                            while (!(encryptedDataXMLEvent.isStartElement() && encryptedDataXMLEvent.asStartElement().getName().equals(Constants.TAG_xenc_CipherValue)));
+
+                            try {
+                                currentEncryptedDataType.validate();
+                            } catch (ParseException e) {
+                                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
+                            }
+
+                            KeyInfoType keyInfoType;
+                            if (this.keyInfoType != null) {
+                                keyInfoType = this.keyInfoType;
+                            } else {
+                                keyInfoType = currentEncryptedDataType.getKeyInfo();
+                            }
+
+                            //create a new Thread for streaming decryption
+                            DecryptionThread decryptionThread = new DecryptionThread(subInputProcessorChain, isSecurityHeaderEvent,
+                                    currentEncryptedDataType, keyInfoType, xmlEventNS);
+
+                            Thread receiverThread = new Thread(decryptionThread);
+                            receiverThread.setName("decrypting thread");
+
+                            DecryptedEventReaderInputProcessor decryptedEventReaderInputProcessor =
+                                    new DecryptedEventReaderInputProcessor(getSecurityProperties(),
+                                            SecurePart.Modifier.getModifier(currentEncryptedDataType.getType()),
+                                            encryptedHeader, comparableNamespaceList, comparableAttributeList,
+                                            this);
+
+                            //add the new created EventReader processor to the chain.
+                            inputProcessorChain.addProcessor(decryptedEventReaderInputProcessor);
+
+                            //when an exception in the decryption thread occurs, we want to forward them:
+                            receiverThread.setUncaughtExceptionHandler(decryptedEventReaderInputProcessor);
+
+                            //we have to start the thread before we call decryptionThread.getPipedInputStream().
+                            //Otherwise we will end in a deadlock, because the StAX reader expects already data.
+                            //@See some lines below:
+                            logger.debug("Starting decryption thread");
+                            receiverThread.start();
+
+                            inputProcessorChain.getDocumentContext().removePathElement();
+
+                            //spec says (4.2): "The cleartext octet sequence obtained in step 3 is interpreted as UTF-8 encoded character data."
+                            XMLEventReader xmlEventReader =
+                                    inputProcessorChain.getSecurityContext().<XMLInputFactory>get(
+                                            Constants.XMLINPUTFACTORY).createXMLEventReader(decryptionThread.getPipedInputStream(),
+                                            "UTF-8");
+
+                            //forward to wrapper element
+                            XMLEvent tmpXmlEvent;
+                            do {
+                                tmpXmlEvent = xmlEventReader.nextEvent();
+                            }
+                            while (!(tmpXmlEvent.isStartElement() && tmpXmlEvent.asStartElement().getName().equals(wrapperElementName)));
+
+                            decryptedEventReaderInputProcessor.setXmlEventReader(xmlEventReader);
+
+                            if (isSecurityHeaderEvent) {
+                                return decryptedEventReaderInputProcessor.processNextHeaderEvent(inputProcessorChain);
+                            } else {
+                                return decryptedEventReaderInputProcessor.processNextEvent(inputProcessorChain);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (!tmpXmlEventList.isEmpty()) {
+            xmlEvent = tmpXmlEventList.pollLast();
+            if (xmlEvent.isStartElement()) {
+                inputProcessorChain.getDocumentContext().addPathElement(xmlEvent.asStartElement().getName());
+            } else if (xmlEvent.isEndElement()) {
+                inputProcessorChain.getDocumentContext().removePathElement();
+            }
+            return xmlEvent;
+        }
+
+        return xmlEvent;
+    }
+
+    @Override
+    public void doFinal(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+        //here we check if all references where processed.
+        List<ReferenceType> references = referenceList.getDataReferenceOrKeyReference();
+        Iterator<ReferenceType> referenceTypeIterator = references.iterator();
+        while (referenceTypeIterator.hasNext()) {
+            ReferenceType referenceType = referenceTypeIterator.next();
+            if (!referenceType.isProcessed()) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, "unprocessedEncryptionReferences");
+            }
+        }
+        inputProcessorChain.doFinal();
+    }
+
+    /**
+     * The DecryptedEventReaderInputProcessor reads the decrypted stream with a StAX reader and
+     * forwards the generated XMLEvents
+     */
+    class DecryptedEventReaderInputProcessor extends AbstractInputProcessor implements Thread.UncaughtExceptionHandler {
+
+        private XMLEventReader xmlEventReader;
+        private Deque<List<ComparableNamespace>> nsStack = new ArrayDeque<List<ComparableNamespace>>(10);
+        private Deque<List<ComparableAttribute>> attrStack = new ArrayDeque<List<ComparableAttribute>>(10);
+        private SecurePart.Modifier encryptionModifier;
+        private boolean encryptedHeader = false;
+        private int documentLevel = 0;
+
+        private boolean rootElementProcessed;
+
+        DecryptedEventReaderInputProcessor(
+                SecurityProperties securityProperties, SecurePart.Modifier encryptionModifier,
+                boolean encryptedHeader, List<ComparableNamespace>[] namespaceList,
+                List<ComparableAttribute>[] attributeList,
+                DecryptInputProcessor decryptInputProcessor
+        ) {
+            super(securityProperties);
+            getAfterProcessors().add(decryptInputProcessor);
+            this.encryptionModifier = encryptionModifier;
+            rootElementProcessed = encryptionModifier != SecurePart.Modifier.Element;
+            this.encryptedHeader = encryptedHeader;
+            for (int i = 0; i < namespaceList.length; i++) {
+                List<ComparableNamespace> namespaces = namespaceList[i];
+                nsStack.push(namespaces);
+            }
+            for (int i = 0; i < attributeList.length; i++) {
+                List<ComparableAttribute> attributes = attributeList[i];
+                attrStack.push(attributes);
+            }
+        }
+
+        public void setXmlEventReader(XMLEventReader xmlEventReader) {
+            this.xmlEventReader = xmlEventReader;
+        }
+
+        @Override
+        public XMLEvent processNextHeaderEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+            return processEvent(inputProcessorChain, true);
+        }
+
+        @Override
+        public XMLEvent processNextEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, WSSecurityException {
+            return processEvent(inputProcessorChain, false);
+        }
+
+        private XMLEvent processEvent(InputProcessorChain inputProcessorChain, boolean headerEvent) throws XMLStreamException, WSSecurityException {
+            //did a execption occur during decryption in the decryption thread?
+            testAndThrowUncaughtException();
+            //here we request the next XMLEvent from the decryption thread
+            //instead from the processor-chain as we normally would do
+            XMLEvent xmlEvent = xmlEventReader.nextEvent();
+
+            if (xmlEvent.isStartElement()) {
+                documentLevel++;
+
+                inputProcessorChain.getDocumentContext().addPathElement(xmlEvent.asStartElement().getName());
+
+                if (!rootElementProcessed) {
+                    //fire a SecurityEvent:
+                    if (inputProcessorChain.getDocumentContext().getDocumentLevel() == 3
+                            && inputProcessorChain.getDocumentContext().isInSOAPHeader()) {
+                        EncryptedPartSecurityEvent encryptedPartSecurityEvent =
+                                new EncryptedPartSecurityEvent(SecurityEvent.Event.EncryptedPart, false);
+                        encryptedPartSecurityEvent.setElement(xmlEvent.asStartElement().getName());
+                        inputProcessorChain.getSecurityContext().registerSecurityEvent(encryptedPartSecurityEvent);
+                    } else {
+                        EncryptedElementSecurityEvent encryptedElementSecurityEvent =
+                                new EncryptedElementSecurityEvent(SecurityEvent.Event.EncryptedElement, false);
+                        encryptedElementSecurityEvent.setElement(xmlEvent.asStartElement().getName());
+                        inputProcessorChain.getSecurityContext().registerSecurityEvent(encryptedElementSecurityEvent);
+                    }
+
+                    rootElementProcessed = true;
+                }
+
+            } else if (xmlEvent.isEndElement()) {
+
+                if (xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().equals(wrapperElementName)) {
+                    //correct path and skip EndElements:
+                    InputProcessorChain subInputProcessorChain = inputProcessorChain.createSubChain(this);
+
+                    //skip EncryptedHeader Element when we processed it.
+                    QName endElement;
+                    if (encryptedHeader) {
+                        subInputProcessorChain.getDocumentContext().addPathElement(Constants.TAG_wsse11_EncryptedHeader);
+                        endElement = Constants.TAG_wsse11_EncryptedHeader;
+                    } else {
+                        endElement = Constants.TAG_xenc_EncryptedData;
+                    }
+                    subInputProcessorChain.getDocumentContext().addPathElement(Constants.TAG_xenc_EncryptedData);
+                    subInputProcessorChain.getDocumentContext().addPathElement(Constants.TAG_xenc_CipherData);
+
+                    //read and discard XMLEvents until the EncryptedData structure
+                    XMLEvent endEvent;
+                    do {
+                        subInputProcessorChain.reset();
+                        if (headerEvent) {
+                            endEvent = subInputProcessorChain.processHeaderEvent();
+                        } else {
+                            endEvent = subInputProcessorChain.processEvent();
+                        }
+                    }
+                    while (!(endEvent.isEndElement() && endEvent.asEndElement().getName().equals(endElement)));
+
+                    inputProcessorChain.getDocumentContext().unsetIsInEncryptedContent();
+
+                    //...fetch the next (unencrypted) event
+                    if (headerEvent) {
+                        xmlEvent = inputProcessorChain.processHeaderEvent();
+                    } else {
+                        xmlEvent = inputProcessorChain.processEvent();
+                    }
+
+                    inputProcessorChain.removeProcessor(this);
+                }
+
+                if (documentLevel > 0) {
+                    inputProcessorChain.getDocumentContext().removePathElement();
+                }
+
+                documentLevel--;
+            }
+
+            if (!(xmlEvent instanceof XMLEventNS)) {
+                xmlEvent = Utils.createXMLEventNS(xmlEvent, nsStack, attrStack);
+            }
+            return xmlEvent;
+        }
+
+        private Throwable thrownException;
+
+        public void uncaughtException(Thread t, Throwable e) {
+            this.thrownException = e;
+        }
+
+        private void testAndThrowUncaughtException() throws XMLStreamException {
+            if (this.thrownException != null) {
+                if (this.thrownException instanceof UncheckedWSSecurityException) {
+                    UncheckedWSSecurityException uxse = (UncheckedWSSecurityException) this.thrownException;
+                    throw new XMLStreamException(uxse.getCause());
+                } else {
+                    throw new XMLStreamException(this.thrownException.getCause());
+                }
+            }
+        }
+    }
+
+    /**
+     * The DecryptionThread handles encrypted XML-Parts
+     */
+    class DecryptionThread implements Runnable {
+
+        private InputProcessorChain inputProcessorChain;
+        private boolean header;
+        private XMLEventNS startXMLElement;
+        private PipedOutputStream pipedOutputStream;
+        private PipedInputStream pipedInputStream;
+        private Cipher symmetricCipher;
+        private Key secretKey;
+
+        public DecryptionThread(InputProcessorChain inputProcessorChain, boolean header,
+                                EncryptedDataType encryptedDataType, KeyInfoType keyInfoType, XMLEventNS startXMLElement) throws XMLStreamException, WSSecurityException {
+
+            this.inputProcessorChain = inputProcessorChain;
+            this.header = header;
+            this.startXMLElement = startXMLElement;
+
+            final String algorithmURI = encryptedDataType.getEncryptionMethod().getAlgorithm();
+
+            //retrieve the securityToken which must be used for decryption
+            SecurityToken securityToken = SecurityTokenFactory.newInstance().getSecurityToken(
+                    keyInfoType, getSecurityProperties().getDecryptionCrypto(),
+                    getSecurityProperties().getCallbackHandler(), inputProcessorChain.getSecurityContext(), this);
+
+            secretKey = securityToken.getSecretKey(algorithmURI, Constants.KeyUsage.Enc);
+
+            try {
+                AlgorithmType syncEncAlgo = JCEAlgorithmMapper.getAlgorithmMapping(algorithmURI);
+                symmetricCipher = Cipher.getInstance(syncEncAlgo.getJCEName(), syncEncAlgo.getJCEProvider());
+                //we have to defer the initialization of the cipher until we can extract the IV...
+            } catch (NoSuchAlgorithmException e) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "unsupportedKeyTransp",
+                        e, "No such algorithm: " + algorithmURI
+                );
+            } catch (NoSuchPaddingException e) {
+                throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "unsupportedKeyTransp",
+                        e, "No such padding: " + algorithmURI
+                );
+            } catch (NoSuchProviderException e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noSecProvider", e);
+            }
+
+            //fire an AlgorithmSuiteSecurityEvent
+            /*AlgorithmSuiteSecurityEvent algorithmSuiteSecurityEvent = new AlgorithmSuiteSecurityEvent(SecurityEvent.Event.AlgorithmSuite);
+            algorithmSuiteSecurityEvent.setAlgorithmURI(algorithmURI);
+            algorithmSuiteSecurityEvent.setKeyUsage(Constants.KeyUsage.Enc);
+            inputProcessorChain.getSecurityContext().registerSecurityEvent(algorithmSuiteSecurityEvent);*/
+
+            //prepare the piped streams and connect them:
+            //5 * 8192 seems to be a fine value
+            pipedInputStream = new PipedInputStream(40960);
+            try {
+                pipedOutputStream = new PipedOutputStream(pipedInputStream);
+            } catch (IOException e) {
+                throw new XMLStreamException(e);
+            }
+        }
+
+        public PipedInputStream getPipedInputStream() {
+            return pipedInputStream;
+        }
+
+        private XMLEvent processNextEvent() throws WSSecurityException, XMLStreamException {
+            inputProcessorChain.reset();
+            if (header) {
+                return inputProcessorChain.processHeaderEvent();
+            } else {
+                return inputProcessorChain.processEvent();
+            }
+        }
+
+        public void run() {
+
+            try {
+                //temporary writer to write the dummy wrapper element with all namespaces in the current scope
+                //spec says (4.2): "The cleartext octet sequence obtained in step 3 is interpreted as UTF-8 encoded character data."
+                BufferedWriter tempBufferedWriter = new BufferedWriter(
+                        new OutputStreamWriter(
+                                pipedOutputStream,
+                                "UTF-8"
+                        )
+                );
+
+                tempBufferedWriter.write('<');
+                tempBufferedWriter.write(wrapperElementName.getPrefix());
+                tempBufferedWriter.write(':');
+                tempBufferedWriter.write(wrapperElementName.getLocalPart());
+                tempBufferedWriter.write(' ');
+                tempBufferedWriter.write("xmlns:");
+                tempBufferedWriter.write(wrapperElementName.getPrefix());
+                tempBufferedWriter.write("=\"");
+                tempBufferedWriter.write(wrapperElementName.getNamespaceURI());
+                tempBufferedWriter.write('\"');
+
+                //apply all namespaces from current scope to get a valid documentfragment:
+                List<ComparableNamespace> comparableNamespacesToApply = new LinkedList<ComparableNamespace>();
+                List<ComparableNamespace>[] comparableNamespaceList = startXMLElement.getNamespaceList();
+                for (int i = 0; i < comparableNamespaceList.length; i++) {
+                    List<ComparableNamespace> comparableNamespaces = comparableNamespaceList[i];
+                    Iterator<ComparableNamespace> comparableNamespaceIterator = comparableNamespaces.iterator();
+                    while (comparableNamespaceIterator.hasNext()) {
+                        ComparableNamespace comparableNamespace = comparableNamespaceIterator.next();
+                        if (!comparableNamespacesToApply.contains(comparableNamespace)) {
+                            comparableNamespacesToApply.add(comparableNamespace);
+                        }
+                    }
+                }
+                Iterator<ComparableNamespace> comparableNamespaceIterator = comparableNamespacesToApply.iterator();
+                while (comparableNamespaceIterator.hasNext()) {
+                    ComparableNamespace comparableNamespace = comparableNamespaceIterator.next();
+                    tempBufferedWriter.write(' ');
+                    tempBufferedWriter.write(comparableNamespace.toString());
+                }
+
+                tempBufferedWriter.write('>');
+                //calling flush after every piece to prevent data salad...
+                tempBufferedWriter.flush();
+
+                IVSplittingOutputStream ivSplittingOutputStream = new IVSplittingOutputStream(
+                        new CipherOutputStream(new FilterOutputStream(pipedOutputStream) {
+
+                            @Override
+                            public void write(int b) throws IOException {
+                                out.write(b);
+                            }
+
+                            @Override
+                            public void write(byte[] b) throws IOException {
+                                out.write(b);
+                            }
+
+                            @Override
+                            public void write(byte[] b, int off, int len) throws IOException {
+                                out.write(b, off, len);
+                            }
+
+                            @Override
+                            public void close() throws IOException {
+                                //we overwrite the close method and don't delegate close. Close must be done separately.
+                                //The reason behind this is the Base64DecoderStream which does the final on close() but after
+                                //that we have to write our dummy end tag
+                                //just calling flush here, seems to be fine
+                                out.flush();
+                            }
+                        }, symmetricCipher),
+                        symmetricCipher, secretKey);
+                //buffering seems not to help
+                //bufferedOutputStream = new BufferedOutputStream(new Base64OutputStream(ivSplittingOutputStream, false), 8192 * 5);
+                ReplaceableOuputStream replaceableOuputStream = new ReplaceableOuputStream(ivSplittingOutputStream);
+                OutputStream decryptOutputStream = new Base64OutputStream(replaceableOuputStream, false);
+                ivSplittingOutputStream.setParentOutputStream(replaceableOuputStream);
+
+                //read the encrypted data from the stream until an end-element occurs and write then
+                //to the decrypter-stream
+                boolean finished = false;
+                while (!finished) {
+                    XMLEvent xmlEvent = processNextEvent();
+
+                    switch (xmlEvent.getEventType()) {
+                        case XMLStreamConstants.END_ELEMENT:
+                            //this must be the CipherValue EndElement.
+                            finished = true;
+                            break;
+                        case XMLStreamConstants.CHARACTERS:
+                            decryptOutputStream.write(xmlEvent.asCharacters().getData().getBytes(inputProcessorChain.getDocumentContext().getEncoding()));
+                            break;
+                        default:
+                            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, "unexpectedXMLEvent", Utils.getXMLEventAsString(xmlEvent));
+                    }
+                }
+
+                //close to get Cipher.doFinal() called
+                decryptOutputStream.close();
+
+                //close the dummy wrapper element:
+                tempBufferedWriter.write("</");
+                tempBufferedWriter.write(wrapperElementName.getPrefix());
+                tempBufferedWriter.write(':');
+                tempBufferedWriter.write(wrapperElementName.getLocalPart());
+                tempBufferedWriter.write('>');
+                //real close of the stream
+                tempBufferedWriter.close();
+
+                logger.debug("Decryption thread finished");
+
+            } catch (Exception e) {
+                throw new UncheckedWSSecurityException(e);
+            }
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/input/DecryptInputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision



Mime
View raw message