Skip to main content

Generating an enveloped digital signature on a partial in-memory XML file

3 replies [Last post]
franknatoli
Offline
Joined: 2007-04-13
Points: 0

Need to generate an enveloped signature on one branch of an XML file that I am building in memory courtesy of JAXB objects. The JWSDP 2.0 sample GenEnveloped.java works great, but its call to the XMLSignatureFactory newReference method uses a first argument of "", which implies the entire document, not a particular branch. And its call to the DocumentBuilderFactory newDocumentBuilder parse method uses an argument of a FileInputStream, i.e., an existing disk file, not an in memory document.

Can an enveloped signature be created for an in memory document, that does not [yet] exist on the disk? If so, are there any source examples of such a construct?

Are there any source examples of referencing a particular branch of an XML file?

Many thanks for any help.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
franknatoli
Offline
Joined: 2007-04-13
Points: 0

I've solved half of this problem.

Much literature notes that one can reference a particular point in an XML file by using the construct "#name", where "name" is the particular point of interest in the XML file. Therefore, it seemed appropriate that the call to XMLSignatureFactory newReference use a first argument of "#name". My problem was that I could not find a single example on the web of how "name" related to any particular point in an XML file. The answer is that some element in the XML file needs to declare "id" attribute of "name". For example:



abc


xyz

The above XML file has two elements, named "Branch1" and "Branch2". If one wants to generate an enveloped digital signature for the information in "Branch1" [not the entire file] it is necessary to provide element "Branch1" with some unique "id" attribute, in this case "fjn1". Given such a declaration, the following code in JWSDP 2.0 XMLDSIG Sample GenEnveloped.java works great:

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

That said, the other half of my problem remains: can I generate an enveloped digital signature on an in-memory JAXB object? Or is it necessary to marshall and thus write out the entire JAXB object and then generate an enveloped digital signature on the particular point of interest in the XML file?

One more point: since I have not yet figured out how to generate an enveloped digital signature on an in-memory JAXB object, I have taken the recourse of marshalling and thus writing out the entire JAXB object and then generating an enveloped digital signature on the particular point of interest in the XML file. I can perform a transform and generate a stream result, which generates an entirely new XML file with a new object. All fine and dandy. But I would really like to put that new object well inside the XML structure, not at the top level, as the XMLDSIG API does. If I instead use a transform to generate a JAXBResult, that "works", but the JAXBResult is the entire XML file, not just the new object. So now, a new question: can the XMLDSIG API be directed to generate a JAXBResult that solely consists of the enveloped object?

Thanks.

amique
Offline
Joined: 2009-12-01
Points: 0

franknatoli wrote:

The above XML file has two elements, named "Branch1" and "Branch2". If one wants to generate an enveloped digital signature for the information in "Branch1" [not the entire file] it is necessary to provide element "Branch1" with some unique "id" attribute, in this case "fjn1". Given such a declaration, the following code in JWSDP 2.0 XMLDSIG Sample GenEnveloped.java works great:
.

I want to achieve the same (signing a particular xml branch) but in my case that branch dont has id element. Is there any way to achieve this using element name.

franknatoli
Offline
Joined: 2007-04-13
Points: 0

I've solved the other half of this problem.

Sun sample GenEnveloped.java contains the following code:

// Create a DOMSignContext and set the signing Key to the DSA
// PrivateKey and specify where the XMLSignature should be inserted
// in the target document (in this case, the document root)
DOMSignContext signContext = new DOMSignContext(privateKey, doc.getDocumentElement());

As usual with all Sun samples, the simplest context is implemented, in this case, inserting the enveloped signature at the top level of the document, accomplished by second argument "doc.getDocumentElement()". My problem was inserting the enveloped signature well inside the document (XML file). I have accomplished this by replacing the above statement with the following:

// get top element of document
Element element = doc.getDocumentElement();
if (element == null)
throw new MyException("getDocumentElement failure");
// find ns2:level2
Node node = element.getFirstChild();
while (node != null)
{
if (node.getNodeName().equals("ns2:level2"))
break;
node = node.getNextSibling();
}
if (node == null)
throw new MyException("Cannot find ns2:level2");
// find ns2:level3
node = node.getFirstChild();
while (node != null)
{
if (node.getNodeName().equals("ns2:level3"))
break;
node = node.getNextSibling();
}
if (node == null)
throw new MyException("Cannot find ns2:level3");
// find ns2:level4
node = node.getFirstChild();
while (node != null)
{
if (node.getNodeName().equals("ns2:level4"))
break;
node = node.getNextSibling();
}
if (node == null)
throw new MyException("Cannot find ns2:level4");
// create signing context pointing to level2.level3.level4
DOMSignContext signContext = new DOMSignContext(privateKey, node);

Of course, "level2, "level3" and "level4" refer to actual tags in the XML file that are nesting within the outer element.

Having implemented the above, Java XMLDSIG API happily complies and places the enveloped signature within element "level4" rather than at the top level of the document.

I suspect there is a more elegant way of specifying that second argument to DOMSignContext, rather than laboriously chasing down the various levels of the document, but I don't know it.

It would be very, very helpful if Sun provided something more than the simplest sample code with the most generic method arguments and/or someone watching these forums for people in need of such advice.