Creating and Validating an XML Signature


Let’s get down to practicalities and see how XML Signatures are created and validated.

Creating an XML Signature

Here are the high-level steps used to create an XML Signature. See the XML Signature specification (www.w3c.org/Signature) or an XML Signature Toolkit’s documentation for complete information.

Step-by-Step

  1. List the URIs of the resources that are to be signed. These resources may be external resources on the Web, a local file, or an XML fragment in the same document as the signature.

  2. Feed each resource into a digest algorithm to produce a digest.

  3. Package each digest into a Reference element, along with information about the digest that was used, which algorithms were used, and which transforms were used.

  4. Construct the SignedInfo section, combining the content in Reference elements with information about what signature algorithm and canonicalized algorithm are to be used.

  5. Canonicalize the SignedInfo data.

  6. Calculate the digest of the SignedInfo data.

  7. Calculate the signature of the SignedInfo digest.

  8. Insert the signature value into the SignatureValue element.

  9. Optional step: Create a KeyInfo section in the XML Signature.

  10. Place the SignedInfo, SignatureValue, and KeyInfo sections into a Signature element.

Java Code Example

The IBM XML Security Suite includes an example Java program that implements XML Signature. The SampleSign2 Java application can be found in the dsig folder, which is under the samples folder.

The XML Security Suite provides many useful Java classes that take the hard work out of implementing the ten steps for creating an XML Signature. A TemplateGenerator object creates the structure of an XML Signature, in which the various components (SignedInfo, KeyInfo, and so forth) can be inserted. This TemplateGenerator object takes a generic document class, plus information about the algorithms to be used (signature algorithm, canonicalization algorithm, digest algorithm), as input. Methods such as addTransform and addReference allow referenced documents to be obtained (for example, from the file system or from a URI) and put into Reference elements within an XML Signature template. Once this is done, we reach the actual signing stage. Here is some example code for signing—the com.ibm.xml.dsig.* and java.security.* namespaces are required.

        KeyStore keystore = KeyStore.getInstance("JKS");          keystore.load(new FileInputStream(keystorepath), storepass);          X509Certificate cert = (X509Certificate)keystore.getCertificate(alias);          Key key = keystore.getKey(alias, keypass); // a private key          if (key == null) {              System.err.println("Could not get a key: "+alias);              System.exit(1);         }          KeyInfo keyInfo = dsig.SignatureUtil.createKeyInfo(cert);          Element signatureElement = signatureGen.getSignatureElement();          keyInfo.insertTo(signatureElement, prefix);          //          // Sign          //          SignatureContext sigContext = new SignatureContext();          sigContext.setIDResolver(idg);          sigContext.sign(signatureElement, key);          doc.appendChild(signatureElement);          dsig.SignatureUtil.printDocument(doc, System.out);

Firstly, the signing (that is, private) key and the public key certificate are obtained from a Java keystore. The signatureGen object is an instance of the TemplateGenerator class and it returns the actual SignatureValue element that is loaded with the value obtained when the “sign” method of the SignatureContext object is run.

The programmer is shielded from much of the intricacy of XML Signature, and certainly does not need to know the inner workings of cryptographic or canonicalization algorithms.

Note that XML Signature is not part of the JDK at the moment, but may enter the JDK in the future through the work of the JSR (Java Specification Requests) 105 group, sponsored by Sun.

Validating an XML Signature

The validation of an XML Signature follows many of the same steps as the creation of the signature. The reason for this is simple: in order to ensure that the signed data hasn’t changed, the digest of the data must be recalculated and compared with the original. If a signature contained only a digest, then it would be equivalent to a checksum. If that were the case, an imposter could simply change the digest as well as changing the signed data, to conceal the change. That is why the SignatureValue contains a version of the digest which has been encrypted using the private key of the signer. The corresponding public key is used (step 5 in the following Step-by-Step exercise) to obtain the digest. If this matches the digest of the signed data, that means that the data has not changed since it was signed.

Step-by-Step

  1. Use the SignatureMethod element to obtain the information about what signature algorithm and digest method were used to create the signature.

  2. Canonicalize the SignedInfo section using the canonicalization algorithm listed in the SignedInfo section.

  3. Recalculate the digest using the canonicalized SignedInfo section as input.

  4. Obtain the signature itself from the SignatureValue element.

  5. Use the signer’s public key and the Signature to obtain the original SignedInfo digest value, and compare this with the digest value obtained in step 3.

  6. At this stage, we’ve passed “core validation” of the XML Signature. We know that the SignedInfo section has not changed if the digests match. To complete “full validation,” we must obtain the original documents that are referred to in the Reference elements and ensure that the digests of these documents match the values in the DigestValue elements in their Reference elements.

C# Code Example

For the signature creation, we used Java. So let’s use C# and the .NET CLR (Common Language Runtime) for the signature validation. Of course, XML Signature is language independent so a signature created with one language should always verify using another language, providing, of course, that the signed data has not changed.

The following namespace definitions are required for the .NET example:

using System;  using System.IO;   using System.Security.Cryptography.Xml;   using System.Security.Cryptography;   using System.Xml;

The SignedXML class in the .NET Framework includes a number of high-level methods used for XML Signature, such as the following:

  • SigningKey Specifies the key that signs the XML data

  • AddReference Adds a signed resource as a Reference to the XML Signature

  • SigningKey Specifies the key used to perform the signature

  • ComputeSignature Calculates the signature, using the signing key

  • CheckSignature Verifies a signature

In this example, the XML document is loaded, and then the CheckSignature() function is run:

// Load the XML.  XmlDocument xmlDocument = new XmlDocument();  xmlDocument.PreserveWhitespace = true;  XmlTextReader r = new XmlTextReader(fileName);  xmlDocument.Load(r);  r.Close();    SignedXml signedXml = new SignedXml(xmlDocument);    // asssume there is only one <ds:Signature> XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature",  "http://www.w3.org/2000/09/xmldsig#");  signedXml.LoadXml((XmlElement)nodeList[0]);    if (signedXml.CheckSignature()) {              Console.WriteLine("Signature check OK");          } else {              Console.WriteLine("Signature check FAILED");          }




Web Services Security
Web Services Security
ISBN: 0072224711
EAN: 2147483647
Year: 2003
Pages: 105
Authors: Mark ONeill

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net