Author: alexoree
Date: Thu Apr 11 00:46:59 2013
New Revision: 1466744

URL: http://svn.apache.org/r1466744
Log:
adding a digital signature utility, still very beta for the 3.2 branch

Modified:
    
juddi/branches/juddi-3.2.x/juddi-client/src/main/java/org/apache/juddi/v3/client/crypto/DigSigUtil.java
    juddi/branches/juddi-3.2.x/juddi-gui-dsig/   (props changed)
    juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/   (props changed)
    juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/build-impl.xml
    juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/genfiles.properties

Modified: 
juddi/branches/juddi-3.2.x/juddi-client/src/main/java/org/apache/juddi/v3/client/crypto/DigSigUtil.java
URL: 
http://svn.apache.org/viewvc/juddi/branches/juddi-3.2.x/juddi-client/src/main/java/org/apache/juddi/v3/client/crypto/DigSigUtil.java?rev=1466744&r1=1466743&r2=1466744&view=diff
==============================================================================
--- 
juddi/branches/juddi-3.2.x/juddi-client/src/main/java/org/apache/juddi/v3/client/crypto/DigSigUtil.java
 (original)
+++ 
juddi/branches/juddi-3.2.x/juddi-client/src/main/java/org/apache/juddi/v3/client/crypto/DigSigUtil.java
 Thu Apr 11 00:46:59 2013
@@ -17,23 +17,40 @@ package org.apache.juddi.v3.client.crypt
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringWriter;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.KeyStore;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.PublicKey;
+import java.security.Security;
+import java.security.cert.CRLException;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertPathValidatorResult;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.PKIXCertPathValidatorResult;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509CRL;
+import java.security.cert.X509CertSelector;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Properties;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.security.auth.x500.X500Principal;
 import javax.xml.bind.JAXB;
 import javax.xml.crypto.dsig.CanonicalizationMethod;
 import javax.xml.crypto.dsig.DigestMethod;
@@ -58,6 +75,8 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import sun.security.provider.certpath.OCSP;
+import sun.security.provider.certpath.OCSP.RevocationStatus;
 
 /**
  * A utility class for signing and verifying JAXB Objects, such as UDDI
@@ -70,7 +89,8 @@ import org.w3c.dom.NodeList;
  */
 public final class DigSigUtil {
 
-    public DigSigUtil() {
+    public DigSigUtil() throws CertificateException {
+        cf = CertificateFactory.getInstance("X.509");
     }
     private Log logger = LogFactory.getLog(this.getClass());
 
@@ -101,6 +121,9 @@ public final class DigSigUtil {
     public final static String SIGNATURE_KEYSTORE_FILE_PASSWORD = 
"filePassword";
     public final static String SIGNATURE_KEYSTORE_KEY_PASSWORD = "keyPassword";
     public final static String SIGNATURE_KEYSTORE_KEY_ALIAS = "keyAlias";
+    public final static String TRUSTSTORE_FILE = "keyStorePath";
+    public final static String TRUSTSTORE_FILETYPE = "keyStoreType";
+    public final static String TRUSTSTORE_FILE_PASSWORD = "filePassword";
     /**
      * default is CanonicalizationMethod.EXCLUSIVE
      *
@@ -202,6 +225,10 @@ public final class DigSigUtil {
      * map.put(DigSigUtil.CHECK_TIMESTAMPS, true);</pre> any value can be used.
      */
     public final static String CHECK_TIMESTAMPS = "checkTimestamps";
+    private CertificateFactory cf = null;
+    public final static String CHECK_REVOCATION_STATUS_OCSP = 
"checkRevocationOCSP";
+    public final static String CHECK_REVOCATION_STATUS_CRL = 
"checkRevocationCRL";
+    public final static String CHECK_TRUST_CHAIN = "checkTrust";
 
     /**
      * Digital signs a UDDI entity, such as a business, service, tmodel or
@@ -296,7 +323,7 @@ public final class DigSigUtil {
     }
 
     /**
-     *  /**
+     *
      * returns the public key of the signing certificate used for a signed JAXB
      * object.
      *
@@ -311,7 +338,7 @@ public final class DigSigUtil {
         }
 
         NodeList childNodes = docElement.getChildNodes();   //children, one of 
these SHOULD be our signature element
-        X509Certificate signingcert = null;
+        // X509Certificate signingcert = null;
         for (int i = 0; i < childNodes.getLength(); i++) {
             //System.out.println(childNodes.item(i).getNamespaceURI() + " " + 
childNodes.item(i).getNodeName());
             if 
(childNodes.item(i).getNamespaceURI().equalsIgnoreCase(XML_DIGSIG_NS) && 
childNodes.item(i).getLocalName().equalsIgnoreCase("Signature")) {
@@ -326,7 +353,7 @@ public final class DigSigUtil {
                                 for (int x = 0; x < 
X509Data.getChildNodes().getLength(); x++) {
                                     if 
(X509Data.getChildNodes().item(x).getLocalName().equalsIgnoreCase("X509Certificate"))
 {
                                         //yay found it!
-                                        CertificateFactory cf = 
CertificateFactory.getInstance("X.509");
+
 
                                         String c =
                                                 "-----BEGIN CERTIFICATE-----\n"
@@ -337,15 +364,12 @@ public final class DigSigUtil {
                                         return (X509Certificate) 
cf.generateCertificate(is);
 
                                     }
+
+                                    //if we have a 
                                     //TODO other parsing items, lots of other 
potentials here
                                 }
+                                return FindCert(X509Data.getChildNodes());
                             }
-                            //System.out.println("ns " + 
sig.getChildNodes().item(k).getChildNodes().item(j).getNamespaceURI()
-                            //      + " nn " + 
sig.getChildNodes().item(k).getChildNodes().item(j).getNodeName()
-                            //    + " nv " + 
sig.getChildNodes().item(k).getChildNodes().item(j).getNodeValue()
-                            //  + " tx " + 
sig.getChildNodes().item(k).getChildNodes().item(j).getTextContent());
-                            //   -----BEGIN CERTIFICATE-----, and must be 
bounded at the end by -----END CERTIFICATE-----.
-
 
                         }
                         break;
@@ -363,11 +387,25 @@ public final class DigSigUtil {
      * Verifies the signature on an enveloped digital signature on a UDDI
      * entity, such as a business, service, tmodel or binding template.
      *
-     * @param obj
+     * It is expect that either the public key of the signing certificate is
+     * included within the signature keyinfo section OR that sufficient
+     * information is provided in the signature to reference a public key
+     * located within the Trust Store provided
+     *
+     * @param obj an enveloped signed JAXB object
+     * @param OutErrorMessage a human readable error message explaining the
+     * reason for failure
      * @return true if the validation passes the signature validation test, and
      * optionally any certificate validation or trust chain validation
+     * @throws IllegalArgumentException for null input
      */
-    public boolean verifySignedUddiEntity(Object obj) {
+    public boolean verifySignedUddiEntity(Object obj, AtomicReference<String> 
OutErrorMessage) throws IllegalArgumentException {
+        if (OutErrorMessage == null) {
+            OutErrorMessage = new AtomicReference<String>();
+        }
+        if (obj == null) {
+            throw new IllegalArgumentException("obj");
+        }
         try {
             DOMResult domResult = new DOMResult();
             JAXB.marshal(obj, domResult);
@@ -382,8 +420,59 @@ public final class DigSigUtil {
                 if (map.containsKey(CHECK_TIMESTAMPS)) {
                     signingcert.checkValidity();
                 }
-                return verifySignature(docElement, signingcert.getPublicKey());
+                if (map.containsKey(CHECK_REVOCATION_STATUS_OCSP)) {
+                    logger.info("verifying revocation status via OSCP for X509 
public key " + signingcert.getSubjectDN().toString());
+                    X500Principal issuerX500Principal = 
signingcert.getIssuerX500Principal();
+                    logger.info("certificate " + 
signingcert.getSubjectDN().toString() + " was issued by " + 
issuerX500Principal.getName() + ", attempting to retrieve certificate");
+                    Security.setProperty("ocsp.enable", "false");
+                    X509Certificate issuer = FindCertByDN(issuerX500Principal);
+                    if (issuer == null) {
+                        throw new CertificateException("unable to locate the 
issuers certificate in the trust store");
+                    }
+                    RevocationStatus check = OCSP.check(signingcert, issuer);
+                    logger.info("certificate " + 
signingcert.getSubjectDN().toString() + " revocation status is " + 
check.getCertStatus().toString() + " reason " + 
check.getRevocationReason().toString());
+                    if (check.getCertStatus() != 
RevocationStatus.CertStatus.GOOD) {
+                        throw new CertificateException("Certificate status is 
" + check.getCertStatus().toString() + " reason " + 
check.getRevocationReason().toString());
+                    }
+                }
+                if (map.containsKey(CHECK_REVOCATION_STATUS_CRL)) {
+                    logger.info("verifying revokation status via CRL for X509 
public key " + signingcert.getSubjectDN().toString());
+
+                    Security.setProperty("ocsp.enable", "false");
+                    System.setProperty("com.sun.security.enableCRLDP", "true");
+
+                    X509CertSelector targetConstraints = new 
X509CertSelector();
+                    targetConstraints.setCertificate(signingcert);
+                    PKIXParameters params = new 
PKIXParameters(GetTrustStore());
+                    params.setRevocationEnabled(true);
+                    CertPath certPath = 
cf.generateCertPath(Arrays.asList(signingcert));
+
+                    CertPathValidator certPathValidator = 
CertPathValidator.getInstance(CertPathValidator.getDefaultType());
+                    CertPathValidatorResult result = 
certPathValidator.validate(certPath, params);
+
+                    PKIXCertPathValidatorResult pkixResult = 
(PKIXCertPathValidatorResult) result;
+                    logger.info("revokation status via CRL PASSED for X509 
public key " + signingcert.getSubjectDN().toString());
+
+                }
+                if (map.containsKey(CHECK_TRUST_CHAIN)) {
+                    logger.info("verifying trust chain X509 public key " + 
signingcert.getSubjectDN().toString());
+                    PKIXParameters params = new 
PKIXParameters(GetTrustStore());
+                    params.setRevocationEnabled(false);
+                    CertPath certPath = 
cf.generateCertPath(Arrays.asList(signingcert));
+
+                    CertPathValidator certPathValidator = 
CertPathValidator.getInstance(CertPathValidator.getDefaultType());
+                    CertPathValidatorResult result = 
certPathValidator.validate(certPath, params);
+
+                    PKIXCertPathValidatorResult pkixResult = 
(PKIXCertPathValidatorResult) result;
+
+                    TrustAnchor ta = pkixResult.getTrustAnchor();
+                    X509Certificate cert = ta.getTrustedCert();
+                    logger.info("trust chain validated X509 public key " + 
signingcert.getSubjectDN().toString());
+                }
+                return verifySignature(docElement, signingcert.getPublicKey(), 
OutErrorMessage);
             }
+
+            //last chance validation
             logger.info("signature did not have an embedded X509 public key. 
reverting to user specified certificate");
             //cert wasn't included in the signature, revert to some other means
             KeyStore ks = 
KeyStore.getInstance(map.getProperty(SIGNATURE_KEYSTORE_FILETYPE));
@@ -412,8 +501,7 @@ public final class DigSigUtil {
                         (KeyStore.PrivateKeyEntry) 
ks.getEntry(map.getProperty(SIGNATURE_KEYSTORE_KEY_ALIAS),
                         new 
KeyStore.PasswordProtection(map.getProperty(SIGNATURE_KEYSTORE_KEY_PASSWORD).toCharArray()));
             }
-            //       PrivateKey privateKey = keyEntry.getPrivateKey();
-            //TODO replace this by finding the certificate in the xml doc
+
 
             Certificate origCert = keyEntry.getCertificate();
             if (map.containsKey(CHECK_TIMESTAMPS)) {
@@ -423,12 +511,40 @@ public final class DigSigUtil {
                 }
             }
             PublicKey validatingKey = origCert.getPublicKey();
-            return verifySignature(docElement, validatingKey);
+            return verifySignature(docElement, validatingKey, OutErrorMessage);
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            //throw new RuntimeException(e);
+            logger.error("Error caught validating signature", e);
+            OutErrorMessage.set(e.getMessage());
+            return false;
         }
     }
 
+    private KeyStore GetTrustStore() throws Exception {
+        KeyStore ks = 
KeyStore.getInstance(map.getProperty(TRUSTSTORE_FILETYPE));
+        URL url = 
Thread.currentThread().getContextClassLoader().getResource(map.getProperty(TRUSTSTORE_FILE));
+        if (url == null) {
+            try {
+                url = new 
File(map.getProperty(TRUSTSTORE_FILE)).toURI().toURL();
+            } catch (Exception x) {
+            }
+        }
+        if (url == null) {
+            try {
+                url = 
this.getClass().getClassLoader().getResource(map.getProperty(TRUSTSTORE_FILE));
+            } catch (Exception x) {
+            }
+        }
+        if 
(!map.getProperty(TRUSTSTORE_FILETYPE).equalsIgnoreCase("WINDOWS-ROOT")) {
+            ks.load(url.openStream(), 
(map.getProperty(TRUSTSTORE_FILE_PASSWORD)).toCharArray());
+        } else {
+            //Windows only
+            ks.load(null, null);
+        }
+
+        return ks;
+    }
+
     private XMLSignatureFactory initXMLSigFactory() {
         XMLSignatureFactory fac = XMLSignatureFactory.getInstance();
         return fac;
@@ -461,13 +577,15 @@ public final class DigSigUtil {
         SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(
                 cm,
                 (C14NMethodParameterSpec) null),
-                fac.newSignatureMethod(SignatureMethod.DSA_SHA1,
+                fac.newSignatureMethod(sigmethod,
                 null), Collections.singletonList(ref));
         return si;
     }
 
-    private boolean verifySignature(Element element, PublicKey validatingKey) {
-
+    private boolean verifySignature(Element element, PublicKey validatingKey, 
AtomicReference<String> OutReadableErrorMessage) {
+        if (OutReadableErrorMessage == null) {
+            OutReadableErrorMessage = new AtomicReference<String>();
+        }
         XMLSignatureFactory fac = initXMLSigFactory();
         NodeList nl = element.getElementsByTagNameNS(XMLSignature.XMLNS, 
"Signature");
         if (nl.getLength() == 0) {
@@ -483,6 +601,7 @@ public final class DigSigUtil {
                 logger.warn("Signature failed core validation");
                 boolean sv = 
signature.getSignatureValue().validate(valContext);
                 logger.debug("signature validation status: " + sv);
+                OutReadableErrorMessage.set("signature validation failed: " + 
sv);
                 // Check the validation status of each Reference.
                 @SuppressWarnings("unchecked")
                 Iterator<Reference> i = 
signature.getSignedInfo().getReferences().iterator();
@@ -492,6 +611,9 @@ public final class DigSigUtil {
                     boolean refValid = ref.validate(valContext);
                     logger.debug(j);
                     logger.debug("ref[" + j + "] validity status: " + 
refValid);
+                    if (!refValid) {
+                        OutReadableErrorMessage.set("signature reference " + j 
+ " invalid");
+                    }
                     logger.debug("Ref type: " + ref.getType() + ", URI: " + 
ref.getURI());
                     for (Object xform : ref.getTransforms()) {
                         logger.debug("Transform: " + xform);
@@ -500,6 +622,9 @@ public final class DigSigUtil {
                     String expectedDigValStr = 
digestToString(ref.getDigestValue());
                     logger.warn("    Calc Digest: " + calcDigValStr);
                     logger.warn("Expected Digest: " + expectedDigValStr);
+                    if (!calcDigValStr.equalsIgnoreCase(expectedDigValStr)) {
+                        OutReadableErrorMessage.set("digest mismatch for 
signature ref " + j);
+                    }
                     /*InputStream is = ref.getDigestInputStream();
                      InputStreamReader isr = new InputStreamReader(is);
                      BufferedReader br = new BufferedReader(isr);
@@ -515,6 +640,7 @@ public final class DigSigUtil {
             }
             return coreValidity;
         } catch (Exception e) {
+            OutReadableErrorMessage.set("signature validation failed: " + 
e.getMessage());
             logger.fatal(e);
             return false;
         }
@@ -591,4 +717,47 @@ public final class DigSigUtil {
             throw new RuntimeException(e);
         }
     }
+
+    /**
+     *
+     * @param childNodes
+     * @return null or the public key of a signing certificate
+     */
+    private X509Certificate FindCert(NodeList childNodes) {
+
+
+        return null;
+    }
+
+    private X509Certificate FindCertByDN(X500Principal name) throws Exception {
+        KeyStore ks = GetTrustStore();
+        Enumeration<String> aliases = ks.aliases();
+        while (aliases.hasMoreElements()) {
+            String nextElement = aliases.nextElement();
+            Certificate certificate = ks.getCertificate(nextElement);
+            X509Certificate x = (X509Certificate) certificate;
+            if (x.getSubjectX500Principal().equals(name)) {
+                return x;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Downloads a CRL from given HTTP/HTTPS/FTP URL, e.g.
+     * http://crl.infonotary.com/crl/identity-ca.crl
+     */
+    private X509CRL downloadCRLFromWeb(String crlURL)
+            throws MalformedURLException, IOException, CertificateException,
+            CRLException {
+        URL url = new URL(crlURL);
+        InputStream crlStream = url.openStream();
+        try {
+            // CertificateFactory cf = CertificateFactory.getInstance("X.509");
+            X509CRL crl = (X509CRL) cf.generateCRL(crlStream);
+            return crl;
+        } finally {
+            crlStream.close();
+        }
+    }
 }

Propchange: juddi/branches/juddi-3.2.x/juddi-gui-dsig/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Apr 11 00:46:59 2013
@@ -0,0 +1,2 @@
+build
+dist

Propchange: juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Apr 11 00:46:59 2013
@@ -0,0 +1 @@
+private

Modified: juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/build-impl.xml
URL: 
http://svn.apache.org/viewvc/juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/build-impl.xml?rev=1466744&r1=1466743&r2=1466744&view=diff
==============================================================================
--- juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/build-impl.xml 
(original)
+++ juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/build-impl.xml Thu Apr 
11 00:46:59 2013
@@ -371,6 +371,11 @@ is divided into following sections:
             </and>
         </condition>
     </target>
+    <target name="-init-test-properties">
+        <property name="test.binaryincludes" value="&lt;nothing&gt;"/>
+        <property name="test.binarytestincludes" value=""/>
+        <property name="test.binaryexcludes" value=""/>
+    </target>
     <target if="${nb.junit.single}" name="-init-macrodef-junit-single" 
unless="${nb.junit.batch}">
         <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3";>
             <attribute default="${includes}" name="includes"/>
@@ -394,7 +399,7 @@ is divided into following sections:
             </sequential>
         </macrodef>
     </target>
-    <target if="${nb.junit.batch}" name="-init-macrodef-junit-batch" 
unless="${nb.junit.single}">
+    <target depends="-init-test-properties" if="${nb.junit.batch}" 
name="-init-macrodef-junit-batch" unless="${nb.junit.single}">
         <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3";>
             <attribute default="${includes}" name="includes"/>
             <attribute default="${excludes}" name="excludes"/>
@@ -408,6 +413,9 @@ is divided into following sections:
                         <fileset dir="${test.src.dir}" 
excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
+                        <fileset dir="${build.test.classes.dir}" 
excludes="@{excludes},${excludes},${test.binaryexcludes}" 
includes="${test.binaryincludes}">
+                            <filename name="${test.binarytestincludes}"/>
+                        </fileset>
                     </batchtest>
                     <syspropertyset>
                         <propertyref prefix="test-sys-prop."/>
@@ -535,7 +543,7 @@ is divided into following sections:
             </sequential>
         </macrodef>
     </target>
-    <target if="${nb.junit.batch}" name="-init-macrodef-junit-debug-batch">
+    <target depends="-init-test-properties" if="${nb.junit.batch}" 
name="-init-macrodef-junit-debug-batch">
         <macrodef name="junit-debug" 
uri="http://www.netbeans.org/ns/j2se-project/3";>
             <attribute default="${includes}" name="includes"/>
             <attribute default="${excludes}" name="excludes"/>
@@ -549,6 +557,9 @@ is divided into following sections:
                         <fileset dir="${test.src.dir}" 
excludes="@{excludes},${excludes}" includes="@{includes}">
                             <filename name="@{testincludes}"/>
                         </fileset>
+                        <fileset dir="${build.test.classes.dir}" 
excludes="@{excludes},${excludes},${test.binaryexcludes}" 
includes="${test.binaryincludes}">
+                            <filename name="${test.binarytestincludes}"/>
+                        </fileset>
                     </batchtest>
                     <syspropertyset>
                         <propertyref prefix="test-sys-prop."/>
@@ -921,7 +932,7 @@ is divided into following sections:
     <target if="has.persistence.xml" name="-copy-persistence-xml">
         <mkdir dir="${build.classes.dir}/META-INF"/>
         <copy todir="${build.classes.dir}/META-INF">
-            <fileset dir="${meta.inf.dir}" includes="persistence.xml"/>
+            <fileset dir="${meta.inf.dir}" includes="persistence.xml orm.xml"/>
         </copy>
     </target>
     <target name="-post-compile">

Modified: 
juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/genfiles.properties
URL: 
http://svn.apache.org/viewvc/juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/genfiles.properties?rev=1466744&r1=1466743&r2=1466744&view=diff
==============================================================================
--- juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/genfiles.properties 
(original)
+++ juddi/branches/juddi-3.2.x/juddi-gui-dsig/nbproject/genfiles.properties Thu 
Apr 11 00:46:59 2013
@@ -4,5 +4,5 @@ [email protected]
 # This file is used by a NetBeans-based IDE to track changes in generated 
files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never 
regenerate such files for you.
 nbproject/build-impl.xml.data.CRC32=64b6f61b
-nbproject/build-impl.xml.script.CRC32=6e5a9720
-nbproject/[email protected]
+nbproject/build-impl.xml.script.CRC32=74dd8af2
+nbproject/[email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to