I'm trying to sign an xml file using enveloped signature and javax.xml.crypto.dsig.* classes. As a result I get file with correct Signature content but with no namespace defined. How can I add xmlns:ds="http://www.w3.org/2000/09/xmldsig#" namespace and corresponding ds prefixes? I don't see any place where I could define it.
Example code:
XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM");
(...)
XMLSignature signature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo);
// Marshal, generate, and sign the enveloped signature.
signature.sign(domSignContext);
gives example XML:
<?xml version="1.0" encoding="UTF-8"?>
<test xmlns="http://different.namespace.com">
<someBody/>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>base64_digest</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>some_base64</SignatureValue>
<KeyInfo>
<X509Data>
<X509SubjectName>subject_data</X509SubjectName>
<X509Certificate>some_more_base64</X509Certificate>
</X509Data>
<KeyValue>
<RSAKeyValue>
<Modulus>another_base64</Modulus>
<Exponent>base64_as_well</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
</Signature>
</test>
but I want:
<?xml version="1.0" encoding="UTF-8"?>
<test xmlns="http://different.namespace.com" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<someBody/>
<ds:Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>base64_digest</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>some_base64</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509SubjectName>subject_data</ds:X509SubjectName>
<ds:X509Certificate>some_more_base64</ds:X509Certificate>
</ds:X509Data>
<ds:KeyValue>
<ds:RSAKeyValue>
<ds:Modulus>another_base64</ds:Modulus>
<ds:Exponent>base64_as_well</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
</ds:Signature>
</test>
XML namespaces associate element and attribute names in an XML document with custom and predefined URIs. To create these associations, you define prefixes for namespace URIs, and use those prefixes to qualify element and attribute names in XML data.
For example, the XsltContext class uses XmlNamespaceManager for XPath support. The namespace manager doesn't perform any validation on the namespaces, but assumes that prefixes and namespaces have already been verified and conform to the W3C Namespaces specification.
One of the significant new features of the Java Platform, Standard Edition 6 (Java SE 6) is the Java XML Digital Signature API. This API allows you to generate and validate XML signatures.
XML Namespace configuration has been available since Spring Security 2.0. In Spring Framework, A namespace element is nothing but it is a more concise way of configuring an individual bean or, more powerfully, to define an alternative configuration syntax.
Below is the sample code from Oracle for generating enveloped signature. And i guess what you are looking for is dsc.setDefaultNamespacePrefix("dsig"); as shown in the example below.
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
Reference ref = fac.newReference
("", fac.newDigestMethod(DigestMethod.SHA1, null),
Collections.singletonList
(fac.newTransform
(Transform.ENVELOPED, (TransformParameterSpec) null)),
null, null);
// Create the SignedInfo
SignedInfo si = fac.newSignedInfo
(fac.newCanonicalizationMethod
(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
(C14NMethodParameterSpec) null),
fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null),
Collections.singletonList(ref));
// Create a DSA KeyPair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(512);
KeyPair kp = kpg.generateKeyPair();
// Create a KeyValue containing the DSA PublicKey that was generated
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(kp.getPublic());
// Create a KeyInfo and add the KeyValue to it
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
// Instantiate the document to be signed
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(sourceFile));
// Create a DOMSignContext and specify the DSA PrivateKey and
// location of the resulting XMLSignature's parent element
DOMSignContext dsc = new DOMSignContext(kp.getPrivate(), doc.getDocumentElement());
dsc.setDefaultNamespacePrefix("dsig");
// Create the XMLSignature (but don't sign it yet)
XMLSignature signature = fac.newXMLSignature(si, ki);
// Marshal, generate (and sign) the enveloped signature
signature.sign(dsc);
// output the resulting document
OutputStream os;
os = new FileOutputStream(DestinationFile);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(os));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With