Consider a scenario where you are developing a healthcare Web service for a hospital that exposes medical records and other patient information. An insurance company or HMO would need to see the details of a lab test and the interactions between the doctor and patient. A doctor would need to see details not only of a patient's current stay at the hospital but also any past visits. The doctor should not need to know whether the patient has insurance deductibles. A nurse may need to see information related only to the current visit. A medical researcher may need to see medical history but not personal details. Many other combinations of information could, of course, be contained in an XML message.
The W3C and the Internet Engineering Task Force (IETF) have put together a joint proposal for using XML-based digital signatures. Java Community Process (www.jcp.org) is also working to define a specification for XML Digital Signatures (JSR-105) within Java. Digitally signing the entire XML document is simplistic. What if a document such as a medical record requires digital signatures on different portions by different medical personnel? Furthermore, signature in this scenario implies order. The admissions department should ideally sign its section before the discharge department does.
The primary use for digital signatures is for nonrepudiation. For example, Flute Bank can receive a signed document and know exactly who sent it, because the signature contains a message digest signed by using the sender's private key. XML signatures define a signature element that contains the information to process a digital signature. Each digital signature refers to one of three things:
An XML element in the signature element
An external XML document referenced by a URI in the document
An external non-XML resource referenced by a URI in the XML document
Consider the following XML document for placing a check order:
<flutebank:checkOrder xmlns:flutebank="http://flutebank.com/CheckOrders"> <flutebank:checkType>flutebank:Dilbert</flutebank:checkType> <flutebank:quantity>1,000</flutebank:quantity> <flutebank:account>ABC123</flutebank:account> <flutebank:startnum>2000</flutebank:startnum> </flutebank:checkOrder>
If a customer of Flutebank.com sent this order to our Web service, the service will need to validate that the order truly came from the account holder, regardless of the specified account number. One approach would be for the customer to digitally sign the above XML document, as in Listing 15.1.
<flutebank:signedCheckOrder xmlns:flutebank="http://flutebank.com/CheckOrders"> <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>j6lbgp5EPmSfTb3atsSuNbeVu8nk=</DigestValue> </Reference> </SignedInfo> <SignatureValue>aiYECAxGoPiL0v3sSamm3rXup5zJa ... </SignatureValue> <KeyInfo> <X509Data> <X509Certificate>MIIDa1sY+mAyIBA ... </X509Certificate> </X509Data> </KeyInfo> </Signature> <flutebank:checkOrder> <flutebank:OrderID>64B4A0D1-814E-4FF6-918A-DD7E7E1AECEA</flutebank:OrderID> <flutebank:checkType>flutebank:Dilbert</flutebank:checkType> <flutebank:quantity>1,000</flutebank:quantity> <flutebank:account>ABC123</flutebank:account> <flutebank:startnum>2000</flutebank:startnum> </flutebank:checkOrder> </flutebank:signedCheckOrder>
Here, the original checkOrder now becomes a child element of the root signedCheckOrders and adds an additional child, the signature element, which contains the digital signature information. Included it are elements that identify the algorithms used to canonicalize the data, the digest algorithm, and the signature algorithm.
The reference element points to the data we are interested in validating. In Listing 15.1, the element contains a null URI, which means that the entire XML document containing the signature element should be signed. This attribute could also include an XPointer reference, to state a specific portion of the document used to compute the signature.
The transforms element performs an XPath transform that removes the signature element. This is required in this scenario, because we are signing the entire document that envelops the signature. The DigestValue, calculated as part of the signing process, will obviously change if you include the digest itself. The transforms element removes the entire signature element from the data that must be digested and signed. This approach prevents recursion issues.
The keyinfo element holds key information required for validation of the signature. In our scenario, it contains an X.509 certificate, which holds the public key for the account holder. This is how Flute Bank can validate that the check order originated from a specific account holder.
The final feature that is critical in this example is the OrderID element. It contains a unique identifier that could be based on a timestamp or other calculated value. We have provided an additional level of protection by tagging each order with a unique identifier, preventing the success of a replay attack. Without the unique identifier, an attacker could simply replay the signed message, causing hundreds of duplicate orders to be created. This could be used to drain the bank account. The Flute Bank Check Order Web service checks to see if it has already processed an order with this unique identifier and ignores any duplicates.
In the above example, the check order was sent directly from the client to Flute Bank. If the check order were routed through other intermediaries, changing the order identifier would cause the signature validation check to fail. Remember that a digest is calculated based on the contents of the message. Rearranging the order within the document will also cause the message digest value to change. Likewise, replaying the same order would be flagged and ignored. Detection of replay attacks can be part of the message or header and can use one or more of the following approaches: timestamps, sequence numbers, expiration message, and correlation.
The XML digital signature specification also incorporates the XML canonical specification for generating the physical document, for scenarios where two XML documents may differ in their exact textual representation but are logically equivalent. Otherwise, documents may become suspect without valid cause. Both digital signature generation and validation are typically done using message digests. For a signature, the digest is calculated on the XML's canonical form. If the digests between two canonical forms of XML match, you can be sure the document has not been tampered with, even though the textual forms may vary.
If you decide to use digital signatures as part of your Web service, you must become aware of the security implications involved. Digital signatures require public and private key pairs, and the validity of the public key has to be provided by other technologies. A certificate trust model is required—either peer-to-peer or hierarchical. A method to generate and maintain trusted key pairs and certificates is also necessary. Finally, it must be possible to validate that the certificate has not been revoked.
Many implementations of XML digital signatures are available, including:
IAIK XML Signature Library: http://jcewww.iaik.tu-graz.ac.at/products/ixsil/index.php
IBM's XML Security Suite: www.alphaworks.ibm.com/tech/xmlsecuritysuite
InfoMosaic SecureXML: www.infomosiac.net
NEC XML Digital Signature Software Library: www.sw.nec.co/jp/soft/xml_s/appform_e.html
Phaos XML: www.phaos.com/e_security/dl_xml.html
Verisign XML Signature SDK: www.xmltrustcenter.org/xmlsig/developer/verisign/index.htm
Providing digital signatures as part of a Web services architecture increases the ability to support nonrepudiation and signer authentication aspects of your services.