Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8368678

XML Namespace declaration missing in input for digest when adding SignatureProperties

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      Ubuntu 24.04 on x86_64

      Tested Temurin 21:

      openjdk version "21.0.8" 2025-07-15 LTS
      OpenJDK Runtime Environment Temurin-21.0.8+9 (build 21.0.8+9-LTS)
      OpenJDK 64-Bit Server VM Temurin-21.0.8+9 (build 21.0.8+9-LTS, mixed mode, sharing)

      and switched to 25 today in case my issue was already fixed:
      openjdk 25 2025-09-16 LTS
      OpenJDK Runtime Environment Temurin-25+36 (build 25+36-LTS)
      OpenJDK 64-Bit Server VM Temurin-25+36 (build 25+36-LTS, mixed mode, sharing)



      A DESCRIPTION OF THE PROBLEM :
      I'm using the XMLSignatureFactory to create a Signature with SignatureProperties. The SignatureProperty contains a Timestamp element from this namespace "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd".

      When the digest computation of this SignatureProperty is prepared, the namespace is not added during the canonicalisation and a wrong digest is computed.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      I provide a sanitized version of the source code with static values used for the SignatureProperties so the digest values are static.
      The XML file output looks perfectly fine, with the exception of the DigestValue for the Reference to the SignatureProperty.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Above code creates this as part of the final output, which is as expected:

      <Object><SignatureProperties><SignatureProperty Id="SignatureProperty_3205bd06-4f89-4c91-a99d-36bba026b8f3" Target="#Signature_d69345d0-6912-4027-82ee-3cf8baaa3f95"><ns1:Timestamp xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><ns1:Created>2025-08-05T13:49:29+00:00</ns1:Created></ns1:Timestamp></SignatureProperty></SignatureProperties></Object>

      Expected input to the digest computation is:

      <SignatureProperty xmlns="http://www.w3.org/2000/09/xmldsig#" Id="SignatureProperty_3205bd06-4f89-4c91-a99d-36bba026b8f3" Target="#Signature_d69345d0-6912-4027-82ee-3cf8baaa3f95"><ns1:Timestamp xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><ns1:Created>2025-08-05T13:49:29+00:00</ns1:Created></ns1:Timestamp></SignatureProperty>

      with this DigestValue

      OTrkBPF56k+HHldEGQtYBRUgA3XD7FaWRS5jV/2/5Ds=
      ACTUAL -
      Actual input to the digest computation is:

      <SignatureProperty xmlns="http://www.w3.org/2000/09/xmldsig#" Id="SignatureProperty_3205bd06-4f89-4c91-a99d-36bba026b8f3" Target="#Signature_d69345d0-6912-4027-82ee-3cf8baaa3f95"><ns1:Timestamp><ns1:Created>2025-08-05T13:49:29+00:00</ns1:Created></ns1:Timestamp></SignatureProperty>

      with this DigestValue

      JcFNsDbGHWMdXI5vJGRvJZ6AxRqO4gZ8kHaDQQ9p8Lw=

      The namespace declaration for the Timestamp element is missing.

      ---------- BEGIN SOURCE ----------
      import javax.xml.crypto.dsig.*;
      import javax.xml.crypto.dom.*;
      import javax.xml.crypto.dsig.dom.DOMSignContext;
      import javax.xml.crypto.dsig.keyinfo.*;
      import javax.xml.crypto.dsig.spec.*;
      import java.io.FileInputStream;
      import java.io.FileOutputStream;
      import java.io.OutputStream;
      import java.security.*;
      import java.util.ArrayList;
      import java.util.Collections;
      import java.util.List;
      import javax.xml.parsers.DocumentBuilderFactory;
      import javax.xml.transform.*;
      import javax.xml.transform.dom.DOMSource;
      import javax.xml.transform.stream.StreamResult;
      import org.w3c.dom.Document;
      import org.w3c.dom.Element;

      public class GenEnveloped {

          public static void main(String[] args) throws Exception {

              // Instantiate the document to be signed
              DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
              dbf.setNamespaceAware(true);
              Document doc = dbf.newDocumentBuilder().parse(new FileInputStream("envelope.xml"));
              //envelope.xml is just <Envelope xmlns="urn:envelope"></Envelope>
              
              // Create a DOM XMLSignatureFactory that will be used to generate the
              // enveloped signature
              XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

              // build SignatureProperties for the Timestamp element
              String timestampNS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
              Element timestamp = doc.createElementNS(timestampNS, "ns1:Timestamp");
              String created = "2025-08-05T13:49:29+00:00";
              timestamp.appendChild(doc.createElementNS(timestampNS, "ns1:Created")).setTextContent(created);
              DOMStructure domTimestamp = new DOMStructure(timestamp);
              String signatureId = "Signature_d69345d0-6912-4027-82ee-3cf8baaa3f95";
              String sigPropId = "SignatureProperty_3205bd06-4f89-4c91-a99d-36bba026b8f3";
              SignatureProperty sigProp = fac.newSignatureProperty
                  (Collections.singletonList(domTimestamp), "#"+signatureId, sigPropId);
              SignatureProperties sigProps = fac.newSignatureProperties(
                  Collections.singletonList(sigProp), null);

              Reference sigprop_reference = fac.newReference
                  ("#"+sigPropId,
                   fac.newDigestMethod(DigestMethod.SHA256, null),
                   Collections.singletonList
                      (fac.newTransform
                          (CanonicalizationMethod.EXCLUSIVE,
                           (TransformParameterSpec) null)),
                   null, null);

              List<XMLObject> xmlObjectList = new ArrayList<XMLObject>();
              xmlObjectList.add(fac.newXMLObject(Collections.singletonList(sigProps), null, null, null));
          
              // Create the SignedInfo
              SignedInfo si = fac.newSignedInfo
                  (fac.newCanonicalizationMethod
                   (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
                    (C14NMethodParameterSpec) null),
                   fac.newSignatureMethod(SignatureMethod.RSA_SHA256, null),
                   Collections.singletonList(sigprop_reference));

              // Create a KeyPair
              KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
              kpg.initialize(4096);
              KeyPair kp = kpg.generateKeyPair();
              KeyInfoFactory kif = fac.getKeyInfoFactory();
              KeyValue kv = kif.newKeyValue(kp.getPublic());
              KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
             
              // Create a DOMSignContext and specify the PrivateKey and
              // location of the resulting XMLSignature's parent element
              DOMSignContext dsc = new DOMSignContext
                  (kp.getPrivate(), doc.getDocumentElement());

              // Create the XMLSignature (but don't sign it yet)
              XMLSignature signature = fac.newXMLSignature(si, ki, xmlObjectList, signatureId, null);

              // Marshal, generate (and sign) the enveloped signature
              signature.sign(dsc);

              // output the resulting document
              OutputStream os = new FileOutputStream("signature.xml");

              TransformerFactory tf = TransformerFactory.newInstance();
              Transformer trans = tf.newTransformer();
              trans.transform(new DOMSource(doc), new StreamResult(os));
          }
      }
      ---------- END SOURCE ----------

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: