You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2014/02/12 18:04:43 UTC

svn commit: r1567683 - in /webservices/wss4j/trunk: ws-security-dom/src/main/java/org/apache/wss4j/dom/action/ ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/ ws-security-dom/src/test/java/org/apache/wss4j/dom/message/ ws-security-stax/src/...

Author: coheigea
Date: Wed Feb 12 17:04:42 2014
New Revision: 1567683

URL: http://svn.apache.org/r1567683
Log:
Add the ability to use both derived signature and encryption

Added:
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/AbstractDerivedAction.java
Modified:
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionDerivedAction.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/SignatureDerivedAction.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java
    webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/DerivedKeyActionTest.java
    webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/DerivedKeyTokenTest.java

Added: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/AbstractDerivedAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/AbstractDerivedAction.java?rev=1567683&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/AbstractDerivedAction.java (added)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/AbstractDerivedAction.java Wed Feb 12 17:04:42 2014
@@ -0,0 +1,45 @@
+/**
+ * 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.apache.wss4j.dom.action;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.handler.RequestData;
+
+public abstract class AbstractDerivedAction {
+    
+    protected Node findPlaceToInsertDKT(RequestData reqData) {
+        Element secHeader = reqData.getSecHeader().getSecurityHeader();
+        Node firstChild = secHeader.getFirstChild();
+        while (firstChild != null) {
+            if (firstChild instanceof Element && 
+                WSConstants.ENC_NS.equals(((Element)firstChild).getNamespaceURI())
+                && "EncryptedKey".equals(((Element)firstChild).getLocalName())
+                && firstChild.getNextSibling() != null) {
+                return firstChild.getNextSibling();
+            }
+            firstChild = firstChild.getNextSibling();
+        }
+        return null;
+    }
+
+}

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionDerivedAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionDerivedAction.java?rev=1567683&r1=1567682&r2=1567683&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionDerivedAction.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionDerivedAction.java Wed Feb 12 17:04:42 2014
@@ -39,8 +39,10 @@ import org.apache.wss4j.dom.message.toke
 import org.apache.wss4j.dom.util.WSSecurityUtil;
 import org.apache.xml.security.stax.impl.util.IDGenerator;
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 
-public class EncryptionDerivedAction implements Action {
+public class EncryptionDerivedAction extends AbstractDerivedAction implements Action {
     
     public void execute(WSHandler handler, SecurityActionToken actionToken,
                         Document doc, RequestData reqData)
@@ -85,6 +87,7 @@ public class EncryptionDerivedAction imp
         }
         
         String derivedKeyTokenReference = encryptionToken.getDerivedKeyTokenReference();
+        boolean usingExistingEncryptedKey = false;
         if ("SecurityContextToken".equals(derivedKeyTokenReference)) {
             sctId = IDGenerator.generateID("uuid:");
             if (reqData.isUse200512Namespace()) {
@@ -96,28 +99,41 @@ public class EncryptionDerivedAction imp
             wsEncrypt.setExternalKey(passwordCallback.getKey(), sctId);
             
         } else {
-            encrKeyBuilder = new WSSecEncryptedKey();
-            encrKeyBuilder.setUserInfo(encryptionToken.getUser());
-            if (encryptionToken.getDerivedKeyIdentifier() != 0) {
-                encrKeyBuilder.setKeyIdentifierType(encryptionToken.getDerivedKeyIdentifier());
+            byte[] ek = null;
+            String tokenIdentifier = null;
+            // See if a SignatureDerivedAction has already set up an EncryptedKey
+            if (reqData.getSignatureToken() != null && reqData.getSignatureToken().getKey() != null
+                && reqData.getSignatureToken().getKeyIdentifier() != null) {
+                ek = reqData.getSignatureToken().getKey();
+                tokenIdentifier = reqData.getSignatureToken().getKeyIdentifier();
+                usingExistingEncryptedKey = true;
             } else {
-                encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+                encrKeyBuilder = new WSSecEncryptedKey();
+                encrKeyBuilder.setUserInfo(encryptionToken.getUser());
+                if (encryptionToken.getDerivedKeyIdentifier() != 0) {
+                    encrKeyBuilder.setKeyIdentifierType(encryptionToken.getDerivedKeyIdentifier());
+                } else {
+                    encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+                }
+                
+                if (encryptionToken.getKeyTransportAlgorithm() != null) {
+                    encrKeyBuilder.setKeyEncAlgo(encryptionToken.getKeyTransportAlgorithm());
+                }
+                if (encryptionToken.getDigestAlgorithm() != null) {
+                    encrKeyBuilder.setDigestAlgorithm(encryptionToken.getDigestAlgorithm());
+                }
+                if (encryptionToken.getMgfAlgorithm() != null) {
+                    encrKeyBuilder.setMGFAlgorithm(encryptionToken.getMgfAlgorithm());
+                }
+                
+                encrKeyBuilder.prepare(doc, encryptionToken.getCrypto());
+
+                ek = encrKeyBuilder.getEphemeralKey();
+                tokenIdentifier = encrKeyBuilder.getId();
+                
+                reqData.getSignatureToken().setKey(ek);
+                reqData.getSignatureToken().setKeyIdentifier(tokenIdentifier);
             }
-            
-            if (encryptionToken.getKeyTransportAlgorithm() != null) {
-                encrKeyBuilder.setKeyEncAlgo(encryptionToken.getKeyTransportAlgorithm());
-            }
-            if (encryptionToken.getDigestAlgorithm() != null) {
-                encrKeyBuilder.setDigestAlgorithm(encryptionToken.getDigestAlgorithm());
-            }
-            if (encryptionToken.getMgfAlgorithm() != null) {
-                encrKeyBuilder.setMGFAlgorithm(encryptionToken.getMgfAlgorithm());
-            }
-            
-            encrKeyBuilder.prepare(doc, encryptionToken.getCrypto());
-
-            byte[] ek = encrKeyBuilder.getEphemeralKey();
-            String tokenIdentifier = encrKeyBuilder.getId();
 
             wsEncrypt.setExternalKey(ek, tokenIdentifier);
             wsEncrypt.setCustomValueType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
@@ -135,9 +151,24 @@ public class EncryptionDerivedAction imp
             }
             
             wsEncrypt.setParts(parts);
-            wsEncrypt.build(doc, reqData.getSecHeader());
+            wsEncrypt.prepare(doc);
             
-            wsEncrypt.prependDKElementToHeader(reqData.getSecHeader());
+            Element externRefList = wsEncrypt.encryptForExternalRef(null, parts);
+            
+            // Put the DerivedKeyToken Element in the right place in the security header
+            Node nextSibling = null;
+            if (usingExistingEncryptedKey) {
+                nextSibling = findPlaceToInsertDKT(reqData);
+            }
+            if (nextSibling == null) {
+                wsEncrypt.prependDKElementToHeader(reqData.getSecHeader());
+            } else {
+                reqData.getSecHeader().getSecurityHeader().insertBefore(
+                    wsEncrypt.getdktElement(), nextSibling);
+            }
+            
+            // Add the ReferenceList to the security header
+            wsEncrypt.addExternalRefElement(externRefList, reqData.getSecHeader());
             
             if (encrKeyBuilder != null) {
                 encrKeyBuilder.prependToHeader(reqData.getSecHeader());
@@ -151,5 +182,5 @@ public class EncryptionDerivedAction imp
                                           "empty", e, "Error during Encryption: ");
         }
     }
-
+    
 }

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/SignatureDerivedAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/SignatureDerivedAction.java?rev=1567683&r1=1567682&r2=1567683&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/SignatureDerivedAction.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/SignatureDerivedAction.java Wed Feb 12 17:04:42 2014
@@ -40,8 +40,9 @@ import org.apache.wss4j.dom.message.toke
 import org.apache.wss4j.dom.util.WSSecurityUtil;
 import org.apache.xml.security.stax.impl.util.IDGenerator;
 import org.w3c.dom.Document;
+import org.w3c.dom.Node;
 
-public class SignatureDerivedAction implements Action {
+public class SignatureDerivedAction extends AbstractDerivedAction implements Action {
     
     public void execute(WSHandler handler, SecurityActionToken actionToken,
                         Document doc, RequestData reqData)
@@ -88,19 +89,32 @@ public class SignatureDerivedAction impl
         }
         
         String derivedKeyTokenReference = signatureToken.getDerivedKeyTokenReference();
+        boolean usingExistingEncryptedKey = false;
         if ("EncryptedKey".equals(derivedKeyTokenReference)) {
-            encrKeyBuilder = new WSSecEncryptedKey();
-            encrKeyBuilder.setUserInfo(signatureToken.getUser());
-            if (signatureToken.getDerivedKeyIdentifier() != 0) {
-                encrKeyBuilder.setKeyIdentifierType(signatureToken.getDerivedKeyIdentifier());
+            byte[] ek = null;
+            String tokenIdentifier = null;
+            // See if an EncryptionAction has already set up an EncryptedKey
+            if (reqData.getEncryptionToken() != null && reqData.getEncryptionToken().getKey() != null
+                && reqData.getEncryptionToken().getKeyIdentifier() != null) {
+                ek = reqData.getEncryptionToken().getKey();
+                tokenIdentifier = reqData.getEncryptionToken().getKeyIdentifier();
+                usingExistingEncryptedKey = true;
             } else {
-                encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+                encrKeyBuilder = new WSSecEncryptedKey();
+                encrKeyBuilder.setUserInfo(signatureToken.getUser());
+                if (signatureToken.getDerivedKeyIdentifier() != 0) {
+                    encrKeyBuilder.setKeyIdentifierType(signatureToken.getDerivedKeyIdentifier());
+                } else {
+                    encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+                }
+                encrKeyBuilder.prepare(doc, signatureToken.getCrypto());
+    
+                ek = encrKeyBuilder.getEphemeralKey();
+                tokenIdentifier = encrKeyBuilder.getId();
+                
+                signatureToken.setKey(ek);
+                signatureToken.setKeyIdentifier(tokenIdentifier);
             }
-            encrKeyBuilder.prepare(doc, signatureToken.getCrypto());
-
-            byte[] ek = encrKeyBuilder.getEphemeralKey();
-            String tokenIdentifier = encrKeyBuilder.getId();
-            
             wsSign.setExternalKey(ek, tokenIdentifier);
             wsSign.setCustomValueType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
         } else if ("SecurityContextToken".equals(derivedKeyTokenReference)) {
@@ -148,9 +162,23 @@ public class SignatureDerivedAction impl
             }
             
             wsSign.setParts(parts);
-            wsSign.build(doc, reqData.getSecHeader());
+            wsSign.prepare(doc, reqData.getSecHeader());
             
-            wsSign.prependDKElementToHeader(reqData.getSecHeader());
+            List<javax.xml.crypto.dsig.Reference> referenceList = 
+                wsSign.addReferencesToSign(parts, reqData.getSecHeader());
+            wsSign.computeSignature(referenceList);
+            
+            // Put the DerivedKeyToken Element in the right place in the security header
+            Node nextSibling = null;
+            if (usingExistingEncryptedKey) {
+                nextSibling = findPlaceToInsertDKT(reqData);
+            }
+            if (nextSibling == null) {
+                wsSign.prependDKElementToHeader(reqData.getSecHeader());
+            } else {
+                reqData.getSecHeader().getSecurityHeader().insertBefore(
+                    wsSign.getdktElement(), nextSibling);
+            }
             
             if (encrKeyBuilder != null) {
                 encrKeyBuilder.prependToHeader(reqData.getSecHeader());

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java?rev=1567683&r1=1567682&r2=1567683&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java Wed Feb 12 17:04:42 2014
@@ -57,7 +57,7 @@ public class RequestData {
     private Object msgContext;
     private SOAPConstants soapConstants;
     private String actor;
-    private String username ;
+    private String username;
     private String pwType = WSConstants.PASSWORD_DIGEST; // Make this the default when no password type is given.
     private Crypto sigVerCrypto;
     private Crypto decCrypto;

Modified: webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/DerivedKeyActionTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/DerivedKeyActionTest.java?rev=1567683&r1=1567682&r2=1567683&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/DerivedKeyActionTest.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/DerivedKeyActionTest.java Wed Feb 12 17:04:42 2014
@@ -19,6 +19,7 @@
 
 package org.apache.wss4j.dom.message;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -398,6 +399,78 @@ public class DerivedKeyActionTest extend
         
         verify(doc, secretKeyCallbackHandler);
     }
+    
+    @org.junit.Test
+    public void testSignatureEncryptionThumbprintSHA1() throws Exception {
+        final WSSConfig cfg = WSSConfig.getNewInstance();
+        final RequestData reqData = new RequestData();
+        reqData.setWssConfig(cfg);
+        reqData.setUsername("wss40");
+        
+        java.util.Map<String, Object> config = new java.util.TreeMap<String, Object>();
+        config.put(WSHandlerConstants.SIG_PROP_FILE, "wss40.properties");
+        config.put(WSHandlerConstants.ENC_PROP_FILE, "wss40.properties");
+        config.put(WSHandlerConstants.PW_CALLBACK_REF, callbackHandler);
+        config.put(WSHandlerConstants.DERIVED_TOKEN_REFERENCE, "EncryptedKey");
+        config.put(WSHandlerConstants.DERIVED_TOKEN_KEY_ID, "Thumbprint");
+        reqData.setMsgContext(config);
+        
+        final Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        CustomHandler handler = new CustomHandler();
+        List<HandlerAction> actions = new ArrayList<HandlerAction>();
+        actions.add(new HandlerAction(WSConstants.DKT_SIGN));
+        actions.add(new HandlerAction(WSConstants.DKT_ENCR));
+        handler.send(
+            doc, 
+            reqData, 
+            actions,
+            true
+        );
+        String outputString = 
+            XMLUtils.PrettyDocumentToString(doc);
+        Assert.assertTrue(outputString.contains(ConversationConstants.WSC_NS_05_12));
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(outputString);
+        }
+        
+        verify(doc);
+    }
+    
+    @org.junit.Test
+    public void testEncryptionSignatureThumbprintSHA1() throws Exception {
+        final WSSConfig cfg = WSSConfig.getNewInstance();
+        final RequestData reqData = new RequestData();
+        reqData.setWssConfig(cfg);
+        reqData.setUsername("wss40");
+        
+        java.util.Map<String, Object> config = new java.util.TreeMap<String, Object>();
+        config.put(WSHandlerConstants.SIG_PROP_FILE, "wss40.properties");
+        config.put(WSHandlerConstants.ENC_PROP_FILE, "wss40.properties");
+        config.put(WSHandlerConstants.PW_CALLBACK_REF, callbackHandler);
+        config.put(WSHandlerConstants.DERIVED_TOKEN_REFERENCE, "EncryptedKey");
+        config.put(WSHandlerConstants.DERIVED_TOKEN_KEY_ID, "Thumbprint");
+        reqData.setMsgContext(config);
+        
+        final Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        CustomHandler handler = new CustomHandler();
+        List<HandlerAction> actions = new ArrayList<HandlerAction>();
+        actions.add(new HandlerAction(WSConstants.DKT_ENCR));
+        actions.add(new HandlerAction(WSConstants.DKT_SIGN));
+        handler.send(
+            doc, 
+            reqData, 
+            actions,
+            true
+        );
+        String outputString = 
+            XMLUtils.PrettyDocumentToString(doc);
+        Assert.assertTrue(outputString.contains(ConversationConstants.WSC_NS_05_12));
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(outputString);
+        }
+        
+        verify(doc);
+    }
 
     private List<WSSecurityEngineResult> verify(Document doc) throws Exception {
         return verify(doc, callbackHandler);

Modified: webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/DerivedKeyTokenTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/DerivedKeyTokenTest.java?rev=1567683&r1=1567682&r2=1567683&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/DerivedKeyTokenTest.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/DerivedKeyTokenTest.java Wed Feb 12 17:04:42 2014
@@ -1036,4 +1036,48 @@ public class DerivedKeyTokenTest extends
         }
     }
     
+    @Test
+    public void testEncryptSignatureInboundAction() throws Exception {
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        {
+            InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
+            String action = WSHandlerConstants.SIGNATURE_DERIVED + " " + WSHandlerConstants.ENCRYPT_DERIVED;
+            
+            Properties properties = new Properties();
+            properties.put(WSHandlerConstants.DERIVED_TOKEN_REFERENCE, "EncryptedKey");
+            if (version == ConversationConstants.VERSION_05_02) {
+                properties.put(WSHandlerConstants.USE_2005_12_NAMESPACE, "false");
+            }
+            properties.put(WSHandlerConstants.USER, "receiver");
+            properties.put(WSHandlerConstants.SIG_ALGO, 
+                           "http://www.w3.org/2000/09/xmldsig#hmac-sha1");
+            Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
+
+            //some test that we can really sure we get what we want from WSS4J
+            NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
+            Assert.assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_soap11_Body.getLocalPart());
+
+            javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
+            transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
+        }
+    
+        {
+            WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+            securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
+            securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
+            securityProperties.setCallbackHandler(new CallbackHandlerImpl());
+            InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
+            XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
+
+            Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
+
+            NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
+            Assert.assertEquals(nodeList.getLength(), 1);
+
+            nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
+            Assert.assertEquals(nodeList.getLength(), 0);
+        }
+    }
 }