-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
11, 25
-
generic
-
generic
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 ----------
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 ----------