Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
FULL PRODUCT VERSION : java version " 1.7.0_25 " Java(TM) SE Runtime Environment (build 1.7.0_25-b16) Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode) ADDITIONAL OS VERSION INFORMATION : Windows 7 Professional, 64-bit A DESCRIPTION OF THE PROBLEM : XML signature validation code that functions in jre170_21 and earlier, breaks in the latest release. This pertains to signatures for manifest items, referenced by xmldsig:id attributes in the XML document. The XML signature validation source code is available here: https://raw.github.com/joval/jOVAL/master/src/org/joval/xml/SignatureValidator.java A Java keystore file containing the NIST certificate is available here: https://github.com/joval/jOVAL/raw/master/components/jovaldi/rsrc/security/cacerts.jks I am attempting to validate the XML documents contained here (specifically scap_gov.nist_USGCB-Windows-7.xml): http://usgcb.nist.gov/usgcb/content/scap/oval510/Win7-510-1.2.7.1.zip REGRESSION. Last worked in version 6u45 STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Instantiate an org.joval.xml.SignatureValidator with the XML file and keystore backed by the file I referenced above, and invoke the validate() method. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - The method should return true. ACTUAL - An XMLSignatureException is thrown. ERROR MESSAGES/STACK TRACES THAT OCCUR : 2013.06.19 22:46:16.588 - INFO - Verifying XML digital signature: ..\..\..\..\content\scap12\scap_gov.nist_USGCB-Windows-7.xml 2013.06.19 22:46:17.334 - SEVERE - javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID scap_gov.nist_datastream_USGCB-Windows-7-1.2.3.1.zip org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:412) org.jcp.xml.dsig.internal.dom.DOMReference.validate(DOMReference.java:371) org.jcp.xml.dsig.internal.dom.DOMXMLSignature.validate(DOMXMLSignature.java:265) org.joval.xml.SignatureValidator.validate(SignatureValidator.java:104) org.joval.scap.xccdf.engine.XPERT.main(XPERT.java:283) caused by: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID scap_gov.nist_datastream_USGCB-Windows-7-1.2.3.1.zip org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:124) org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:404) org.jcp.xml.dsig.internal.dom.DOMReference.validate(DOMReference.java:371) org.jcp.xml.dsig.internal.dom.DOMXMLSignature.validate(DOMXMLSignature.java:265) org.joval.xml.SignatureValidator.validate(SignatureValidator.java:104) org.joval.scap.xccdf.engine.XPERT.main(XPERT.java:283) caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID scap_gov.nist_datastream_USGCB-Windows-7-1.2.3.1.zip com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolve(ResolverFragment.java:90) com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:283) org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:117) org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:404) org.jcp.xml.dsig.internal.dom.DOMReference.validate(DOMReference.java:371) org.jcp.xml.dsig.internal.dom.DOMXMLSignature.validate(DOMXMLSignature.java:265) org.joval.xml.SignatureValidator.validate(SignatureValidator.java:104) org.joval.scap.xccdf.engine.XPERT.main(XPERT.java:283) REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- // Copyright (C) 2012 jOVAL.org. All rights reserved. // This software is licensed under the AGPL 3.0 license available at http://www.joval.org/agpl_v3.txt package org.joval.xml; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Enumeration; import java.util.NoSuchElementException; import java.security.Key; import java.security.KeyException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.PublicKey; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.CertSelector; import java.security.cert.X509Certificate; import java.security.cert.X509CertSelector; import javax.security.auth.x500.X500Principal; import javax.xml.XMLConstants; import javax.xml.crypto.AlgorithmMethod; import javax.xml.crypto.KeySelector; import javax.xml.crypto.KeySelectorException; import javax.xml.crypto.KeySelectorResult; import javax.xml.crypto.MarshalException; import javax.xml.crypto.NoSuchMechanismException; import javax.xml.crypto.NodeSetData; import javax.xml.crypto.OctetStreamData; import javax.xml.crypto.XMLCryptoContext; import javax.xml.crypto.XMLStructure; import javax.xml.crypto.dsig.SignatureMethod; import javax.xml.crypto.dsig.XMLSignature; import javax.xml.crypto.dsig.XMLSignatureException; import javax.xml.crypto.dsig.XMLSignatureFactory; import javax.xml.crypto.dsig.dom.DOMValidateContext; import javax.xml.crypto.dsig.keyinfo.KeyInfo; import javax.xml.crypto.dsig.keyinfo.KeyName; import javax.xml.crypto.dsig.keyinfo.KeyValue; import javax.xml.crypto.dsig.keyinfo.RetrievalMethod; import javax.xml.crypto.dsig.keyinfo.X509Data; import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; import org.xml.sax.SAXException; import org.w3c.dom.Document; import org.w3c.dom.NodeList; /** * Utility class for validating XML digital signatures. * @see http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/XMLDigitalSignatureAPI8.html * * @author David A. Solin * @version %I% %G% */ public class SignatureValidator { private Document doc; private NodeList signatures; private KeyStore keyStore; /** * Create a new validator for the specified XML file using the specified KeyStore. */ public SignatureValidator(File f, KeyStore keyStore) throws FactoryConfigurationError, ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); doc = dbf.newDocumentBuilder().parse(f); signatures = doc.getElementsByTagNameNS(XMLSignature.XMLNS, " Signature " ); this.keyStore = keyStore; } /** * Assign a specific KeyStore to be used for validation. */ public void setKeyStore(KeyStore keyStore) { this.keyStore = keyStore; } /** * Returns whether or not there is an XML signature node in the document. */ public boolean containsSignature() { return signatures.getLength() > 0; } /** * Validate the document's XML digital signature. */ public boolean validate() throws XMLSignatureException { int len = signatures.getLength(); if (len == 0) { throw new XMLSignatureException( " Cannot find Signature element " ); } else { try { for (int i=0; i < len; i++) { DOMValidateContext ctx = new DOMValidateContext(new X509KeySelector(), signatures.item(i)); XMLSignature signature = XMLSignatureFactory.getInstance().unmarshalXMLSignature(ctx); if (!signature.validate(ctx)) { return false; } } return true; } catch (NoSuchMechanismException e) { throw new XMLSignatureException(e); } catch (ClassCastException e) { throw new XMLSignatureException(e); } catch (MarshalException e) { throw new XMLSignatureException(e); } } } /** * Validate the document's XML digital signature using the supplied public key. */ public boolean validate(Key validationKey) throws XMLSignatureException { int len = signatures.getLength(); if (len == 0) { throw new XMLSignatureException( " Cannot find Signature element " ); } else { try { for (int i=0; i < len; i++) { DOMValidateContext ctx = new DOMValidateContext(validationKey, signatures.item(i)); XMLSignature signature = XMLSignatureFactory.getInstance().unmarshalXMLSignature(ctx); if (!signature.validate(ctx)) { return false; } } return true; } catch (NoSuchMechanismException e) { throw new XMLSignatureException(e); } catch (ClassCastException e) { throw new XMLSignatureException(e); } catch (MarshalException e) { throw new XMLSignatureException(e); } } } /** * Obtain a Source for the document. This makes it possible to insure that the underlying data has been validated. */ public Source getSource() { return new DOMSource(doc); } // Private /** * KeySelector implementation for X.509 certificates. */ class X509KeySelector extends KeySelector { @Override public KeySelectorResult select(KeyInfo ki, KeySelector.Purpose p, AlgorithmMethod am, XMLCryptoContext ctx) throws KeySelectorException { KeySelectorResult result = null; SignatureMethod sm = (SignatureMethod)am; for (Object obj : ki.getContent()) { XMLStructure xs = (XMLStructure)obj; if (xs instanceof X509Data) { result = select((X509Data)xs, sm); } else if (xs instanceof KeyName) { KeyName kn = (KeyName)xs; try { Certificate cert = keyStore.getCertificate(kn.getName()); if (cert != null && equals(sm.getAlgorithm(), cert.getPublicKey().getAlgorithm())) { result = new SimpleKeySelectorResult(cert.getPublicKey()); } } catch (KeyStoreException e) { throw new KeySelectorException(e); } } else if (xs instanceof RetrievalMethod) { RetrievalMethod rm = (RetrievalMethod)xs; try { if (rm.getType().equals(X509Data.RAW_X509_CERTIFICATE_TYPE)) { OctetStreamData data = (OctetStreamData)rm.dereference(ctx); CertificateFactory cf = CertificateFactory.getInstance( " X.509 " ); X509Certificate cert = (X509Certificate)cf.generateCertificate(data.getOctetStream()); result = select(cert, sm); } else if (rm.getType().equals(X509Data.TYPE)) { NodeSetData nd = (NodeSetData)rm.dereference(ctx); System.out.println( " DAS conversion is TBD " ); } } catch (Exception e) { throw new KeySelectorException(e); } } else if (xs instanceof KeyValue) { PublicKey pk = null; try { pk = ((KeyValue)xs).getPublicKey(); } catch (KeyException ke) { throw new KeySelectorException(ke); } if (equals(sm.getAlgorithm(), pk.getAlgorithm())) { result = new SimpleKeySelectorResult(pk); } } if (result != null) { return result; } } throw new KeySelectorException( " Key not found " ); } // Internal KeySelectorResult select(X509Data data, SignatureMethod sm) throws KeySelectorException { String oid = getOid(sm.getAlgorithm()); KeySelectorResult result = null; for (Object obj : data.getContent()) { try { if (obj instanceof X509Certificate) { return select((X509Certificate)obj, sm); } else if (obj instanceof X509IssuerSerial) { X509IssuerSerial xis = (X509IssuerSerial)obj; X509CertSelector xcs = new X509CertSelector(); xcs.setSubjectPublicKeyAlgID(oid); xcs.setSerialNumber(xis.getSerialNumber()); xcs.setIssuer(new X500Principal(xis.getIssuerName()).getName()); return select(xcs); } else if (obj instanceof String) { String sn = (String)obj; X509CertSelector xcs = new X509CertSelector(); xcs.setSubjectPublicKeyAlgID(oid); xcs.setSubject(new X500Principal(sn).getName()); return select(xcs); } else if (obj instanceof byte[]) { byte[] ski = (byte[])obj; X509CertSelector xcs = new X509CertSelector(); xcs.setSubjectPublicKeyAlgID(oid); byte[] encodedSki = new byte[ski.length+2]; encodedSki[0] = 0x04; // OCTET STRING tag value encodedSki[1] = (byte)ski.length; System.arraycopy(ski, 0, encodedSki, 2, ski.length); xcs.setSubjectKeyIdentifier(encodedSki); return select(xcs); } } catch (IOException e) { throw new KeySelectorException(e); } catch (KeyStoreException e) { throw new KeySelectorException(e); } catch (NoSuchElementException e) { throw new KeySelectorException(e); } } return null; } /** * Return the certificate in the key store that matches the specified selector * * @throws NoSuchElementException if there is no match */ KeySelectorResult select(X509CertSelector cs) throws KeyStoreException, NoSuchElementException { for (Enumeration e = keyStore.aliases(); e.hasMoreElements(); ) { Certificate cert = keyStore.getCertificate((String)e.nextElement()); if (cert != null && cs.match(cert)) { return new SimpleKeySelectorResult(cert.getPublicKey()); } } throw new NoSuchElementException(cs.getSubject().toString()); } /** * Return the certificate in the key store that matches the specified X509 certificate (or null if there is no match). * * @throws NoSuchElementException if there is no match */ KeySelectorResult select(X509Certificate xc, SignatureMethod sm) throws KeyStoreException, NoSuchElementException { boolean[] keyUsage = xc.getKeyUsage(); if (keyUsage[0]) { String alias = keyStore.getCertificateAlias(xc); if (alias != null) { PublicKey pk = keyStore.getCertificate(alias).getPublicKey(); if (equals(sm.getAlgorithm(), pk.getAlgorithm())) { return new SimpleKeySelectorResult(pk); } } } throw new NoSuchElementException(xc.getSubjectX500Principal().toString()); } /** * Return the OID corresponding to the Algorithm URI. */ String getOid(String uri) { if (uri.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) { return " 1.2.840.10040.4.1 " ; } else if (uri.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) { return " 1.2.840.113549.1.1 " ; } else { return null; } } /** * Determine whether the algorithm URI matches the algorithm name. */ boolean equals(String uri, String name) { if (name.equalsIgnoreCase( " DSA " ) && uri.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) { return true; } else if (name.equalsIgnoreCase( " RSA " ) && uri.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) { return true; } else { return false; } } } /** * A simple KeySelectorResult implementation. */ static class SimpleKeySelectorResult implements KeySelectorResult { private Key key; SimpleKeySelectorResult(Key key) { this.key = key; } // Implement KeySelectorResult public Key getKey() { return key; } } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : We will have to distribute our application with an earlier release of Java, such as 170_21.
|