You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2015/06/29 12:59:26 UTC

svn commit: r1688180 - in /webservices/wss4j/trunk: ws-security-common/src/main/java/org/apache/wss4j/common/crypto/ ws-security-common/src/test/java/org/apache/wss4j/common/crypto/ ws-security-dom/src/test/java/org/apache/wss4j/dom/message/ ws-securit...

Author: coheigea
Date: Mon Jun 29 10:59:25 2015
New Revision: 1688180

URL: http://svn.apache.org/r1688180
Log:
[WSS-543] - Create a Merlin implementation that retrieves CA certs via their SubjectKeyIdentifier

Added:
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/BouncyCastleUtils.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java
    webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureAKITest.java
    webservices/wss4j/trunk/ws-security-dom/src/test/resources/wss40CAAKI.properties
Modified:
    webservices/wss4j/trunk/ws-security-common/src/test/java/org/apache/wss4j/common/crypto/AuthorityKeyIdentifierTest.java

Added: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/BouncyCastleUtils.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/BouncyCastleUtils.java?rev=1688180&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/BouncyCastleUtils.java (added)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/BouncyCastleUtils.java Mon Jun 29 10:59:25 2015
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.wss4j.common.crypto;
+
+import java.security.cert.X509Certificate;
+
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
+
+public final class BouncyCastleUtils {
+    
+    private BouncyCastleUtils() {
+        // complete
+    }
+
+    public static byte[] getAuthorityKeyIdentifierBytes(X509Certificate cert) {
+        byte[] extensionValue = cert.getExtensionValue("2.5.29.35"); //NOPMD
+        if (extensionValue != null) {
+            byte[] octets = ASN1OctetString.getInstance(extensionValue).getOctets();     
+            AuthorityKeyIdentifier authorityKeyIdentifier = 
+                AuthorityKeyIdentifier.getInstance(octets);
+            return authorityKeyIdentifier.getKeyIdentifier();
+        }
+        return null;
+    }
+    
+    public static byte[] getSubjectKeyIdentifierBytes(X509Certificate cert) {
+        byte[] extensionValue = cert.getExtensionValue("2.5.29.14"); //NOPMD
+        if (extensionValue != null) {
+            byte[] subjectOctets = 
+                ASN1OctetString.getInstance(extensionValue).getOctets();     
+            SubjectKeyIdentifier subjectKeyIdentifier =
+                SubjectKeyIdentifier.getInstance(subjectOctets);
+            return subjectKeyIdentifier.getKeyIdentifier();
+        }
+        return null;
+    }
+    
+}
+
+

Added: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java?rev=1688180&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java (added)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java Mon Jun 29 10:59:25 2015
@@ -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.wss4j.common.crypto;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.apache.wss4j.common.ext.WSSecurityException;
+
+/**
+ * A Crypto implementation based on two Java KeyStore objects, one being the keystore, and one
+ * being the truststore. It differs from Merlin in that it searches the truststore for the
+ * issuing cert using the AuthorityKeyIdentifier bytes of the certificate, as opposed to the
+ * issuer DN.
+ */
+public class MerlinAKI extends Merlin {
+    
+    private static final org.slf4j.Logger LOG = 
+        org.slf4j.LoggerFactory.getLogger(MerlinAKI.class);
+    
+    public MerlinAKI() {
+        super();
+    }
+    
+    public MerlinAKI(boolean loadCACerts, String cacertsPasswd) {
+        super(loadCACerts, cacertsPasswd);
+    }
+    
+    public MerlinAKI(Properties properties, ClassLoader loader, PasswordEncryptor passwordEncryptor) 
+        throws WSSecurityException, IOException {
+        super(properties, loader, passwordEncryptor);
+    }
+    
+    /**
+     * Evaluate whether a given certificate chain should be trusted.
+     *
+     * @param certs Certificate chain to validate
+     * @param enableRevocation whether to enable CRL verification or not
+     * @param subjectCertConstraints A set of constraints on the Subject DN of the certificates
+     * 
+     * @throws WSSecurityException if the certificate chain is invalid
+     */
+    @Override
+    public void verifyTrust(
+        X509Certificate[] certs, 
+        boolean enableRevocation,
+        Collection<Pattern> subjectCertConstraints
+    ) throws WSSecurityException {
+        //
+        // FIRST step - Search the keystore for the transmitted certificate
+        //
+        if (certs.length == 1 && !enableRevocation) {
+            String issuerString = certs[0].getIssuerX500Principal().getName();
+            BigInteger issuerSerial = certs[0].getSerialNumber();
+            
+            CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ISSUER_SERIAL);
+            cryptoType.setIssuerSerial(issuerString, issuerSerial);
+            X509Certificate[] foundCerts = getX509Certificates(cryptoType);
+    
+            //
+            // If a certificate has been found, the certificates must be compared
+            // to ensure against phony DNs (compare encoded form including signature)
+            //
+            if (foundCerts != null && foundCerts[0] != null && foundCerts[0].equals(certs[0])) {
+                try {
+                    certs[0].checkValidity();
+                } catch (CertificateExpiredException | CertificateNotYetValidException e) {
+                    throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.FAILED_CHECK, e, "invalidCert"
+                    );
+                }
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug(
+                        "Direct trust for certificate with " + certs[0].getSubjectX500Principal().getName()
+                    );
+                }
+                return;
+            }
+        }
+        
+        //
+        // SECOND step - Search for the issuer cert (chain) of the transmitted certificate in the 
+        // keystore or the truststore
+        //
+        X509Certificate[] x509certs = certs;
+        String issuerString = certs[0].getIssuerX500Principal().getName();
+        try {
+            if (certs.length == 1) {
+                byte[] keyIdentifierBytes = 
+                    BouncyCastleUtils.getAuthorityKeyIdentifierBytes(certs[0]);
+                X509Certificate[] foundCerts = getX509CertificatesFromKeyIdentifier(keyIdentifierBytes);
+        
+                // If the certs have not been found, the issuer is not in the keystore/truststore
+                // As a direct result, do not trust the transmitted certificate
+                if (foundCerts == null || foundCerts.length < 1) {
+                    String subjectString = certs[0].getSubjectX500Principal().getName();
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug(
+                            "No certs found in keystore for issuer " + issuerString 
+                            + " of certificate for " + subjectString
+                        );
+                    }
+                    throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.FAILURE, "certpath", new Object[] {"No trusted certs found"}
+                    );
+                }
+                
+                //
+                // Form a certificate chain from the transmitted certificate
+                // and the certificate(s) of the issuer from the keystore/truststore
+                //
+                x509certs = new X509Certificate[foundCerts.length + 1];
+                x509certs[0] = certs[0];
+                System.arraycopy(foundCerts, 0, x509certs, 1, foundCerts.length);
+            }
+        } catch (NoSuchAlgorithmException | CertificateException ex) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, ex, "certpath");
+        }
+        
+        //
+        // THIRD step
+        // Check the certificate trust path for the issuer cert chain
+        //
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(
+                "Preparing to validate certificate path for issuer " + issuerString
+            );
+        }
+        
+        try {
+            // Generate cert path
+            List<X509Certificate> certList = Arrays.asList(x509certs);
+            CertPath path = getCertificateFactory().generateCertPath(certList);
+
+            Set<TrustAnchor> set = new HashSet<>();
+            if (truststore != null) {
+                Enumeration<String> truststoreAliases = truststore.aliases();
+                while (truststoreAliases.hasMoreElements()) {
+                    String alias = truststoreAliases.nextElement();
+                    X509Certificate cert = 
+                        (X509Certificate) truststore.getCertificate(alias);
+                    if (cert != null) {
+                        TrustAnchor anchor = 
+                            new TrustAnchor(cert, cert.getExtensionValue(NAME_CONSTRAINTS_OID));
+                        set.add(anchor);
+                    }
+                }
+            }
+
+            //
+            // Add certificates from the keystore - only if there is no TrustStore, apart from
+            // the case that the truststore is the JDK CA certs. This behaviour is preserved
+            // for backwards compatibility reasons
+            //
+            if (keystore != null && (truststore == null || loadCACerts)) {
+                Enumeration<String> aliases = keystore.aliases();
+                while (aliases.hasMoreElements()) {
+                    String alias = aliases.nextElement();
+                    X509Certificate cert = 
+                        (X509Certificate) keystore.getCertificate(alias);
+                    if (cert != null) {
+                        TrustAnchor anchor = 
+                            new TrustAnchor(cert, cert.getExtensionValue(NAME_CONSTRAINTS_OID));
+                        set.add(anchor);
+                    }
+                }
+            }
+
+            // Verify the trust path using the above settings
+            String provider = getCryptoProvider();
+            CertPathValidator validator = null;
+            if (provider == null || provider.length() == 0) {
+                validator = CertPathValidator.getInstance("PKIX");
+            } else {
+                validator = CertPathValidator.getInstance("PKIX", provider);
+            }
+            
+            PKIXParameters param = createPKIXParameters(set, enableRevocation);
+            validator.validate(path, param);
+        } catch (NoSuchProviderException | NoSuchAlgorithmException 
+            | CertificateException | InvalidAlgorithmParameterException
+            | java.security.cert.CertPathValidatorException 
+            | KeyStoreException e) {
+                throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.FAILURE, e, "certpath"
+                );
+        }
+        
+        // Finally check Cert Constraints
+        if (!matches(certs[0], subjectCertConstraints)) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+        }
+    }
+    
+    private X509Certificate[] getX509CertificatesFromKeyIdentifier(
+        byte[] keyIdentifierBytes
+    ) throws WSSecurityException, NoSuchAlgorithmException, CertificateEncodingException {
+        if (keyIdentifierBytes == null) {
+            return null;
+        }
+        
+        Certificate[] certs = null;
+        if (keystore != null) {
+            certs = getCertificates(keyIdentifierBytes, keystore);
+        }
+
+        //If we can't find the issuer in the keystore then look at the truststore
+        if ((certs == null || certs.length == 0) && truststore != null) {
+            certs = getCertificates(keyIdentifierBytes, truststore);
+        }
+        
+        if (certs == null || certs.length == 0) {
+            return null;
+        }
+        
+        X509Certificate[] x509certs = new X509Certificate[certs.length];
+        for (int i = 0; i < certs.length; i++) {
+            x509certs[i] = (X509Certificate) certs[i];
+        }
+        return x509certs;
+    }
+
+    private Certificate[] getCertificates(
+        byte[] keyIdentifier, 
+        KeyStore store
+    ) throws WSSecurityException, NoSuchAlgorithmException, CertificateEncodingException {
+        try {
+            for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
+                String alias = e.nextElement();
+                Certificate[] certs = store.getCertificateChain(alias);
+                if (certs == null || certs.length == 0) {
+                    // no cert chain, so lets check if getCertificate gives us a result.
+                    Certificate cert = store.getCertificate(alias);
+                    if (cert != null) {
+                        certs = new Certificate[]{cert};
+                    }
+                }
+                
+                if (certs != null && certs.length > 0 && certs[0] instanceof X509Certificate) {
+                    byte[] subjectKeyIdentifier = 
+                        BouncyCastleUtils.getSubjectKeyIdentifierBytes((X509Certificate)certs[0]);
+                    if (subjectKeyIdentifier != null 
+                        && Arrays.equals(subjectKeyIdentifier, keyIdentifier)) {
+                        return certs;
+                    }
+                }
+            }
+        } catch (KeyStoreException e) {
+            throw new WSSecurityException(
+                WSSecurityException.ErrorCode.FAILURE, e, "keystore"
+            );
+        }
+        return new Certificate[]{};
+    }
+    
+}

Modified: webservices/wss4j/trunk/ws-security-common/src/test/java/org/apache/wss4j/common/crypto/AuthorityKeyIdentifierTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/test/java/org/apache/wss4j/common/crypto/AuthorityKeyIdentifierTest.java?rev=1688180&r1=1688179&r2=1688180&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/test/java/org/apache/wss4j/common/crypto/AuthorityKeyIdentifierTest.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/test/java/org/apache/wss4j/common/crypto/AuthorityKeyIdentifierTest.java Mon Jun 29 10:59:25 2015
@@ -25,9 +25,6 @@ import java.security.cert.X509Certificat
 import java.util.Arrays;
 
 import org.apache.wss4j.common.util.Loader;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
-import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
 
 /**
  * This is a test for extracting AuthorityKeyIdentifier/SubjectKeyIdentifier information from
@@ -35,6 +32,10 @@ import org.bouncycastle.asn1.x509.Subjec
  */
 public class AuthorityKeyIdentifierTest extends org.junit.Assert {
     
+    public AuthorityKeyIdentifierTest() {
+        WSProviderConfig.init();
+    }
+    
     @org.junit.Test
     public void testExtractKeyIdentifiers() throws Exception {
         // Load the keystore
@@ -45,10 +46,7 @@ public class AuthorityKeyIdentifierTest
         assertNotNull(cert);
         
         // Get AuthorityKeyIdentifier from the cert
-        byte[] octets = (ASN1OctetString.getInstance(cert.getExtensionValue("2.5.29.35")).getOctets());     
-        AuthorityKeyIdentifier authorityKeyIdentifier = 
-            AuthorityKeyIdentifier.getInstance(octets);
-        byte[] keyIdentifierBytes = authorityKeyIdentifier.getKeyIdentifier();
+        byte[] keyIdentifierBytes = BouncyCastleUtils.getAuthorityKeyIdentifierBytes(cert);
         assertNotNull(keyIdentifierBytes);
         
         // Now load the CA cert
@@ -59,17 +57,44 @@ public class AuthorityKeyIdentifierTest
         assertNotNull(caCert);
         
         // Get SubjectKeyIdentifier from the CA cert
-        byte[] subjectOctets = 
-            (ASN1OctetString.getInstance(caCert.getExtensionValue("2.5.29.14")).getOctets());     
-        SubjectKeyIdentifier subjectKeyIdentifier =
-            SubjectKeyIdentifier.getInstance(subjectOctets);
-        assertNotNull(subjectKeyIdentifier);
-        byte[] subjectKeyIdentifierBytes = subjectKeyIdentifier.getKeyIdentifier();
+        byte[] subjectKeyIdentifierBytes = 
+            BouncyCastleUtils.getSubjectKeyIdentifierBytes(caCert);
         assertNotNull(subjectKeyIdentifierBytes);
 
         assertTrue(Arrays.equals(keyIdentifierBytes, subjectKeyIdentifierBytes));
     }
     
+    @org.junit.Test
+    public void testMerlinAKI() throws Exception {
+        // Load the keystore
+        KeyStore keyStore = loadKeyStore("keys/wss40.jks", "security");
+        assertNotNull(keyStore);
+        X509Certificate cert = (X509Certificate)keyStore.getCertificate("wss40");
+        assertNotNull(cert);
+        
+        // Now load the CA keystore + instantiate MerlinAKI
+        KeyStore caKeyStore = loadKeyStore("keys/wss40CA.jks", "security");
+        assertNotNull(caKeyStore);
+        MerlinAKI crypto = new MerlinAKI();
+        crypto.setTrustStore(caKeyStore);
+        
+        // Verify trust...
+        crypto.verifyTrust(new X509Certificate[]{cert}, false, null);
+        
+        // Now test with a non-trusted cert
+        KeyStore badKeyStore = loadKeyStore("keys/wss86.keystore", "security");
+        assertNotNull(badKeyStore);
+        X509Certificate badCert = (X509Certificate)badKeyStore.getCertificate("wss86");
+        assertNotNull(badCert);
+        
+        try {
+            crypto.verifyTrust(new X509Certificate[]{badCert}, false, null);
+            fail("Failure expected on trying to validate an untrusted cert");
+        } catch (Exception ex) {
+            // expected
+        }
+    }
+    
     private KeyStore loadKeyStore(String path, String password) throws Exception {
         KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
         ClassLoader loader = Loader.getClassLoader(AuthorityKeyIdentifierTest.class);

Added: webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureAKITest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureAKITest.java?rev=1688180&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureAKITest.java (added)
+++ webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureAKITest.java Mon Jun 29 10:59:25 2015
@@ -0,0 +1,90 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.wss4j.dom.message;
+
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.util.XMLUtils;
+import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.WSSConfig;
+import org.apache.wss4j.dom.WSSecurityEngine;
+import org.apache.wss4j.dom.WSSecurityEngineResult;
+import org.apache.wss4j.dom.common.SOAPUtil;
+import org.apache.wss4j.dom.common.SecurityTestUtil;
+import org.apache.wss4j.dom.handler.WSHandlerResult;
+import org.w3c.dom.Document;
+
+
+/**
+ * A set of test-cases for signing and verifying SOAP requests using the Merlin AKI Crypto implementation.
+ */
+public class SignatureAKITest extends org.junit.Assert {
+    private static final org.slf4j.Logger LOG = 
+        org.slf4j.LoggerFactory.getLogger(SignatureAKITest.class);
+    
+    private WSSecurityEngine secEngine = new WSSecurityEngine();
+    private Crypto crypto = null;
+    
+    @org.junit.AfterClass
+    public static void cleanup() throws Exception {
+        SecurityTestUtil.cleanup();
+    }
+    
+    public SignatureAKITest() throws Exception {
+        WSSConfig.init();
+        crypto = CryptoFactory.getInstance("wss40CAAKI.properties");
+    }
+
+    @org.junit.Test
+    public void testSignatureAKI() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("wss40", "security");
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader(doc);
+        secHeader.insertSecurityHeader();
+        Crypto signingCrypto = CryptoFactory.getInstance("wss40.properties");
+        Document signedDoc = builder.build(doc, signingCrypto, secHeader);
+
+        if (LOG.isDebugEnabled()) {
+            String outputString = 
+                XMLUtils.PrettyDocumentToString(signedDoc);
+            LOG.debug(outputString);
+        }
+        WSHandlerResult results = verify(signedDoc);
+        
+        WSSecurityEngineResult actionResult =
+            results.getActionResults().get(WSConstants.SIGN).get(0);
+        assertNotNull(actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE));
+        assertNotNull(actionResult.get(WSSecurityEngineResult.TAG_X509_REFERENCE_TYPE));
+    }
+    
+    /**
+     * Verifies the soap envelope.
+     * This method verifies all the signature generated. 
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private WSHandlerResult verify(Document doc) throws Exception {
+        return secEngine.processSecurityHeader(doc, null, null, crypto);
+    }
+
+}

Added: webservices/wss4j/trunk/ws-security-dom/src/test/resources/wss40CAAKI.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/test/resources/wss40CAAKI.properties?rev=1688180&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/test/resources/wss40CAAKI.properties (added)
+++ webservices/wss4j/trunk/ws-security-dom/src/test/resources/wss40CAAKI.properties Mon Jun 29 10:59:25 2015
@@ -0,0 +1,3 @@
+org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.MerlinAKI
+org.apache.wss4j.crypto.merlin.truststore.password=security
+org.apache.wss4j.crypto.merlin.truststore.file=keys/wss40CA.jks