You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by gi...@apache.org on 2012/09/16 15:06:43 UTC

svn commit: r1385257 - in /santuario/xml-security-java/trunk/src: main/java/org/apache/xml/security/stax/ext/ main/java/org/apache/xml/security/stax/impl/ main/java/org/apache/xml/security/stax/impl/processor/output/ test/java/org/apache/xml/security/t...

Author: giger
Date: Sun Sep 16 13:06:42 2012
New Revision: 1385257

URL: http://svn.apache.org/viewvc?rev=1385257&view=rev
Log:
SANTUARIO-341 - Support C14N PrefixList for outbound signature in stax code 

Modified:
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityUtils.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/SignaturePartDef.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureEndingOutputProcessor.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureOutputProcessor.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java
    santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationTest.java

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java?rev=1385257&r1=1385256&r2=1385257&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java Sun Sep 16 13:06:42 2012
@@ -155,7 +155,7 @@ public abstract class AbstractOutputProc
         outputAsEvent(outputProcessorChain, xmlSecStartElement);
     }
 
-    public void createStartElementAndOutputAsEvent(
+    public XMLSecStartElement createStartElementAndOutputAsEvent(
             OutputProcessorChain outputProcessorChain, QName element,
             boolean outputLocalNs, List<XMLSecAttribute> attributes) throws XMLStreamException, XMLSecurityException {
 
@@ -186,6 +186,7 @@ public abstract class AbstractOutputProc
         XMLSecStartElement xmlSecStartElement
                 = XMLSecEventFactory.createXmlSecStartElement(element, attributes, comparableNamespaces);
         outputAsEvent(outputProcessorChain, xmlSecStartElement);
+        return xmlSecStartElement;
     }
 
     public XMLSecEndElement createEndElement(QName element) {

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java?rev=1385257&r1=1385256&r2=1385257&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java Sun Sep 16 13:06:42 2012
@@ -198,6 +198,7 @@ public class XMLSecurityProperties {
     private boolean useSingleCert = true;
     private Key signatureKey;
     private X509Certificate[] signatureCerts;
+    private boolean addExcC14NInclusivePrefixes = false;
 
     public X509Certificate[] getSignatureCerts() {
         return signatureCerts;
@@ -248,6 +249,14 @@ public class XMLSecurityProperties {
         this.useSingleCert = useSingleCert;
     }
 
+    public boolean isAddExcC14NInclusivePrefixes() {
+        return addExcC14NInclusivePrefixes;
+    }
+
+    public void setAddExcC14NInclusivePrefixes(boolean addExcC14NInclusivePrefixes) {
+        this.addExcC14NInclusivePrefixes = addExcC14NInclusivePrefixes;
+    }
+
     /**
      * Returns the actual set actions
      *

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityUtils.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityUtils.java?rev=1385257&r1=1385256&r2=1385257&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityUtils.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityUtils.java Sun Sep 16 13:06:42 2012
@@ -23,6 +23,8 @@ import org.apache.xml.security.keys.cont
 import org.apache.xml.security.stax.config.TransformerAlgorithmMapper;
 import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
+import org.apache.xml.security.stax.ext.stax.XMLSecNamespace;
+import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
 import org.apache.xml.security.stax.impl.algorithms.ECDSAUtils;
 
 import javax.security.auth.callback.Callback;
@@ -42,9 +44,7 @@ import java.security.cert.X509Certificat
 import java.security.interfaces.DSAPublicKey;
 import java.security.interfaces.ECPublicKey;
 import java.security.interfaces.RSAPublicKey;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * @author $Author$
@@ -309,4 +309,49 @@ public class XMLSecurityUtils {
         
         abstractOutputProcessor.createEndElementAndOutputAsEvent(outputProcessorChain, XMLSecurityConstants.TAG_dsig_X509Data);
     }
+
+    public static Set<String> getExcC14NInclusiveNamespacePrefixes(XMLSecStartElement xmlSecStartElement, boolean excludeVisible) {
+
+        if (xmlSecStartElement == null) {
+            return Collections.emptySet();
+        }
+        Set<String> prefixes = new HashSet<String>();
+
+        XMLSecStartElement parentXMXmlSecStartElement = xmlSecStartElement.getParentXMLSecStartElement();
+        if (parentXMXmlSecStartElement != null) {
+            List<XMLSecNamespace> onElementDeclaredNamespaces = parentXMXmlSecStartElement.getOnElementDeclaredNamespaces();
+            List<XMLSecNamespace> xmlSecNamespaces = new ArrayList<XMLSecNamespace>();
+            parentXMXmlSecStartElement.getNamespacesFromCurrentScope(xmlSecNamespaces);
+            xmlSecNamespaces = xmlSecNamespaces.subList(0, xmlSecNamespaces.size() - onElementDeclaredNamespaces.size());
+
+            //reverse iteration -> From current element namespaces to parent namespaces
+            for (int i = xmlSecNamespaces.size() - 1; i >= 0; i--) {
+                XMLSecNamespace xmlSecNamespace = xmlSecNamespaces.get(i);
+                String prefix = xmlSecNamespace.getPrefix();
+                if (prefix == null || prefix.isEmpty()) {
+                    prefixes.add("#default");
+                } else {
+                    prefixes.add(xmlSecNamespace.getPrefix());
+                }
+            }
+
+            if (excludeVisible) {
+                for (int i = 0; i < onElementDeclaredNamespaces.size(); i++) {
+                    XMLSecNamespace xmlSecNamespace = onElementDeclaredNamespaces.get(i);
+                    String prefix = xmlSecNamespace.getPrefix();
+                    if (prefix == null || prefix.isEmpty()) {
+                        prefixes.remove("#default");
+                    } else {
+                        prefixes.remove(prefix);
+                    }
+                }
+                if (xmlSecStartElement.getName().getPrefix() == null || xmlSecStartElement.getName().getPrefix().isEmpty()) {
+                    prefixes.remove("#default");
+                } else {
+                    prefixes.remove(xmlSecStartElement.getName().getPrefix());
+                }
+            }
+        }
+        return prefixes;
+    }
 }

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/SignaturePartDef.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/SignaturePartDef.java?rev=1385257&r1=1385256&r2=1385257&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/SignaturePartDef.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/SignaturePartDef.java Sun Sep 16 13:06:42 2012
@@ -30,7 +30,8 @@ public class SignaturePartDef {
     private String digestValue;
     private String[] transforms;
     private String digestAlgo;
-    private String inclusiveNamespaces;
+    private String inclusiveNamespacesPrefixes;
+    private boolean excludeVisibleC14Nprefixes;
     private boolean externalResource;
     private boolean generateXPointer;
 
@@ -66,12 +67,20 @@ public class SignaturePartDef {
         this.digestAlgo = digestAlgo;
     }
 
-    public String getInclusiveNamespaces() {
-        return inclusiveNamespaces;
+    public String getInclusiveNamespacesPrefixes() {
+        return inclusiveNamespacesPrefixes;
     }
 
-    public void setInclusiveNamespaces(String inclusiveNamespaces) {
-        this.inclusiveNamespaces = inclusiveNamespaces;
+    public void setInclusiveNamespacesPrefixes(String inclusiveNamespacesPrefixes) {
+        this.inclusiveNamespacesPrefixes = inclusiveNamespacesPrefixes;
+    }
+
+    public boolean isExcludeVisibleC14Nprefixes() {
+        return excludeVisibleC14Nprefixes;
+    }
+
+    public void setExcludeVisibleC14Nprefixes(boolean excludeVisibleC14Nprefixes) {
+        this.excludeVisibleC14Nprefixes = excludeVisibleC14Nprefixes;
     }
 
     public boolean isExternalResource() {

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureEndingOutputProcessor.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureEndingOutputProcessor.java?rev=1385257&r1=1385256&r2=1385257&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureEndingOutputProcessor.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureEndingOutputProcessor.java Sun Sep 16 13:06:42 2012
@@ -22,6 +22,7 @@ import org.apache.commons.codec.binary.B
 import org.apache.xml.security.stax.ext.*;
 import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
+import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
 import org.apache.xml.security.stax.impl.SignaturePartDef;
 import org.apache.xml.security.stax.impl.algorithms.SignatureAlgorithm;
 import org.apache.xml.security.stax.impl.algorithms.SignatureAlgorithmFactory;
@@ -39,6 +40,7 @@ import java.security.NoSuchProviderExcep
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author $Author$
@@ -95,7 +97,7 @@ public abstract class AbstractSignatureE
 
         List<XMLSecAttribute> attributes = new ArrayList<XMLSecAttribute>(1);
         attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Id, IDGenerator.generateID(null)));
-        createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Signature, true, attributes);
+        XMLSecStartElement signatureElement = createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Signature, true, attributes);
 
         SignatureAlgorithm signatureAlgorithm;
 
@@ -122,13 +124,21 @@ public abstract class AbstractSignatureE
 
         signatureAlgorithm.engineInitSign(wrappingSecurityToken.getSecretKey(getSecurityProperties().getSignatureAlgorithm()));
 
-        SignedInfoProcessor signedInfoProcessor = newSignedInfoProcessor(signatureAlgorithm, subOutputProcessorChain);
-
+        SignedInfoProcessor signedInfoProcessor = newSignedInfoProcessor(signatureAlgorithm, signatureElement, subOutputProcessorChain);
         createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_SignedInfo, false, null);
 
         attributes = new ArrayList<XMLSecAttribute>(1);
-        attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, getSecurityProperties().getSignatureCanonicalizationAlgorithm()));
+        final String signatureCanonicalizationAlgorithm = getSecurityProperties().getSignatureCanonicalizationAlgorithm();
+        attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, signatureCanonicalizationAlgorithm));
         createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_CanonicalizationMethod, false, attributes);
+
+        if (getSecurityProperties().isAddExcC14NInclusivePrefixes() && XMLSecurityConstants.NS_C14N_EXCL.equals(signatureCanonicalizationAlgorithm)) {
+            attributes = new ArrayList<XMLSecAttribute>(1);
+            attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_PrefixList, signedInfoProcessor.getInclusiveNamespacePrefixes()));
+            createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces, true, attributes);
+            createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces);
+        }
+
         createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_CanonicalizationMethod);
 
         attributes = new ArrayList<XMLSecAttribute>(1);
@@ -178,15 +188,9 @@ public abstract class AbstractSignatureE
         createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Signature);
     }
 
-    protected SignedInfoProcessor newSignedInfoProcessor(SignatureAlgorithm signatureAlgorithm, OutputProcessorChain outputProcessorChain)
-            throws XMLSecurityException {
-        SignedInfoProcessor signedInfoProcessor = new SignedInfoProcessor(signatureAlgorithm);
-        signedInfoProcessor.setXMLSecurityProperties(getSecurityProperties());
-        signedInfoProcessor.setAction(getAction());
-        signedInfoProcessor.addAfterProcessor(AbstractSignatureEndingOutputProcessor.class.getName());
-        signedInfoProcessor.init(outputProcessorChain);
-        return signedInfoProcessor;
-    }
+    protected abstract SignedInfoProcessor newSignedInfoProcessor(
+            SignatureAlgorithm signatureAlgorithm, XMLSecStartElement xmlSecStartElement, OutputProcessorChain outputProcessorChain)
+            throws XMLSecurityException;
 
     protected abstract void createTransformsStructureForSignature(
             OutputProcessorChain subOutputProcessorChain,
@@ -204,11 +208,15 @@ public abstract class AbstractSignatureE
         private OutputStream bufferedSignerOutputStream;
         private Transformer transformer;
         private byte[] signatureValue = null;
+        private String inclusiveNamespacePrefixes = null;
         private SignatureAlgorithm signatureAlgorithm;
+        private XMLSecStartElement xmlSecStartElement;
 
-        public SignedInfoProcessor(SignatureAlgorithm signatureAlgorithm) throws XMLSecurityException {
+        public SignedInfoProcessor(SignatureAlgorithm signatureAlgorithm, XMLSecStartElement xmlSecStartElement)
+                throws XMLSecurityException {
             super();
             this.signatureAlgorithm = signatureAlgorithm;
+            this.xmlSecStartElement = xmlSecStartElement;
         }
 
         @Override
@@ -217,9 +225,28 @@ public abstract class AbstractSignatureE
             this.signerOutputStream = new SignerOutputStream(this.signatureAlgorithm);
             this.bufferedSignerOutputStream = new BufferedOutputStream(this.signerOutputStream);
 
+            final String canonicalizationAlgorithm = getSecurityProperties().getSignatureCanonicalizationAlgorithm();
+
+            List<String> inclusiveNamespacePrefixes = null;
+            if (getSecurityProperties().isAddExcC14NInclusivePrefixes() &&
+                    XMLSecurityConstants.NS_C14N_EXCL.equals(canonicalizationAlgorithm)) {
+
+                Set<String> prefixSet = XMLSecurityUtils.getExcC14NInclusiveNamespacePrefixes(xmlSecStartElement, false);
+                StringBuilder prefixes = new StringBuilder();
+                for (Iterator<String> iterator = prefixSet.iterator(); iterator.hasNext(); ) {
+                    String prefix = iterator.next();
+                    if (prefixes.length() != 0) {
+                        prefixes.append(" ");
+                    }
+                    prefixes.append(prefix);
+                }
+                inclusiveNamespacePrefixes = new ArrayList<String>(prefixSet);
+                this.inclusiveNamespacePrefixes = prefixes.toString();
+            }
+
             try {
-                this.transformer = XMLSecurityUtils.getTransformer(null, this.bufferedSignerOutputStream,
-                        getSecurityProperties().getSignatureCanonicalizationAlgorithm(), XMLSecurityConstants.DIRECTION.OUT);
+                this.transformer = XMLSecurityUtils.getTransformer(inclusiveNamespacePrefixes, this.bufferedSignerOutputStream,
+                        canonicalizationAlgorithm, XMLSecurityConstants.DIRECTION.OUT);
             } catch (NoSuchMethodException e) {
                 throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
             } catch (InstantiationException e) {
@@ -249,6 +276,10 @@ public abstract class AbstractSignatureE
             }
         }
 
+        public String getInclusiveNamespacePrefixes() {
+            return inclusiveNamespacePrefixes;
+        }
+
         @Override
         public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain)
                 throws XMLStreamException, XMLSecurityException {

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureOutputProcessor.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureOutputProcessor.java?rev=1385257&r1=1385256&r2=1385257&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureOutputProcessor.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureOutputProcessor.java Sun Sep 16 13:06:42 2012
@@ -26,12 +26,12 @@ import org.apache.xml.security.stax.conf
 import org.apache.xml.security.stax.config.ResourceResolverMapper;
 import org.apache.xml.security.stax.ext.*;
 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
+import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
 import org.apache.xml.security.stax.impl.SignaturePartDef;
 import org.apache.xml.security.stax.impl.transformer.TransformIdentity;
 import org.apache.xml.security.stax.impl.util.DigestOutputStream;
 import org.xmlsecurity.ns.configuration.AlgorithmType;
 
-import javax.xml.namespace.QName;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import java.io.BufferedOutputStream;
@@ -42,10 +42,7 @@ import java.lang.reflect.InvocationTarge
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * @author $Author$
@@ -92,9 +89,21 @@ public abstract class AbstractSignatureO
 
                 InputStream inputStream = resourceResolver.getInputStreamFromExternalReference();
 
+                SignaturePartDef signaturePartDef = new SignaturePartDef();
+                signaturePartDef.setSigRefId(externalReference);
+                signaturePartDef.setExternalResource(true);
+                signaturePartDef.setTransforms(securePart.getTransforms());
+                String digestMethod = securePart.getDigestMethod();
+                if (digestMethod == null) {
+                    digestMethod = getSecurityProperties().getSignatureDigestAlgorithm();
+                }
+                signaturePartDef.setDigestAlgo(digestMethod);
+                getSignaturePartDefList().add(signaturePartDef);
+
                 try {
                     if (securePart.getTransforms() != null) {
-                        Transformer transformer = buildTransformerChain(digestOutputStream, securePart.getTransforms());
+                        signaturePartDef.setExcludeVisibleC14Nprefixes(true);
+                        Transformer transformer = buildTransformerChain(digestOutputStream, signaturePartDef, null);
                         transformer.transform(inputStream);
                         transformer.doFinal();
                     } else {
@@ -118,17 +127,7 @@ public abstract class AbstractSignatureO
                     logger.debug("Calculated Digest: " + calculatedDigest);
                 }
 
-                SignaturePartDef signaturePartDef = new SignaturePartDef();
-                signaturePartDef.setSigRefId(externalReference);
                 signaturePartDef.setDigestValue(calculatedDigest);
-                signaturePartDef.setExternalResource(true);
-                signaturePartDef.setTransforms(securePart.getTransforms());
-                String digestMethod = securePart.getDigestMethod();
-                if (digestMethod == null) {
-                    digestMethod = getSecurityProperties().getSignatureDigestAlgorithm();
-                }
-                signaturePartDef.setDigestAlgo(digestMethod);
-                getSignaturePartDefList().add(signaturePartDef);
             }
         }
 
@@ -144,7 +143,9 @@ public abstract class AbstractSignatureO
         this.activeInternalSignatureOutputProcessor = activeInternalSignatureOutputProcessor;
     }
 
-    private DigestOutputStream createMessageDigestOutputStream(String digestAlgorithm) throws XMLSecurityException, NoSuchAlgorithmException, NoSuchProviderException {
+    private DigestOutputStream createMessageDigestOutputStream(String digestAlgorithm)
+            throws XMLSecurityException, NoSuchAlgorithmException, NoSuchProviderException {
+
         AlgorithmType algorithmType = JCEAlgorithmMapper.getAlgorithmMapping(digestAlgorithm);
         if (algorithmType == null) {
             throw new XMLSecurityException(XMLSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "unknownSignatureAlgorithm", digestAlgorithm);
@@ -158,10 +159,14 @@ public abstract class AbstractSignatureO
         return new DigestOutputStream(messageDigest);
     }
 
-    protected Transformer buildTransformerChain(OutputStream outputStream, String[] transforms)
+    protected Transformer buildTransformerChain(OutputStream outputStream,
+                                                SignaturePartDef signaturePartDef,
+                                                XMLSecStartElement xmlSecStartElement)
             throws XMLSecurityException, NoSuchMethodException, InstantiationException,
             IllegalAccessException, InvocationTargetException {
 
+        String[] transforms = signaturePartDef.getTransforms();
+
         if (transforms == null || transforms.length == 0) {
             Transformer transformer = new TransformIdentity();
             transformer.setOutputStream(outputStream);
@@ -172,12 +177,31 @@ public abstract class AbstractSignatureO
         for (int i = transforms.length - 1; i >= 0; i--) {
             String transform = transforms[i];
 
+            List<String> inclusiveNamespacePrefixes = null;
+            if (getSecurityProperties().isAddExcC14NInclusivePrefixes() &&
+                    XMLSecurityConstants.NS_C14N_EXCL.equals(transform)) {
+
+                Set<String> prefixSet = XMLSecurityUtils.getExcC14NInclusiveNamespacePrefixes(
+                        xmlSecStartElement, signaturePartDef.isExcludeVisibleC14Nprefixes()
+                );
+                StringBuilder prefixes = new StringBuilder();
+                for (Iterator<String> iterator = prefixSet.iterator(); iterator.hasNext(); ) {
+                    String prefix = iterator.next();
+                    if (prefixes.length() != 0) {
+                        prefixes.append(" ");
+                    }
+                    prefixes.append(prefix);
+                }
+                inclusiveNamespacePrefixes = new ArrayList<String>(prefixSet);
+                signaturePartDef.setInclusiveNamespacesPrefixes(prefixes.toString());
+            }
+
             if (parentTransformer != null) {
                 parentTransformer = XMLSecurityUtils.getTransformer(
                         parentTransformer, null, transform, XMLSecurityConstants.DIRECTION.OUT);
             } else {
                 parentTransformer = XMLSecurityUtils.getTransformer(
-                        null, outputStream, transform, XMLSecurityConstants.DIRECTION.OUT);
+                        inclusiveNamespacePrefixes, outputStream, transform, XMLSecurityConstants.DIRECTION.OUT);
             }
         }
         return parentTransformer;
@@ -186,19 +210,19 @@ public abstract class AbstractSignatureO
     public class InternalSignatureOutputProcessor extends AbstractOutputProcessor {
 
         private SignaturePartDef signaturePartDef;
-        private QName startElement;
+        private XMLSecStartElement xmlSecStartElement;
         private int elementCounter = 0;
 
         private OutputStream bufferedDigestOutputStream;
         private DigestOutputStream digestOutputStream;
         private Transformer transformer;
 
-        public InternalSignatureOutputProcessor(SignaturePartDef signaturePartDef, QName startElement)
+        public InternalSignatureOutputProcessor(SignaturePartDef signaturePartDef, XMLSecStartElement xmlSecStartElement)
                 throws XMLSecurityException, NoSuchProviderException, NoSuchAlgorithmException {
             super();
             this.addBeforeProcessor(InternalSignatureOutputProcessor.class.getName());
             this.signaturePartDef = signaturePartDef;
-            this.startElement = startElement;
+            this.xmlSecStartElement = xmlSecStartElement;
         }
 
         @Override
@@ -206,7 +230,7 @@ public abstract class AbstractSignatureO
             try {
                 this.digestOutputStream = createMessageDigestOutputStream(signaturePartDef.getDigestAlgo());
                 this.bufferedDigestOutputStream = new BufferedOutputStream(digestOutputStream);
-                this.transformer = buildTransformerChain(this.bufferedDigestOutputStream, signaturePartDef.getTransforms());
+                this.transformer = buildTransformerChain(this.bufferedDigestOutputStream, signaturePartDef, xmlSecStartElement);
             } catch (NoSuchMethodException e) {
                 throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILED_SIGNATURE, e);
             } catch (InstantiationException e) {
@@ -236,7 +260,9 @@ public abstract class AbstractSignatureO
                 case XMLStreamConstants.END_ELEMENT:
                     elementCounter--;
 
-                    if (elementCounter == 0 && xmlSecEvent.asEndElement().getName().equals(this.startElement)) {
+                    if (elementCounter == 0 &&
+                            xmlSecEvent.asEndElement().getName().equals(this.xmlSecStartElement.getName())) {
+
                         transformer.doFinal();
                         try {
                             bufferedDigestOutputStream.close();

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java?rev=1385257&r1=1385256&r2=1385257&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java Sun Sep 16 13:06:42 2012
@@ -31,6 +31,7 @@ import org.apache.xml.security.stax.ext.
 import org.apache.xml.security.stax.ext.XMLSecurityUtils;
 import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
+import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
 import org.apache.xml.security.stax.impl.SignaturePartDef;
 import org.apache.xml.security.stax.impl.algorithms.SignatureAlgorithm;
 import org.apache.xml.security.stax.impl.securityToken.OutboundSecurityToken;
@@ -49,8 +50,11 @@ public class XMLSignatureEndingOutputPro
     }
 
     @Override
-    protected SignedInfoProcessor newSignedInfoProcessor(SignatureAlgorithm signatureAlgorithm, OutputProcessorChain outputProcessorChain) throws XMLSecurityException {
-        this.signedInfoProcessor = new SignedInfoProcessor(signatureAlgorithm);
+    protected SignedInfoProcessor newSignedInfoProcessor(
+            SignatureAlgorithm signatureAlgorithm, XMLSecStartElement xmlSecStartElement,
+            OutputProcessorChain outputProcessorChain) throws XMLSecurityException {
+
+        this.signedInfoProcessor = new SignedInfoProcessor(signatureAlgorithm, xmlSecStartElement);
         this.signedInfoProcessor.setXMLSecurityProperties(getSecurityProperties());
         this.signedInfoProcessor.setAction(getAction());
         this.signedInfoProcessor.addAfterProcessor(XMLSignatureEndingOutputProcessor.class.getName());
@@ -120,6 +124,14 @@ public class XMLSignatureEndingOutputPro
                 List<XMLSecAttribute> attributes = new ArrayList<XMLSecAttribute>(1);
                 attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, transform));
                 createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform, false, attributes);
+
+                if (getSecurityProperties().isAddExcC14NInclusivePrefixes()) {
+                    attributes = new ArrayList<XMLSecAttribute>(1);
+                    attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_PrefixList, signaturePartDef.getInclusiveNamespacesPrefixes()));
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces, true, attributes);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces);
+                }
+
                 createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform);
             }
             createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Transforms);

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java?rev=1385257&r1=1385256&r2=1385257&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java Sun Sep 16 13:06:42 2012
@@ -74,6 +74,7 @@ public class XMLSignatureOutputProcessor
                     try {
                         SignaturePartDef signaturePartDef = new SignaturePartDef();
                         signaturePartDef.setTransforms(securePart.getTransforms());
+                        signaturePartDef.setExcludeVisibleC14Nprefixes(true);
                         String digestMethod = securePart.getDigestMethod();
                         if (digestMethod == null) {
                             digestMethod = getSecurityProperties().getSignatureDigestAlgorithm();
@@ -115,7 +116,7 @@ public class XMLSignatureOutputProcessor
                         }
 
                         getSignaturePartDefList().add(signaturePartDef);
-                        internalSignatureOutputProcessor = new InternalSignatureOutputProcessor(signaturePartDef, xmlSecStartElement.getName());
+                        internalSignatureOutputProcessor = new InternalSignatureOutputProcessor(signaturePartDef, xmlSecStartElement);
                         internalSignatureOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
                         internalSignatureOutputProcessor.setAction(getAction());
                         internalSignatureOutputProcessor.addAfterProcessor(XMLSignatureOutputProcessor.class.getName());
@@ -137,5 +138,4 @@ public class XMLSignatureOutputProcessor
         }
         outputProcessorChain.processEvent(xmlSecEvent);
     }
-
 }

Modified: santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationTest.java?rev=1385257&r1=1385256&r2=1385257&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationTest.java (original)
+++ santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureCreationTest.java Sun Sep 16 13:06:42 2012
@@ -618,6 +618,57 @@ public class SignatureCreationTest exten
     }
 
     @Test
+    public void testExcC14nInclusivePrefixes() throws Exception {
+        // Set up the Configuration
+        XMLSecurityProperties properties = new XMLSecurityProperties();
+        XMLSecurityConstants.Action[] actions =
+                new XMLSecurityConstants.Action[]{XMLSecurityConstants.SIGNATURE};
+        properties.setOutAction(actions);
+
+        // Set the key up
+        KeyStore keyStore = KeyStore.getInstance("jks");
+        keyStore.load(
+                this.getClass().getClassLoader().getResource("transmitter.jks").openStream(),
+                "default".toCharArray()
+        );
+        Key key = keyStore.getKey("transmitter", "default".toCharArray());
+        properties.setSignatureKey(key);
+        X509Certificate cert = (X509Certificate)keyStore.getCertificate("transmitter");
+        properties.setSignatureCerts(new X509Certificate[]{cert});
+
+        properties.setSignatureCanonicalizationAlgorithm(XMLSecurityConstants.NS_C14N_EXCL);
+        properties.setAddExcC14NInclusivePrefixes(true);
+
+        SecurePart securePart =
+                new SecurePart(new QName("urn:example:po", "PaymentInfo"), SecurePart.Modifier.Content);
+        properties.addSignaturePart(securePart);
+
+        OutboundXMLSec outboundXMLSec = XMLSec.getOutboundXMLSec(properties);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        XMLStreamWriter xmlStreamWriter = outboundXMLSec.processOutMessage(baos, "UTF-8");
+
+        InputStream sourceDocument =
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
+
+        XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
+        xmlStreamWriter.close();
+
+        //System.out.println("Got:\n" + new String(baos.toByteArray(), "UTF-8"));
+        Document document =
+                documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
+
+        NodeList nodeList = document.getElementsByTagNameNS(XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces.getNamespaceURI(), XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces.getLocalPart());
+        Assert.assertEquals(2, nodeList.getLength());
+        Assert.assertEquals("", ((Element)nodeList.item(0)).getAttribute(XMLSecurityConstants.ATT_NULL_PrefixList.getLocalPart()));
+        Assert.assertEquals("", ((Element)nodeList.item(1)).getAttribute(XMLSecurityConstants.ATT_NULL_PrefixList.getLocalPart()));
+
+        // Verify using DOM
+        verifyUsingDOM(document, cert, properties.getSignatureSecureParts());
+    }
+
+    @Test
     public void testSignatureCreationKeyValue() throws Exception {
         // Set up the Configuration
         XMLSecurityProperties properties = new XMLSecurityProperties();