[java-opensaml] 01/04: OSJ-230: Expose signing parameter to control ContentReference c14n ...

Brent Putman putmanb at georgetown.edu
Tue Sep 11 21:38:38 EDT 2018


This is an automated email from the git hooks/post-receive script.

putmanb pushed a commit to branch master
in repository java-opensaml.

View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=a2921ae5a69931afc98d5713f91894b3c0c958f2

commit a2921ae5a69931afc98d5713f91894b3c0c958f2
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Wed Sep 5 23:16:57 2018 -0400

    OSJ-230: Expose signing parameter to control ContentReference c14n ...
---
 .../saml/common/SAMLObjectContentReference.java    |   3 +-
 .../xmlsec/SignatureSigningConfiguration.java      |   7 +
 .../xmlsec/SignatureSigningParameters.java         |  21 +++
 .../xmlsec/signature/support/SignatureSupport.java | 147 ++++++++++++++++---
 .../TransformsConfigurableContentReference.java    |  38 +++++
 .../signature/support/URIContentReference.java     |   8 +-
 .../impl/BasicSignatureSigningConfiguration.java   |  22 +++
 .../BasicSignatureSigningParametersResolver.java   |  22 +++
 ...asicSignatureSigningParametersResolverTest.java |  31 ++++
 .../signature/support/SignatureSupportTest.java    | 162 +++++++++++++++++++++
 10 files changed, 434 insertions(+), 27 deletions(-)

diff --git a/opensaml-saml-api/src/main/java/org/opensaml/saml/common/SAMLObjectContentReference.java b/opensaml-saml-api/src/main/java/org/opensaml/saml/common/SAMLObjectContentReference.java
index 21aa5b7..6916ab9 100644
--- a/opensaml-saml-api/src/main/java/org/opensaml/saml/common/SAMLObjectContentReference.java
+++ b/opensaml-saml-api/src/main/java/org/opensaml/saml/common/SAMLObjectContentReference.java
@@ -40,6 +40,7 @@ import org.opensaml.core.xml.NamespaceManager;
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.xmlsec.signature.support.ConfigurableContentReference;
 import org.opensaml.xmlsec.signature.support.SignatureConstants;
+import org.opensaml.xmlsec.signature.support.TransformsConfigurableContentReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,7 +73,7 @@ import com.google.common.base.Strings;
  * </p>
  * 
  */
-public class SAMLObjectContentReference implements ConfigurableContentReference {
+public class SAMLObjectContentReference implements ConfigurableContentReference, TransformsConfigurableContentReference {
 
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(SAMLObjectContentReference.class);
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/SignatureSigningConfiguration.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/SignatureSigningConfiguration.java
index 60813db..0277f2d 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/SignatureSigningConfiguration.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/SignatureSigningConfiguration.java
@@ -58,6 +58,13 @@ public interface SignatureSigningConfiguration extends WhitelistBlacklistConfigu
     @Nonnull @NonnullElements @Unmodifiable @NotLive public List<String> getSignatureReferenceDigestMethods();
     
     /**
+     * Get a canonicalization algorithm URI suitable for use as a Signature Reference Transform value.
+     * 
+     * @return a digest method algorithm URI
+     */
+    @Nullable public String getSignatureReferenceCanonicalizationAlgorithm();
+    
+    /**
      * Get a canonicalization algorithm URI suitable for use as a Signature CanonicalizationMethod value.
      * 
      * @return a canonicalization algorithm URI
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/SignatureSigningParameters.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/SignatureSigningParameters.java
index 126fcde..b97bf5e 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/SignatureSigningParameters.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/SignatureSigningParameters.java
@@ -37,6 +37,9 @@ public class SignatureSigningParameters {
     /** The signature reference digest method URI. */
     private String signatureReferenceDigestMethod;
     
+    /** The signature reference canonicalization transform algorithm. */
+    private String signatureReferenceCanonicalizationAlgorithm;
+    
     /** The signature canonicalization algorithm URI. */
     private String signatureCanonicalizationAlgorithm;
     
@@ -101,6 +104,24 @@ public class SignatureSigningParameters {
     }
     
     /**
+     * Get a canonicalization algorithm URI suitable for use as a Signature Reference Transform value.
+     * 
+     * @return a digest method algorithm URI
+     */
+    @Nullable public String getSignatureReferenceCanonicalizationAlgorithm() {
+        return signatureReferenceCanonicalizationAlgorithm;
+    }
+
+    /**
+     * Get a canonicalization algorithm URI suitable for use as a Signature Reference Transform value.
+     * 
+     * @param uri a canonicalization algorithm URI
+     */
+    public void setSignatureReferenceCanonicalizationAlgorithm(@Nullable final String uri) {
+        signatureReferenceCanonicalizationAlgorithm = uri;
+    }
+
+    /**
      * Get a canonicalization algorithm URI suitable for use as a Signature CanonicalizationMethod value.
      * 
      * @return a canonicalization algorithm URI
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/SignatureSupport.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/SignatureSupport.java
index bb9508a..1214280 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/SignatureSupport.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/SignatureSupport.java
@@ -17,9 +17,11 @@
 
 package org.opensaml.xmlsec.signature.support;
 
-import javax.annotation.Nonnull;
+import java.util.List;
+import java.util.Set;
 
-import net.shibboleth.utilities.java.support.logic.Constraint;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.core.xml.XMLObjectBuilder;
 import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
@@ -35,12 +37,25 @@ import org.opensaml.xmlsec.signature.Signature;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Sets;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
 /**
  * Helper methods for working with XML Signature.
  */
 public final class SignatureSupport {
     
-    //TODO refactor these methods to get method length and cyclomatic complexity down.
+    /** Set of known canonicalization algorithm URIs. */
+    private static final Set<String> C14N_ALGORITHMS = Sets.newHashSet(
+            SignatureConstants.ALGO_ID_C14N11_OMIT_COMMENTS,
+            SignatureConstants.ALGO_ID_C14N11_WITH_COMMENTS,
+            SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS,
+            SignatureConstants.ALGO_ID_C14N_EXCL_WITH_COMMENTS,
+            SignatureConstants.ALGO_ID_C14N_OMIT_COMMENTS,
+            SignatureConstants.ALGO_ID_C14N_WITH_COMMENTS
+            );
     
     /** Constructor. */
     private SignatureSupport() {
@@ -56,7 +71,6 @@ public final class SignatureSupport {
         return LoggerFactory.getLogger(SignatureSupport.class);
     }
     
-// Checkstyle: CyclomaticComplexity OFF
     /**
      * Prepare a {@link Signature} with necessary additional information prior to signing.
      * 
@@ -99,8 +113,6 @@ public final class SignatureSupport {
         Constraint.isNotNull(signature, "Signature cannot be null");
         Constraint.isNotNull(parameters, "Signature signing parameters cannot be null");
 
-        final Logger log = getLogger();
-        
         // Signing credential
         if (signature.getSigningCredential() == null) {
             signature.setSigningCredential(parameters.getSigningCredential());
@@ -122,7 +134,7 @@ public final class SignatureSupport {
             signature.setHMACOutputLength(parameters.getSignatureHMACOutputLength());
         }
     
-        // C14N
+        // SignedInfo C14N
         if (signature.getCanonicalizationAlgorithm() == null) {
             signature.setCanonicalizationAlgorithm(parameters.getSignatureCanonicalizationAlgorithm());
         }
@@ -130,22 +142,27 @@ public final class SignatureSupport {
             throw new SecurityException("No C14N algorithm was available on the signing parameters or Signature");
         }
     
-        // Reference(s) digest method
-        final String paramsDigestAlgo = parameters.getSignatureReferenceDigestMethod();
-        for (final ContentReference cr : signature.getContentReferences()) {
-            if (cr instanceof ConfigurableContentReference) {
-                final ConfigurableContentReference configurableReference = (ConfigurableContentReference) cr;
-                if (paramsDigestAlgo != null) {
-                    configurableReference.setDigestAlgorithm(paramsDigestAlgo);
-                }
-                if (configurableReference.getDigestAlgorithm() == null) {
-                    throw new SecurityException("No reference digest algorithm was available " 
-                            + "on the signing parameters or Signature ContentReference");
-                }
-            }
-        }
+        // Content reference(s): digest method and c14 transform
+        processContentReferences(signature, parameters);
     
         // KeyInfo
+        processKeyInfo(signature, parameters);
+    }
+
+    /**
+     * Prepare the content references.
+     * 
+     * @param signature the Signature to be updated
+     * @param parameters the signing parameters to use
+     * 
+     * @throws SecurityException thrown if a required parameter is not supplied in the parameters instance
+     *          or available on the Signature instance
+     */
+    private static void processKeyInfo(final Signature signature, 
+            final SignatureSigningParameters parameters) throws SecurityException {
+        
+        final Logger log = getLogger();
+        
         if (signature.getKeyInfo() == null) {
             final KeyInfoGenerator kiGenerator = parameters.getKeyInfoGenerator();
             if (kiGenerator != null) {
@@ -163,7 +180,93 @@ public final class SignatureSupport {
             }
         }
     }
-// Checkstyle: CyclomaticComplexity ON
+
+    /**
+     * Prepare the content references.
+     * 
+     * @param signature the Signature to be updated
+     * @param parameters the signing parameters to use
+     * 
+     * @throws SecurityException thrown if a required parameter is not supplied in the parameters instance
+     *          or available on the Signature instance
+     */
+    private static void processContentReferences(@Nonnull final Signature signature, 
+            @Nonnull final SignatureSigningParameters parameters) throws SecurityException {
+        
+        final String paramsDigestAlgo = parameters.getSignatureReferenceDigestMethod();
+        final String paramsC14NTransform = parameters.getSignatureReferenceCanonicalizationAlgorithm();
+        
+        for (final ContentReference cr : signature.getContentReferences()) {
+            if (cr instanceof ConfigurableContentReference) {
+                final ConfigurableContentReference configurableReference = (ConfigurableContentReference) cr;
+                if (paramsDigestAlgo != null) {
+                    configurableReference.setDigestAlgorithm(paramsDigestAlgo);
+                }
+                if (configurableReference.getDigestAlgorithm() == null) {
+                    throw new SecurityException("No reference digest algorithm was available " 
+                            + "on the signing parameters or Signature ContentReference");
+                }
+            }
+            
+            if (paramsC14NTransform != null) {
+                addOrReplaceReferenceCanonicalizationTransform(cr, paramsC14NTransform);
+            }
+        }
+    }
+
+    /**
+     * Process the indicated content reference and either add or replace its canonicalization Transform algorithm
+     * with the indicated algorithm.
+     * 
+     * @param cr the content reference to process
+     * @param uri the canonicalization algorithm to either add or replace
+     */
+    private static void addOrReplaceReferenceCanonicalizationTransform(@Nullable final ContentReference cr, 
+            @Nullable final String uri) {
+        
+        if (cr == null || uri == null) {
+            return;
+        }
+        
+        final Logger log = getLogger();
+        
+        log.trace("Adding or replacing content reference transform: {}", uri);
+        
+        if (cr instanceof TransformsConfigurableContentReference) {
+            final List<String> transforms = ((TransformsConfigurableContentReference)cr).getTransforms();
+            if (transforms == null) {
+                return;
+            }
+            
+            for (int i=0; i<transforms.size(); i++) {
+                if (isCanonicalizationAlgorithm(transforms.get(i))) {
+                    transforms.set(i, uri);
+                    return;
+                }
+            }
+            // Didn't see an existing one, so add it
+            transforms.add(uri);
+        } else {
+            log.warn("A non-null signature reference c14n transform was specified, " 
+                    + "but ContentReference was not configurable for transforms: {}",
+                    cr.getClass().getName());
+        }
+    }
+    
+    /**
+     * Evaluate whether the indicated algorithm URI is a canonicalization algorithm URI.
+     * 
+     * @param uri the algorithm URI to evaluate
+     * @return true if is a canonicalization algorithm, false otherwise
+     */
+    private static boolean isCanonicalizationAlgorithm(@Nullable final String uri) {
+        final String trimmed = StringSupport.trimOrNull(uri);
+        if (trimmed == null) {
+            return false;
+        } else {
+            return C14N_ALGORITHMS.contains(trimmed);
+        }
+    }
     
     /**
      * Signs a {@link SignableXMLObject}.
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/TransformsConfigurableContentReference.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/TransformsConfigurableContentReference.java
new file mode 100644
index 0000000..67716d3
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/TransformsConfigurableContentReference.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.xmlsec.signature.support;
+
+import java.util.List;
+
+/**
+ * A specialization of {@link ContentReference} which allows signature transforms to be specified.
+ * 
+ * Note: This sub-interface was added in a minor update because we can not add new methods to 
+ * {@link ConfigurableContentReference}. In a future major release we could collapse this change 
+ * into that single interface.
+ */
+public interface TransformsConfigurableContentReference extends ContentReference {
+    
+    /**
+     * Gets the mutable list of transforms applied to the content prior to digest generation.
+     * 
+     * @return the transforms applied to the content prior to digest generation
+     */
+    public List<String> getTransforms();
+ 
+}
\ No newline at end of file
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/URIContentReference.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/URIContentReference.java
index d77a289..cc2964d 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/URIContentReference.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/signature/support/URIContentReference.java
@@ -23,9 +23,6 @@ import java.util.List;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
 import org.apache.xml.security.signature.XMLSignature;
 import org.apache.xml.security.signature.XMLSignatureException;
 import org.apache.xml.security.transforms.TransformationException;
@@ -33,6 +30,9 @@ import org.apache.xml.security.transforms.Transforms;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
 /**
  * A generic content reference that uses a URI to reference the content to be signed.
  * 
@@ -40,7 +40,7 @@ import org.slf4j.LoggerFactory;
  * The default digest algorithm used is {@link SignatureConstants#ALGO_ID_DIGEST_SHA256}.
  * </p>
  */
-public class URIContentReference implements ConfigurableContentReference {
+public class URIContentReference implements ConfigurableContentReference, TransformsConfigurableContentReference {
 
     /** Logger. */
     private final Logger log = LoggerFactory.getLogger(URIContentReference.class);
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicSignatureSigningConfiguration.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicSignatureSigningConfiguration.java
index f6f1b4f..8d0c4d5 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicSignatureSigningConfiguration.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicSignatureSigningConfiguration.java
@@ -57,6 +57,9 @@ public class BasicSignatureSigningConfiguration extends BasicWhitelistBlacklistC
     /** Digest method algorithm URIs. */
     @Nonnull @NonnullElements private List<String> signatureReferenceDigestMethods;
     
+    /** The signature reference canonicalization transform algorithm. */
+    @Nullable private String signatureReferenceCanonicalizationAlgorithm;
+    
     /** Signature canonicalization algorithm URI. */
     @Nullable private String signatureCanonicalization;
     
@@ -133,6 +136,25 @@ public class BasicSignatureSigningConfiguration extends BasicWhitelistBlacklistC
         }
         signatureReferenceDigestMethods = new ArrayList<>(StringSupport.normalizeStringCollection(algorithms));
     }
+    
+    /**
+     * Get a canonicalization algorithm URI suitable for use as a Signature Reference Transform value.
+     * 
+     * @return a digest method algorithm URI
+     */
+    @Override
+    @Nullable public String getSignatureReferenceCanonicalizationAlgorithm() {
+        return signatureReferenceCanonicalizationAlgorithm;
+    }
+
+    /**
+     * Get a canonicalization algorithm URI suitable for use as a Signature Reference Transform value.
+     * 
+     * @param uri a canonicalization algorithm URI
+     */
+    public void setSignatureReferenceCanonicalizationAlgorithm(@Nullable final String uri) {
+        signatureReferenceCanonicalizationAlgorithm = StringSupport.trimOrNull(uri);
+    }
 
     /** {@inheritDoc} */
     @Override
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicSignatureSigningParametersResolver.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicSignatureSigningParametersResolver.java
index 6894b51..6b31253 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicSignatureSigningParametersResolver.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicSignatureSigningParametersResolver.java
@@ -122,6 +122,7 @@ public class BasicSignatureSigningParametersResolver
         resolveAndPopulateCredentialAndSignatureAlgorithm(params, criteria, whitelistBlacklistPredicate);
         
         params.setSignatureReferenceDigestMethod(resolveReferenceDigestMethod(criteria, whitelistBlacklistPredicate));
+        params.setSignatureReferenceCanonicalizationAlgorithm(resolveReferenceCanonicalizationAlgorithm(criteria));
         
         params.setSignatureCanonicalizationAlgorithm(resolveCanonicalizationAlgorithm(criteria));
         
@@ -160,6 +161,9 @@ public class BasicSignatureSigningParametersResolver
             log.debug("\tSignature KeyInfoGenerator: {}", params.getKeyInfoGenerator() != null ? "present" : "null");
             
             log.debug("\tReference digest method algorithm URI: {}", params.getSignatureReferenceDigestMethod()); 
+            log.debug("\tReference canonicalization algorithm URI: {}", 
+                    params.getSignatureReferenceCanonicalizationAlgorithm()); 
+            
             log.debug("\tCanonicalization algorithm URI: {}", params.getSignatureCanonicalizationAlgorithm()); 
             log.debug("\tHMAC output length: {}", params.getSignatureHMACOutputLength()); 
         }
@@ -342,6 +346,24 @@ public class BasicSignatureSigningParametersResolver
         }
         return null;
     }
+    
+    /**
+     * Resolve and return the reference canonicalization algorithm URI to use.
+     * 
+     * @param criteria the input criteria being evaluated
+     * @return the reference canonicalization algorithm URI
+     */
+    @Nullable protected String resolveReferenceCanonicalizationAlgorithm(@Nonnull final CriteriaSet criteria) {
+        for (final SignatureSigningConfiguration config : criteria.get(SignatureSigningConfigurationCriterion.class)
+                .getConfigurations()) {
+            
+            if (config.getSignatureReferenceCanonicalizationAlgorithm() != null) {
+                return config.getSignatureReferenceCanonicalizationAlgorithm();
+            }
+            
+        }
+        return null;
+    }
 
     /**
      * Resolve and return the {@link KeyInfoGenerator} instance to use with the specified credential.
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/impl/BasicSignatureSigningParametersResolverTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/impl/BasicSignatureSigningParametersResolverTest.java
index cc106b7..3d19229 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/impl/BasicSignatureSigningParametersResolverTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/impl/BasicSignatureSigningParametersResolverTest.java
@@ -132,6 +132,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSigningCredential(), rsaCred);
         Assert.assertEquals(params.getSignatureAlgorithm(), defaultRSAAlgo);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
         Assert.assertNull(params.getSignatureHMACOutputLength());
         Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -149,6 +150,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSigningCredential(), rsaCred);
         Assert.assertEquals(params.getSignatureAlgorithm(), SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
         Assert.assertNull(params.getSignatureHMACOutputLength());
         Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -169,6 +171,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSigningCredential(), rsaCred);
         Assert.assertEquals(params.getSignatureAlgorithm(), SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), SignatureConstants.ALGO_ID_DIGEST_SHA256);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
         Assert.assertNull(params.getSignatureHMACOutputLength());
         Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -189,6 +192,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSigningCredential(), rsaCred);
         Assert.assertEquals(params.getSignatureAlgorithm(), SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), SignatureConstants.ALGO_ID_DIGEST_SHA256);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
         Assert.assertNull(params.getSignatureHMACOutputLength());
         Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -204,6 +208,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSigningCredential(), dsaCred);
         Assert.assertEquals(params.getSignatureAlgorithm(), defaultDSAAlgo);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
         Assert.assertNull(params.getSignatureHMACOutputLength());
         Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -221,6 +226,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
             Assert.assertEquals(params.getSigningCredential(), ecCred);
             Assert.assertEquals(params.getSignatureAlgorithm(), defaultECAlgo);
             Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+            Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
             Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
             Assert.assertNull(params.getSignatureHMACOutputLength());
             Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -237,6 +243,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSigningCredential(), hmacCred);
         Assert.assertEquals(params.getSignatureAlgorithm(), defaultHMACAlgo);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
         Assert.assertEquals(params.getSignatureHMACOutputLength(), defaultHMACOutputLength);
         Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -257,6 +264,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSignatureAlgorithm(), SignatureConstants.ALGO_ID_MAC_HMAC_SHA256);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), SignatureConstants.ALGO_ID_DIGEST_SHA256);
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureHMACOutputLength(), Integer.valueOf(160));
         Assert.assertNotNull(params.getKeyInfoGenerator());
     }
@@ -274,10 +282,28 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSignatureAlgorithm(), defaultRSAAlgo);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), SignatureConstants.ALGO_ID_C14N11_WITH_COMMENTS);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertNull(params.getSignatureHMACOutputLength());
         Assert.assertNotNull(params.getKeyInfoGenerator());
     }
     
+    @Test
+    public void testReferenceC14NOverride() throws ResolverException {
+        config1.setSigningCredentials(Collections.singletonList(rsaCred));
+        
+        config2.setSignatureReferenceCanonicalizationAlgorithm(SignatureConstants.TRANSFORM_C14N_EXCL_WITH_COMMENTS);
+        
+        SignatureSigningParameters params = resolver.resolveSingle(criteriaSet);
+        
+        Assert.assertNotNull(params);
+        Assert.assertEquals(params.getSigningCredential(), rsaCred);
+        Assert.assertEquals(params.getSignatureAlgorithm(), defaultRSAAlgo);
+        Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+        Assert.assertEquals(params.getSignatureReferenceCanonicalizationAlgorithm(), SignatureConstants.TRANSFORM_C14N_EXCL_WITH_COMMENTS);
+        Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
+        Assert.assertNull(params.getSignatureHMACOutputLength());
+        Assert.assertNotNull(params.getKeyInfoGenerator());
+    }
     
     @Test
     public void testMultipleCreds() throws ResolverException {
@@ -290,6 +316,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSignatureAlgorithm(), defaultRSAAlgo);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertNull(params.getSignatureHMACOutputLength());
         Assert.assertNotNull(params.getKeyInfoGenerator());
         
@@ -301,6 +328,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSigningCredential(), dsaCred);
         Assert.assertEquals(params.getSignatureAlgorithm(), defaultDSAAlgo);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
         Assert.assertNull(params.getSignatureHMACOutputLength());
         Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -315,6 +343,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
             Assert.assertEquals(params.getSigningCredential(), ecCred);
             Assert.assertEquals(params.getSignatureAlgorithm(), defaultECAlgo);
             Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
             Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
             Assert.assertNull(params.getSignatureHMACOutputLength());
             Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -328,6 +357,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSigningCredential(), hmacCred);
         Assert.assertEquals(params.getSignatureAlgorithm(), defaultHMACAlgo);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
         Assert.assertEquals(params.getSignatureHMACOutputLength(), defaultHMACOutputLength);
         Assert.assertNotNull(params.getKeyInfoGenerator());
@@ -346,6 +376,7 @@ public class BasicSignatureSigningParametersResolverTest extends XMLObjectBaseTe
         Assert.assertEquals(params.getSigningCredential(), dsaCred);
         Assert.assertEquals(params.getSignatureAlgorithm(), defaultDSAAlgo);
         Assert.assertEquals(params.getSignatureReferenceDigestMethod(), defaultReferenceDigest);
+        Assert.assertNull(params.getSignatureReferenceCanonicalizationAlgorithm());
         Assert.assertEquals(params.getSignatureCanonicalizationAlgorithm(), defaultC14N);
         Assert.assertNull(params.getSignatureHMACOutputLength());
         Assert.assertNotNull(params.getKeyInfoGenerator());
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/support/SignatureSupportTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/support/SignatureSupportTest.java
new file mode 100644
index 0000000..6543497
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/signature/support/SignatureSupportTest.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.xmlsec.signature.support;
+
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.List;
+
+import org.opensaml.core.xml.XMLObjectBaseTestCase;
+import org.opensaml.security.SecurityException;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.credential.CredentialSupport;
+import org.opensaml.security.crypto.KeySupport;
+import org.opensaml.xmlsec.SignatureSigningParameters;
+import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGenerator;
+import org.opensaml.xmlsec.signature.Signature;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class SignatureSupportTest extends XMLObjectBaseTestCase {
+    
+    private Credential signingCredential;
+    
+    private KeyInfoGenerator keyInfoGenerator;
+    
+    @BeforeClass
+    public void initializeKeyPairAndGenerator() throws NoSuchAlgorithmException, NoSuchProviderException {
+        KeyPair keyPair = KeySupport.generateKeyPair("RSA", 1024, null);
+        signingCredential = CredentialSupport.getSimpleCredential(keyPair.getPublic(), keyPair.getPrivate());
+        keyInfoGenerator = DefaultSecurityConfigurationBootstrap.buildBasicKeyInfoGeneratorManager()
+                .getDefaultManager().getFactory(signingCredential).newInstance();
+    }
+    
+    @Test
+    public void testBasic() throws SecurityException {
+        Signature signature = buildTemplateSignature();
+        
+        SignatureSigningParameters params = buildTemplateSigningParameters();
+        
+        SignatureSupport.prepareSignatureParams(signature, params);
+        
+        Assert.assertNotNull(signature.getCanonicalizationAlgorithm());
+        Assert.assertNotNull(signature.getSignatureAlgorithm());
+        Assert.assertNotNull(signature.getSigningCredential());
+        Assert.assertNotNull(signature.getKeyInfo());
+        
+        URIContentReference cr = (URIContentReference) signature.getContentReferences().get(0);
+        Assert.assertNotNull(cr);
+        
+        Assert.assertEquals(cr.getDigestAlgorithm(), SignatureConstants.ALGO_ID_DIGEST_SHA512);
+        
+        Assert.assertTrue(cr.getTransforms().isEmpty());
+    }
+    
+    @Test
+    public void testAddReferenceCanonicalizationTransformAlone() throws SecurityException {
+        Signature signature = buildTemplateSignature();
+        
+        SignatureSigningParameters params = buildTemplateSigningParameters();
+        params.setSignatureReferenceCanonicalizationAlgorithm(SignatureConstants.TRANSFORM_C14N_WITH_COMMENTS);
+        
+        SignatureSupport.prepareSignatureParams(signature, params);
+        
+        URIContentReference cr = (URIContentReference) signature.getContentReferences().get(0);
+        Assert.assertNotNull(cr);
+        
+        Assert.assertEquals(cr.getTransforms().size(), 1);
+        Assert.assertEquals(cr.getTransforms().get(0), SignatureConstants.TRANSFORM_C14N_WITH_COMMENTS);
+    }
+
+    @Test
+    public void testAddReferenceCanonicalizationTransformAfterEnveloped() throws SecurityException {
+        Signature signature = buildTemplateSignature();
+        List<String> transforms = ((URIContentReference) signature.getContentReferences().get(0)).getTransforms();
+        transforms.add(SignatureConstants.TRANSFORM_ENVELOPED_SIGNATURE);
+        
+        SignatureSigningParameters params = buildTemplateSigningParameters();
+        params.setSignatureReferenceCanonicalizationAlgorithm(SignatureConstants.TRANSFORM_C14N_WITH_COMMENTS);
+        
+        SignatureSupport.prepareSignatureParams(signature, params);
+        
+        URIContentReference cr = (URIContentReference) signature.getContentReferences().get(0);
+        Assert.assertNotNull(cr);
+        
+        Assert.assertEquals(cr.getTransforms().size(), 2);
+        Assert.assertEquals(cr.getTransforms().get(1), SignatureConstants.TRANSFORM_C14N_WITH_COMMENTS);
+    }
+
+    @Test
+    public void testReplaceReferenceCanonicalizationTransformAlone() throws SecurityException {
+        Signature signature = buildTemplateSignature();
+        List<String> transforms = ((URIContentReference) signature.getContentReferences().get(0)).getTransforms();
+        transforms.add(SignatureConstants.TRANSFORM_C14N_OMIT_COMMENTS);
+        
+        SignatureSigningParameters params = buildTemplateSigningParameters();
+        params.setSignatureReferenceCanonicalizationAlgorithm(SignatureConstants.TRANSFORM_C14N_WITH_COMMENTS);
+        
+        SignatureSupport.prepareSignatureParams(signature, params);
+        
+        URIContentReference cr = (URIContentReference) signature.getContentReferences().get(0);
+        Assert.assertNotNull(cr);
+        
+        Assert.assertEquals(cr.getTransforms().size(), 1);
+        Assert.assertEquals(cr.getTransforms().get(0), SignatureConstants.TRANSFORM_C14N_WITH_COMMENTS);
+    }
+    
+    @Test
+    public void testReplaceReferenceCanonicalizationTransformAfterEnveloped() throws SecurityException {
+        Signature signature = buildTemplateSignature();
+        List<String> transforms = ((URIContentReference) signature.getContentReferences().get(0)).getTransforms();
+        transforms.add(SignatureConstants.TRANSFORM_ENVELOPED_SIGNATURE);
+        transforms.add(SignatureConstants.TRANSFORM_C14N_OMIT_COMMENTS);
+        
+        SignatureSigningParameters params = buildTemplateSigningParameters();
+        params.setSignatureReferenceCanonicalizationAlgorithm(SignatureConstants.TRANSFORM_C14N_WITH_COMMENTS);
+        
+        SignatureSupport.prepareSignatureParams(signature, params);
+        
+        URIContentReference cr = (URIContentReference) signature.getContentReferences().get(0);
+        Assert.assertNotNull(cr);
+        
+        Assert.assertEquals(cr.getTransforms().size(), 2);
+        Assert.assertEquals(cr.getTransforms().get(1), SignatureConstants.TRANSFORM_C14N_WITH_COMMENTS);
+    }
+    
+    private Signature buildTemplateSignature() {
+        Signature signature = buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);
+        URIContentReference cr = new URIContentReference("abc123");
+        signature.getContentReferences().add(cr);
+        // Note: no transforms by default
+        return signature;
+    }
+    
+    private SignatureSigningParameters buildTemplateSigningParameters() {
+        SignatureSigningParameters params = new SignatureSigningParameters();
+        params.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
+        params.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+        params.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA512); // Note: not the URIContentReference default
+        params.setSigningCredential(signingCredential);
+        params.setKeyInfoGenerator(keyInfoGenerator);
+        return params;
+    }
+
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list