JDK-8017265 : XMLSignature Cannot Resolve ID
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.xml.crypto
  • Affected Version: 7u25
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_7
  • Submitted: 2013-06-20
  • Updated: 2013-06-21
  • Resolved: 2013-06-21
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version  " 1.7.0_25 " 
Java(TM) SE Runtime Environment (build 1.7.0_25-b16)
Java HotSpot(TM) Client VM (build 23.25-b01, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Versi?n 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
The XMLSignature when signs a SignedInfo with NODE references such as #ID_NODE, does not resolve the element with the ID_NODE.

It is working OK in version J7U21, the Version J7U25 has the problem.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Just follow the oracle tutorial:

http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/XMLDigitalSignatureAPI8.html

But Sign an XMLNode using the ID as references, ie:
<a><b ID='toSign'></b></a>

Reference ref = fac.newReference
  ( " #toSign " , fac.newDigestMethod(DigestMethod.SHA1, null),
    Collections.singletonList
      (fac.newTransform(Transform.ENVELOPED,
        (TransformParameterSpec) null)), null, null);

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
In Java 7U21 --> It is working ok
in Java 7U25 -->  com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID toSign
ACTUAL -
Cannot resolve element with ID toSign --> The XML Doc cannot be signed

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread  " main "  javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID toSign
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMReference.digest(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(Unknown Source)
at xmlSign.main(xmlSign.java:87)
Caused by: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID toSign
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(Unknown Source)
... 5 more
Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID toSign
at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolve(Unknown Source)
at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(Unknown Source)
... 6 more
javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID toSign
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMReference.digest(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(Unknown Source)
at xmlSign.main(xmlSign.java:87)
Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID toSign
at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolve(Unknown Source)
at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(Unknown Source)
... 6 more


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;

import javax.xml.crypto.MarshalException;
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.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;



public class xmlSign {

/**
 * @param args
 * @throws ParserConfigurationException
 * @throws IOException
 * @throws SAXException
 * @throws NoSuchAlgorithmException
 * @throws InvalidAlgorithmParameterException
 * @throws KeyException
 * @throws XMLSignatureException
 * @throws MarshalException
 * @throws TransformerException
 */
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, KeyException, MarshalException, XMLSignatureException, TransformerException {
DocumentBuilderFactory dbf =
  DocumentBuilderFactory.newInstance();

dbf.setNamespaceAware(true);

DocumentBuilder builder = dbf.newDocumentBuilder();

//The XML with a ID Node labeled as toSign
ByteArrayInputStream is = new ByteArrayInputStream( " <a><b ID='toSign'></b></a> " .getBytes());
Document doc = builder.parse(is);

KeyPairGenerator kpg = KeyPairGenerator.getInstance( " DSA " );
kpg.initialize(512);
KeyPair kp = kpg.generateKeyPair();

DOMSignContext dsc = new DOMSignContext
  (kp.getPrivate(), doc.getDocumentElement());
XMLSignatureFactory fac =
  XMLSignatureFactory.getInstance( " DOM " );

//The reference to be signed usign URI #toSign
Reference ref = fac.newReference
  ( " #toSign " , fac.newDigestMethod(DigestMethod.SHA1, null),
    Collections.singletonList
      (fac.newTransform(Transform.ENVELOPED,
        (TransformParameterSpec) null)), null, null);

SignedInfo si = fac.newSignedInfo
  (fac.newCanonicalizationMethod
    (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
      (C14NMethodParameterSpec) null),
    fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null),
    Collections.singletonList(ref));

KeyInfoFactory kif = fac.getKeyInfoFactory();

KeyValue kv = kif.newKeyValue(kp.getPublic());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));

XMLSignature signature = fac.newXMLSignature(si, ki);

//Sign the documento this is not working at Java 7U25
signature.sign(dsc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(System.out));
}

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Just use J7u21

SUPPORT :
YES
Comments
The previous code which arbitrarily searched for ID references by the name of "Id" has been removed because it was insecure and is subject to XML Signature wrapping attacks. There are 3 potential workarounds that you can apply: 1. Use a validating schema which will register the elements with ID references. 2. Register the ID elements with the DOMValidateContext.setIdAttributeNS method before validating the signature 3. Implement a custom URIDereferencer which can find these references and override the builtin URIDereferencer with the DOMValidateContext.setURIDereferencer method. We will open a separate doc bug to have the tutorial fixed.
21-06-2013