You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by co...@apache.org on 2014/05/22 12:31:26 UTC

svn commit: r1596803 - in /santuario/xml-security-java/trunk/src: main/java/org/apache/jcp/xml/dsig/internal/dom/ main/java/org/apache/xml/security/algorithms/ main/java/org/apache/xml/security/algorithms/implementations/ main/java/org/apache/xml/secur...

Author: coheigea
Date: Thu May 22 10:31:25 2014
New Revision: 1596803

URL: http://svn.apache.org/r1596803
Log:
Improving HMAC Signature testing

Added:
    santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/HMACSignatureAlgorithmTest.java
    santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/algorithms/HMACSignatureAlgorithmTest.java
Modified:
    santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/JCEMapper.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/SignatureAlgorithm.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/implementations/IntegrityHmac.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/resource/config.xml
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignature.java

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java?rev=1596803&r1=1596802&r2=1596803&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java Thu May 22 10:31:25 2014
@@ -53,12 +53,16 @@ public abstract class DOMHMACSignatureMe
         org.slf4j.LoggerFactory.getLogger(DOMHMACSignatureMethod.class);
 
     // see RFC 4051 for these algorithm definitions
+    static final String HMAC_SHA224 = 
+        "http://www.w3.org/2001/04/xmldsig-more#hmac-sha224";
     static final String HMAC_SHA256 =
         "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
     static final String HMAC_SHA384 =
         "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384";
     static final String HMAC_SHA512 =
         "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512";
+    static final String HMAC_RIPEMD160 =
+        "http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160";
 
     private Mac hmac;
     private int outputLength;
@@ -235,6 +239,28 @@ public abstract class DOMHMACSignatureMe
             return 160;
         }
     }
+    
+    static final class SHA224 extends DOMHMACSignatureMethod {
+        SHA224(AlgorithmParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+            super(params);
+        }
+        SHA224(Element dmElem) throws MarshalException {
+            super(dmElem);
+        }
+        @Override
+        public String getAlgorithm() {
+            return HMAC_SHA224;
+        }
+        @Override
+        String getJCAAlgorithm() {
+            return "HmacSHA224";
+        }
+        @Override
+        int getDigestLength() {
+            return 224;
+        }
+    }
 
     static final class SHA256 extends DOMHMACSignatureMethod {
         SHA256(AlgorithmParameterSpec params)
@@ -301,4 +327,26 @@ public abstract class DOMHMACSignatureMe
             return 512;
         }
     }
+    
+    static final class RIPEMD160 extends DOMHMACSignatureMethod {
+        RIPEMD160(AlgorithmParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+            super(params);
+        }
+        RIPEMD160(Element dmElem) throws MarshalException {
+            super(dmElem);
+        }
+        @Override
+        public String getAlgorithm() {
+            return HMAC_RIPEMD160;
+        }
+        @Override
+        String getJCAAlgorithm() {
+            return "HMACRIPEMD160";
+        }
+        @Override
+        int getDigestLength() {
+            return 160;
+        }
+    }
 }

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java?rev=1596803&r1=1596802&r2=1596803&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java Thu May 22 10:31:25 2014
@@ -131,12 +131,16 @@ public abstract class DOMSignatureMethod
             return new SHA512withECDSA(smElem);
         } else if (alg.equals(SignatureMethod.HMAC_SHA1)) {
             return new DOMHMACSignatureMethod.SHA1(smElem);
+        } else if (alg.equals(DOMHMACSignatureMethod.HMAC_SHA224)) {
+            return new DOMHMACSignatureMethod.SHA224(smElem);
         } else if (alg.equals(DOMHMACSignatureMethod.HMAC_SHA256)) {
             return new DOMHMACSignatureMethod.SHA256(smElem);
         } else if (alg.equals(DOMHMACSignatureMethod.HMAC_SHA384)) {
             return new DOMHMACSignatureMethod.SHA384(smElem);
         } else if (alg.equals(DOMHMACSignatureMethod.HMAC_SHA512)) {
             return new DOMHMACSignatureMethod.SHA512(smElem);
+        } else if (alg.equals(DOMHMACSignatureMethod.HMAC_RIPEMD160)) {
+            return new DOMHMACSignatureMethod.RIPEMD160(smElem);
         } else {
             throw new MarshalException
                 ("unsupported SignatureMethod algorithm: " + alg);

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java?rev=1596803&r1=1596802&r2=1596803&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java Thu May 22 10:31:25 2014
@@ -271,12 +271,16 @@ public final class DOMXMLSignatureFactor
             return new DOMSignatureMethod.SHA256withDSA(params);
         } else if (algorithm.equals(SignatureMethod.HMAC_SHA1)) {
             return new DOMHMACSignatureMethod.SHA1(params);
+        } else if (algorithm.equals(DOMHMACSignatureMethod.HMAC_SHA224)) {
+            return new DOMHMACSignatureMethod.SHA224(params);
         } else if (algorithm.equals(DOMHMACSignatureMethod.HMAC_SHA256)) {
             return new DOMHMACSignatureMethod.SHA256(params);
         } else if (algorithm.equals(DOMHMACSignatureMethod.HMAC_SHA384)) {
             return new DOMHMACSignatureMethod.SHA384(params);
         } else if (algorithm.equals(DOMHMACSignatureMethod.HMAC_SHA512)) {
             return new DOMHMACSignatureMethod.SHA512(params);
+        } else if (algorithm.equals(DOMHMACSignatureMethod.HMAC_RIPEMD160)) {
+            return new DOMHMACSignatureMethod.RIPEMD160(params);
         } else if (algorithm.equals(DOMSignatureMethod.ECDSA_SHA1)) {
             return new DOMSignatureMethod.SHA1withECDSA(params);
         } else if (algorithm.equals(DOMSignatureMethod.ECDSA_SHA256)) {

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/JCEMapper.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/JCEMapper.java?rev=1596803&r1=1596802&r2=1596803&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/JCEMapper.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/JCEMapper.java Thu May 22 10:31:25 2014
@@ -164,6 +164,10 @@ public class JCEMapper {
             new Algorithm("HmacSHA1", "HmacSHA1", "Mac", 160, 0)
         );
         algorithmsMap.put(
+            XMLSignature.ALGO_ID_MAC_HMAC_SHA224, 
+            new Algorithm("HmacSHA224", "HmacSHA224", "Mac", 224, 0)
+        );
+        algorithmsMap.put(
             XMLSignature.ALGO_ID_MAC_HMAC_SHA256, 
             new Algorithm("HmacSHA256", "HmacSHA256", "Mac", 256, 0)
         );

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/SignatureAlgorithm.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/SignatureAlgorithm.java?rev=1596803&r1=1596802&r2=1596803&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/SignatureAlgorithm.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/SignatureAlgorithm.java Thu May 22 10:31:25 2014
@@ -424,6 +424,9 @@ public class SignatureAlgorithm extends 
             XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160, IntegrityHmac.IntegrityHmacRIPEMD160.class
         );
         algorithmHash.put(
+            XMLSignature.ALGO_ID_MAC_HMAC_SHA224, IntegrityHmac.IntegrityHmacSHA224.class
+        );
+        algorithmHash.put(
             XMLSignature.ALGO_ID_MAC_HMAC_SHA256, IntegrityHmac.IntegrityHmacSHA256.class
         );
         algorithmHash.put(

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/implementations/IntegrityHmac.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/implementations/IntegrityHmac.java?rev=1596803&r1=1596802&r2=1596803&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/implementations/IntegrityHmac.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/algorithms/implementations/IntegrityHmac.java Thu May 22 10:31:25 2014
@@ -391,6 +391,34 @@ public abstract class IntegrityHmac exte
             return 160;
         }
     }
+    
+    /**
+     * Class IntegrityHmacSHA224
+     */
+    public static class IntegrityHmacSHA224 extends IntegrityHmac {
+
+        /**
+         * Constructor IntegrityHmacSHA224
+         *
+         * @throws XMLSignatureException
+         */
+        public IntegrityHmacSHA224() throws XMLSignatureException {
+            super();
+        }
+
+        /**
+         * Method engineGetURI
+         *
+         * @inheritDoc
+         */
+        public String engineGetURI() {
+            return XMLSignature.ALGO_ID_MAC_HMAC_SHA224;
+        }
+
+        int getDigestLength() {
+            return 224;
+        }
+    }
 
     /**
      * Class IntegrityHmacSHA256

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/resource/config.xml
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/resource/config.xml?rev=1596803&r1=1596802&r2=1596803&view=diff
==============================================================================
Binary files - no diff available.

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignature.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignature.java?rev=1596803&r1=1596802&r2=1596803&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignature.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignature.java Thu May 22 10:31:25 2014
@@ -121,6 +121,10 @@ public final class XMLSignature extends 
     public static final String ALGO_ID_MAC_HMAC_RIPEMD160 = 
         Constants.MoreAlgorithmsSpecNS + "hmac-ripemd160";
     
+    /** HMAC - Optional HMAC-SHA2224 */
+    public static final String ALGO_ID_MAC_HMAC_SHA224 = 
+        Constants.MoreAlgorithmsSpecNS + "hmac-sha224";
+    
     /** HMAC - Optional HMAC-SHA256 */
     public static final String ALGO_ID_MAC_HMAC_SHA256 = 
         Constants.MoreAlgorithmsSpecNS + "hmac-sha256";

Added: santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/HMACSignatureAlgorithmTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/HMACSignatureAlgorithmTest.java?rev=1596803&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/HMACSignatureAlgorithmTest.java (added)
+++ santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/HMACSignatureAlgorithmTest.java Thu May 22 10:31:25 2014
@@ -0,0 +1,183 @@
+/**
+ * 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 javax.xml.crypto.test.dsig;
+
+import java.lang.reflect.Constructor;
+import java.security.Key;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Collections;
+
+import javax.xml.crypto.KeySelector;
+import javax.xml.crypto.dom.DOMStructure;
+import javax.xml.crypto.dsig.CanonicalizationMethod;
+import javax.xml.crypto.dsig.DigestMethod;
+import javax.xml.crypto.dsig.Reference;
+import javax.xml.crypto.dsig.SignatureMethod;
+import javax.xml.crypto.dsig.SignedInfo;
+import javax.xml.crypto.dsig.XMLObject;
+import javax.xml.crypto.dsig.XMLSignature;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.crypto.dsig.dom.DOMSignContext;
+import javax.xml.crypto.dsig.dom.DOMValidateContext;
+import javax.xml.crypto.dsig.keyinfo.KeyInfo;
+import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
+import javax.xml.crypto.test.KeySelectors;
+import javax.xml.parsers.DocumentBuilder;
+
+import org.apache.xml.security.utils.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+/**
+ * Test signing using all available HMAC signing algorithms
+ */
+public class HMACSignatureAlgorithmTest extends org.junit.Assert {
+
+    private KeySelector sks;
+    private CanonicalizationMethod withoutComments;
+    private DigestMethod sha1;
+    private SignatureMethod hmacSha1, hmacSha224, hmacSha256, hmacSha384, hmacSha512, ripemd160;
+    private XMLSignatureFactory fac;
+    private DocumentBuilder db;
+
+    static {
+        Security.insertProviderAt
+            (new org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI(), 1);
+    }
+
+    public HMACSignatureAlgorithmTest() throws Exception {
+        //
+        // If the BouncyCastle provider is not installed, then try to load it 
+        // via reflection.
+        //
+        if (Security.getProvider("BC") == null) {
+            Constructor<?> cons = null;
+            try {
+                Class<?> c = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
+                cons = c.getConstructor(new Class[] {});
+            } catch (Exception e) {
+                //ignore
+            }
+            if (cons == null) {
+                // BouncyCastle is not available so just return
+                return;
+            } else {
+                Provider provider = (java.security.Provider)cons.newInstance();
+                Security.insertProviderAt(provider, 2);
+            }
+        }
+        
+        db = XMLUtils.createDocumentBuilder(false);
+        // create common objects
+        fac = XMLSignatureFactory.getInstance();
+        withoutComments = fac.newCanonicalizationMethod
+            (CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null);
+        
+        // Digest Methods
+        sha1 = fac.newDigestMethod(DigestMethod.SHA1, null);
+        
+        hmacSha1 = fac.newSignatureMethod("http://www.w3.org/2000/09/xmldsig#hmac-sha1", null);
+        hmacSha224 = fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#hmac-sha224", null);
+        hmacSha256 = fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", null);
+        hmacSha384 = fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#hmac-sha384", null);
+        hmacSha512 = fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#hmac-sha512", null);
+        ripemd160 = fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160", null);
+        
+        sks = new KeySelectors.SecretKeySelector("testkey".getBytes("ASCII"));
+    }
+
+    @org.junit.Test
+    public void testHMACSHA1() throws Exception {
+        test_create_signature_enveloping(hmacSha1, sha1, null,
+                                         TestUtils.getSecretKey("testkey".getBytes("ASCII")), sks);
+    }
+  
+    @org.junit.Test
+    public void testHMACSHA_224() throws Exception {
+        test_create_signature_enveloping(hmacSha224, sha1, null,
+                                         TestUtils.getSecretKey("testkey".getBytes("ASCII")), sks);
+    }
+    
+    @org.junit.Test
+    public void testHMACSHA_256() throws Exception {
+        test_create_signature_enveloping(hmacSha256, sha1, null,
+                                         TestUtils.getSecretKey("testkey".getBytes("ASCII")), sks);
+    }
+    
+    @org.junit.Test
+    public void testHMACSHA_384() throws Exception {
+        test_create_signature_enveloping(hmacSha384, sha1, null,
+                                         TestUtils.getSecretKey("testkey".getBytes("ASCII")), sks);
+    }
+    
+    @org.junit.Test
+    public void testHMACSHA_512() throws Exception {
+        test_create_signature_enveloping(hmacSha512, sha1, null,
+                                         TestUtils.getSecretKey("testkey".getBytes("ASCII")), sks);
+    }
+  
+    @org.junit.Test
+    public void testHMACRIPEMD160() throws Exception {
+        test_create_signature_enveloping(ripemd160, sha1, null,
+                                         TestUtils.getSecretKey("testkey".getBytes("ASCII")), sks);
+    }
+    
+    private void test_create_signature_enveloping(
+        SignatureMethod sm, DigestMethod dm, KeyInfo ki, Key signingKey, KeySelector ks
+    ) throws Exception {
+
+        // create reference
+        Reference ref = fac.newReference("#DSig.Object_1", dm, null,
+                                         XMLObject.TYPE, null);
+
+        // create SignedInfo
+        SignedInfo si = fac.newSignedInfo(withoutComments, sm,
+                                          Collections.singletonList(ref));
+
+        Document doc = db.newDocument();
+        // create Objects
+        Element webElem = doc.createElementNS(null, "Web");
+        Text text = doc.createTextNode("up up and away");
+        webElem.appendChild(text);
+        XMLObject obj = fac.newXMLObject(Collections.singletonList
+                                         (new DOMStructure(webElem)), "DSig.Object_1", "text/xml", null);
+
+        // create XMLSignature
+        XMLSignature sig = fac.newXMLSignature
+        (si, ki, Collections.singletonList(obj), null, null);
+
+        DOMSignContext dsc = new DOMSignContext(signingKey, doc);
+        dsc.setDefaultNamespacePrefix("dsig");
+
+        sig.sign(dsc);
+        TestUtils.validateSecurityOrEncryptionElement(doc.getDocumentElement());
+        
+        // XMLUtils.outputDOM(doc.getDocumentElement(), System.out);
+
+        DOMValidateContext dvc = new DOMValidateContext
+        (ks, doc.getDocumentElement());
+        XMLSignature sig2 = fac.unmarshalXMLSignature(dvc);
+
+        assertTrue(sig.equals(sig2));
+        assertTrue(sig2.validate(dvc));
+    }
+
+}

Added: santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/algorithms/HMACSignatureAlgorithmTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/algorithms/HMACSignatureAlgorithmTest.java?rev=1596803&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/algorithms/HMACSignatureAlgorithmTest.java (added)
+++ santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/algorithms/HMACSignatureAlgorithmTest.java Thu May 22 10:31:25 2014
@@ -0,0 +1,296 @@
+/**
+ * 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.xml.security.test.dom.algorithms;
+
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.security.Key;
+import java.security.Provider;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.test.dom.DSNamespaceContext;
+import org.apache.xml.security.transforms.Transforms;
+import org.apache.xml.security.utils.XMLUtils;
+import org.junit.Assert;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * A test to make sure that the various Signature HMAC algorithms are working
+ */
+public class HMACSignatureAlgorithmTest extends org.junit.Assert {
+
+    static {
+        org.apache.xml.security.Init.init();
+    }
+    
+    public HMACSignatureAlgorithmTest() throws Exception {
+        //
+        // If the BouncyCastle provider is not installed, then try to load it 
+        // via reflection.
+        //
+        if (Security.getProvider("BC") == null) {
+            Constructor<?> cons = null;
+            try {
+                Class<?> c = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
+                cons = c.getConstructor(new Class[] {});
+            } catch (Exception e) {
+                //ignore
+            }
+            if (cons == null) {
+                // BouncyCastle is not available so just return
+                return;
+            } else {
+                Provider provider = (java.security.Provider)cons.newInstance();
+                Security.insertProviderAt(provider, 2);
+            }
+        }
+    }
+    
+    @org.junit.Test
+    public void testHMACSHA1() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument = 
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+        
+        // Set up the Key
+        byte[] hmacKey = "secret".getBytes("ASCII");
+        SecretKey key = new SecretKeySpec(hmacKey, "http://www.w3.org/2000/09/xmldsig#hmac-sha1");
+        
+        List<String> localNames = new ArrayList<String>();
+        localNames.add("PaymentInfo");
+        
+        sign("http://www.w3.org/2000/09/xmldsig#hmac-sha1", document, localNames, key);
+        // XMLUtils.outputDOM(document, System.out);
+        verify(document, key, localNames);
+    }
+    
+    @org.junit.Test
+    public void testHMACMD5() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument = 
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+        
+        // Set up the Key
+        byte[] hmacKey = "secret".getBytes("ASCII");
+        SecretKey key = new SecretKeySpec(hmacKey, "http://www.w3.org/2001/04/xmldsig-more#hmac-md5");
+        
+        List<String> localNames = new ArrayList<String>();
+        localNames.add("PaymentInfo");
+        
+        sign("http://www.w3.org/2001/04/xmldsig-more#hmac-md5", document, localNames, key);
+        // XMLUtils.outputDOM(document, System.out);
+        verify(document, key, localNames);
+    }
+    
+    @org.junit.Test
+    public void testHMACSHA_224() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument = 
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+        
+        // Set up the Key
+        byte[] hmacKey = "secret".getBytes("ASCII");
+        SecretKey key = new SecretKeySpec(hmacKey, "http://www.w3.org/2001/04/xmldsig-more#hmac-sha224");
+        
+        List<String> localNames = new ArrayList<String>();
+        localNames.add("PaymentInfo");
+        
+        sign("http://www.w3.org/2001/04/xmldsig-more#hmac-sha224", document, localNames, key);
+        // XMLUtils.outputDOM(document, System.out);
+        verify(document, key, localNames);
+    }
+    
+    @org.junit.Test
+    public void testHMACSHA_256() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument = 
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+        
+        // Set up the Key
+        byte[] hmacKey = "secret".getBytes("ASCII");
+        SecretKey key = new SecretKeySpec(hmacKey, "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256");
+        
+        List<String> localNames = new ArrayList<String>();
+        localNames.add("PaymentInfo");
+        
+        sign("http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", document, localNames, key);
+        // XMLUtils.outputDOM(document, System.out);
+        verify(document, key, localNames);
+    }
+    
+    @org.junit.Test
+    public void testHMACSHA_384() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument = 
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+        
+        // Set up the Key
+        byte[] hmacKey = "secret".getBytes("ASCII");
+        SecretKey key = new SecretKeySpec(hmacKey, "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384");
+        
+        List<String> localNames = new ArrayList<String>();
+        localNames.add("PaymentInfo");
+        
+        sign("http://www.w3.org/2001/04/xmldsig-more#hmac-sha384", document, localNames, key);
+        // XMLUtils.outputDOM(document, System.out);
+        verify(document, key, localNames);
+    }
+    
+    @org.junit.Test
+    public void testHMACSHA_512() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument = 
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+        
+        // Set up the Key
+        byte[] hmacKey = "secret".getBytes("ASCII");
+        SecretKey key = new SecretKeySpec(hmacKey, "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512");
+        
+        List<String> localNames = new ArrayList<String>();
+        localNames.add("PaymentInfo");
+        
+        sign("http://www.w3.org/2001/04/xmldsig-more#hmac-sha512", document, localNames, key);
+        // XMLUtils.outputDOM(document, System.out);
+        verify(document, key, localNames);
+    }
+    
+    @org.junit.Test
+    public void testHMACRIPEMD160() throws Exception {
+        // Read in plaintext document
+        InputStream sourceDocument = 
+                this.getClass().getClassLoader().getResourceAsStream(
+                        "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+        DocumentBuilder builder = XMLUtils.createDocumentBuilder(false);
+        Document document = builder.parse(sourceDocument);
+        
+        // Set up the Key
+        byte[] hmacKey = "secret".getBytes("ASCII");
+        SecretKey key = new SecretKeySpec(hmacKey, "http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160");
+        
+        List<String> localNames = new ArrayList<String>();
+        localNames.add("PaymentInfo");
+        
+        sign("http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160", document, localNames, key);
+        // XMLUtils.outputDOM(document, System.out);
+        verify(document, key, localNames);
+    }
+
+    private XMLSignature sign(
+        String algorithm,
+        Document document,
+        List<String> localNames,
+        Key signingKey
+    ) throws Exception {
+        String c14nMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
+        XMLSignature sig = new XMLSignature(document, "", algorithm, c14nMethod);
+
+        Element root = document.getDocumentElement();
+        root.appendChild(sig.getElement());
+
+        XPathFactory xpf = XPathFactory.newInstance();
+        XPath xpath = xpf.newXPath();
+        xpath.setNamespaceContext(new DSNamespaceContext());
+
+        for (String localName : localNames) {
+            String expression = "//*[local-name()='" + localName + "']";
+            NodeList elementsToSign =
+                    (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
+            for (int i = 0; i < elementsToSign.getLength(); i++) {
+                Element elementToSign = (Element)elementsToSign.item(i);
+                Assert.assertNotNull(elementToSign);
+                String id = UUID.randomUUID().toString();
+                elementToSign.setAttributeNS(null, "Id", id);
+                elementToSign.setIdAttributeNS(null, "Id", true);
+
+                Transforms transforms = new Transforms(document);
+                transforms.addTransform(c14nMethod);
+                String digestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
+                sig.addDocument("#" + id, transforms, digestMethod);
+            }
+        }
+
+        sig.sign(signingKey);
+
+        String expression = "//ds:Signature[1]";
+        Element sigElement =
+                (Element) xpath.evaluate(expression, document, XPathConstants.NODE);
+        Assert.assertNotNull(sigElement);
+
+        return sig;
+    }
+    
+    private void verify(
+        Document document,
+        Key key,
+        List<String> localNames
+    ) throws Exception {
+        XPathFactory xpf = XPathFactory.newInstance();
+        XPath xpath = xpf.newXPath();
+        xpath.setNamespaceContext(new DSNamespaceContext());
+
+        String expression = "//dsig:Signature[1]";
+        Element sigElement =
+            (Element) xpath.evaluate(expression, document, XPathConstants.NODE);
+        Assert.assertNotNull(sigElement);
+
+        for (String name : localNames) {
+            expression = "//*[local-name()='" + name + "']";
+            Element signedElement =
+                (Element) xpath.evaluate(expression, document, XPathConstants.NODE);
+            Assert.assertNotNull(signedElement);
+            signedElement.setIdAttributeNS(null, "Id", true);
+        }
+
+        XMLSignature signature = new XMLSignature(sigElement, "");
+
+        Assert.assertTrue(signature.checkSignatureValue(key));
+    }
+
+}