October 11, 2004

Securing Web services: Using XML signatures

Author: Jeffrey Vagle

An important consideration in the creation, deployment, and use of Web services is the message itself. Since Web services rely on the transmission and receipt of SOAP messages, the ability to verify the integrity and authenticity of these messages should have a rather high priority associated with it. Further, since Web services are often used to present commercial transaction interfaces to potential customers, message non-repudiation plays a key role in these scenarios. The XML Signature specification, a W3C/IETF effort, addresses these problems by providing a digital signature framework for XML documents based on standard public key cryptography notions, as discussed in an earlier article.The XML Signature specification allows for the use of digital signatures applied to arbitrary digital content, which includes XML-formatted text, providing message integrity, authentication, and non-repudiation services for any type of data -- quite a useful feature set to contribute to secure Web services.

The specification

Since XML signatures may be applied arbitrarily within an XML document, they can be used to sign more than one type of resource. Within XML documents, signatures are related to the data object that they sign through Uniform Resource Identifiers (URI) or local references. This means that the signed data object may either reside locally within the document or may be found elsewhere, as defined by a valid URI. XML digital signatures use the structure of the XML document to define these relationships.

XML signatures can be generally applied in three ways: detached, enveloping, and enveloped. Detached XML signatures can sign content external to the XML document itself, or they can be applied within the same XML document, where the XML signature and the data are sibling elements within that document. In either case, the data being signed is identified via a URI or XML transform. Enveloping XML signatures sign data contained within the Object element
of that signature. As in the detached example, a URI or XML transform is used to identify the data. Finally, the enveloped XML signature signs data that contains the signature itself as an element. Those of you familiar with digital signatures may be scratching your head at this one: how can a digital signature be applied to data that includes in it that very signature? Wouldn't signing the data object result in a change to that object, thus invalidating the signature? You can avoid this problem through careful definition of the signature calculation to exclude any portion of the signature itself in the signature creation.

Using combinations of the above approaches, XML signatures can be used to selectively sign only those portions of an XML document that need signatures, as opposed to the entire XML document. This gives us a great deal of flexilibility when it comes to signature usage and applications. For example, if an XML document is passed between multiple parties, each party may sign only those sections of the XML document that is relevant to it, or signatures may be nested as part of this process.

The structure of XML signatures is as follows:


(<Reference (URI=)? >





Note that the Reference element identifies the data or object being signed, the SignatureValue element carries the actual signature data, and the KeyInfo element may include certificate or public key data within the Signature element. If the XML signature is to be enveloping, the Object element may include the data to be signed (located via Reference).

Example: Creating an XML signature

Our examples will utilize the Apache Project's XML Security Java libraries, which contain implementations of XML Signature and XML Encryption. In addition to these libraries, you'll need to obtain a Java Cryptography Extension (JCE) implementation. As part of Apache's XML Security Java libraries you have the option of obtaining the BouncyCastle JCE provider during the Ant build/install process. Depending on where you live, you probably have other JCE options as well. Be sure to familiarize yourself with your local laws concerning cryptography export restrictions before you use it. Installation details for the XML Security package and supporting libraries are beyond the scope of this article; refer to each package's documentation. Finally, I'll assume you have a moderate familiarity with XML concepts.

In order to employ digital signatures of any kind, we need to set ourselves up with public/private keypairs. There are more than a few ways to go about this, and the details behind this topic can easily be found elsewhere. We discussed approaches to this topic using Java keystores in an earlier article, and we'll use those methods here.

For simplicity's sake, we leave details such as try/catch blocks and initialization out of our code examples.

The first step we'll take is to set up a few variables which define our keystore-related details:

keyStore = "/path/to/keystorefile";

String keyStoreType = "jks";
String keyStorePass = "password";
String keyAlias = "MyKeyName";

We assume here that the keystore password and the private key password are the same. Be sure to change the values for keyStore, keyStorePass, and keyAlias to values correct for your location. We now instantiate and load the Java KeyStore, obtaining the private key to be used for signatures:

ks = java.security.KeyStore.getInstance(keyStoreType);

java.io.FileInputStream in = new

ks.load(in, keyStorePass.toCharArray());
java.security.PrivateKey privKey =

We're ready to begin building our example XML document. The Java SDK provides a convenient DocumentBuilderFactory class which we'll use for this purpose.

docFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();

javax.xml.parsers.DocumentBuilder docBuilder =

org.w3c.dom.Document doc = docBuilder.newDocument();

Note that since XML signatures use XML namespaces, we tell our DocumentBuilderFactory
to be namespace-aware.

Now we'll create a simple XML document, containing only one Element with a child node for signature. In addition, we'll define a file to which we'll write our XML document.

element = doc.createElement("Foo");

org.w3c.dom.Text textNode = doc.createTextNode("This is a

java.io.File xmlFile = new File("/path/to/xmlfile.txt");

We've created our XML document, so now we're ready to create an XML signature, defining the base URI with our XML filename, and using RSA with SHA-1 as the signature method.

baseURI = xmlFile.toURL().toString();

xmlSig = new org.apache.xml.security.signature.XMLSignature(doc,

For this example we'll create an enveloped XML signature. That is, our signature will be part of the XML document as a child of the document's root element. To do so, we'll add the element associated with the XML signature to the document itself:

sigElement = xmlSig.getElement();


We also need to define the rules for XML document transformation and canonicalization, necessary for parsing and signature verification by others.

transforms = new org.apache.xml.security.transforms.Transforms(doc);

xmlSig.addDocument("", transforms,

Optionally, we can include the public key certificate
information associated with the private key we used to create this digital signature.

pkCertAlias = "MyCertName";

java.security.cert.X509Certificate pkCert =


All we have to do now is sign the document and write it to a file, using a convenience class found in the Apache XML Security package:

java.io.FileOutputStream out = new



Verifying an XML Signature

To demonstrate the verification of an XML digital signature, we'll use the output file from the above XML digital signature creation example. From this file, we'll rebuild the original XML document.

xmlFile = new java.io.File("/path/to/xmlfile.txt");
java.xml.parsers.DocumentBuilderFactory docFactory = new
javax.xml.parsers.DocumentBuilder docBuilder =
java.io.FileInputStream in = new java.io.FileInputStream(xmlFile);
org.w3c.dom.Document doc = docBuilder.parse(in);

Once we have the Document in hand, we can extract the XML signature. Admittedly, there are more elegant and general means of getting at the signature element, but we're aiming for
simplicity here.

xmlSigs = getElementsByTagName("Signature");

org.w3c.dom.Element xmlSigElement =

String baseURI = xmlFile.toURL().toString();
org.apache.xml.security.signature.XMLSignature xmlSig = new
org.apache.xml.security.signature.XMLSignature(xmlSigElement, baseURI);

Since we included the X.509 certificate in our XML signature's keyinfo, we can obtain it now.

keyInfo = xmlSig.getKeyInfo();

java.security.cert.X509Certificate pkCert =

We now have all the pieces to verify the document's XML signature.

valid = xmlSig.checkSignatureValue(pkCert);

if (valid)
System.out.println("Signature is valid.");
System.out.println("Signature is not valid.");
Click Here!