A digital signature (not to be confused with a digital certificate) is the electronic equivalent of a written signature. It is used by distributed applications to authenticate the identity of the sender of a message or document. It also ensures that the message or document is unchanged.
The XML digital signature specification defines an optional XML element that facilitates the inclusion of a digital signature within an XML document. It provides any web service with the ability to ensure data integrity, authentication, and nonrepudiation with any other web service.
In addition to specifying syntax, the specification makes recommendations about the types of data that require a digital signature. The most thought-provoking recommendation relates to the signing of visual items (such as Cascading Style Sheets and browser plug-ins) that are external to the XML data itself, but will eventually be used to render the XML data. As a rule, the specification recommends that if the representation of XML data is for visual display, then to preserve validity of the signed information over time, both the XML data and the items applied for visual representation should be signed. The specification suggests that this recommendation should be applied to nonvisual renderings, such is audio, as well.
Here is a digitally signed version of
PO.xml
. The purchase order
information is unchanged, but the document is much larger; most of it
now consists of a
<Signature>
element:
<PurchaseOrder xmlns="urn:oreilly-jaws-samples"> <shipTo country="US"> <name>Joe Smith</name> <street>14 Oak Park</street> <city>Bedford</city> <state>MA</state> <zip>01730</zip> </shipTo> <items> <item partNum="872-AA"> <productName>Candy Canes</productName> <quantity>444</quantity> <price>1.68</price> <comment>I want candy!</comment> </item> </items> <Signature Id="EnvelopedSig" xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo Id="EnvelopedSig.SigInfo"> <CanonicalizationMethod Algorithm= "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <SignatureMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <Reference Id="EnvelopedSig.Ref" 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> yHIsORnxE3nAObbjMKVo1qEbToQ= </DigestValue> </Reference> </SignedInfo> <SignatureValue Id="EnvelopedSig.SigValue"> GqWAmNzBCXrogn0BlC2VJYA8CS7gu9xH/XVWFa08eY9HqVnrfU6Eh5Ig6wlcvj4RrpxnNklBnOuvv JCKqllQy4e76Tduvq/N8kVd0SkYf2QZAC+j1IqUPFQe8CNA0CfUrHZdiS4TDDVv4sf0V1c6UBj7zT 7leCQxAdgpOg/2Cxc= </SignatureValue> <KeyInfo Id="EnvelopedSig.KeyInfo"> <KeyValue> <RSAKeyValue> <Modulus> AIvPY8i2eRs9C5FRc61PAOtQ5fM+g3R1Yr6mJVd5zFrRRrJzB/awFLXb73kSlWqHao+3nxuF38r RkqiQ0HmqgsoKgWChXmLuQ5RqKJi1qxOG+WoTvdYY/KB2q9mTDj0X8+OGlkSCZPRTkGIKjD7rw4 Vvml7nKlqWg/NhCLWCQFWZ </Modulus> <Exponent>AQAB</Exponent> </RSAKeyValue> </KeyValue> </KeyInfo> </Signature> </PurchaseOrder>
The first step toward creating a digital signature is ensuring that
it and the data being signed can’t be tampered with.
This step is accomplished by applying a mathematical algorithm called
a secure hash to
a portion of the message data. The result is called the
"
digest” of the message.
The next step is to take that digest, plus all the additional
information that will be signed (in our example, in the
<SignedInfo>
element), digest it again,
encrypt it, and write it into the XML message itself as the digital
signature. In PO.xml, the selected algorithm and
the initial digest are contained in the
<DigestMethod>
and
<DigestValue>
elements. The final digested, encrypted
digital signature is contained in the
<SignatureValue>
element, and the decryption key is
stored in the <KeyInfo>
element. The recipient can determine
whether the signature is valid by decrypting the digest and
recreating the whole process that was performed by the sender to
create the digest. If the resulting digest matches the original, the
signed content was probably not tampered with.
The <Reference>
element
provides information used to generate the message digest. This
information includes any data transformation or normalization used
along the way, including canonicalization. For instance, you can
associate a digital signature to an XML document in different ways:
The signature is a child of the data being signed.
The signature encloses the data being signed.
The signature is a sibling of the element being signed and is referenced by a local link, or it can be located elsewhere on the network.
This information needs to be carried within the signature using the
<Transforms>
tag. In our example, we chose to use the
enveloped method:
<Transforms> <Transform Algorithm= "http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> </Transforms>
Other examples of transforms are base64 encoding, XPATH filtering, XSLT transformation, and schema validation.
In our example, the selected algorithm and the digest are specified with these tags:
<DigestMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue> yHIsORnxE3nAObbjMKVo1qEbToQ= </DigestValue>
It’s worth taking a more detailed look at the
<Signature>
element. The
<SignedInfo>
element is required; it specifies the
data that is actually signed and the algorithms used to sign it.
<SignedInfo>
has three elements:
<CanonicalizationMethod>
,
<SignatureMethod>
, and
<Reference>
.
A secure hash is intolerant of minor changes in a document. Any change, even the introduction of a space, produces a completely different hash. This intolerance of change is essential to the nature of a secure hash; it must be next to impossible to modify the original document in such a way that it still produces the same hash or to predict how a change to a document will change the hash. However, this feature presents a problem for XML. XML documents are frequently parsed and reparsed as they are transferred from the sender to the recipient, and parsers can make insignificant modifications (such as the elimination of whitespace). Canonicalization puts the document into a standard format before computing the digest, so we can be confident that the sender and receiver will compute the same digest regardless of what processing occurred along the way.
This canonical format was standardized by the W3C in the XML-Canonicalization (xml-c14n) specification.[18] Here are the high-level rules that an xml-c14n-compliant canonical conversion covers in detail:
The document is encoded in UTF-8.
Line breaks are normalized to #xA (hexadecimal A, decimal 10, or ASCII newline) on input, before parsing.
Attribute values are normalized, as if by a validating processor.
Character and parsed entity references are replaced.
CDATA sections are replaced by their character content.
The XML declaration and document type declaration (DTD) are removed.
Empty elements are converted to start-end tag pairs.
Whitespace outside of the document element and within start and end tags is normalized.
All whitespace in character content is retained (excluding characters removed during line feed normalization).
Attribute value delimiters are set to quotation marks (double quotes).
Special characters in attribute values and character content are replaced by character references.
Superfluous namespace declarations are removed from each element.
Default attributes are added to each element.
Lexicographic order is imposed on the namespace declarations and attributes of each element.
The
second step involved in creating the digest is tracking and
specifying the actual method used to create the signature (denoted by
the <SignatureMethod>
element). Once the
canonical version of the XML is derived, the data that is part of the
<SignedInfo>
element needs to be converted
into the actual signature value (and placed in the
<SignatureValue>
element). The
<SignatureMethod>
element dictates the
algorithm that will be used for this operation.
The algorithm used to create the signature and, finally, the
signature itself, are specified by the
<SignatureMethod>
and
<SignatureValue>
tags:
<SignatureMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <Reference Id="EnvelopedSig.Ref" URI=""> ... <SignatureValue Id="EnvelopedSig.SigValue"> GqWAmNzBCXrogn0BlC2VJYA8CS7gu9xH/XVWFa08eY9HqVnrfU6Eh5Ig6wlcvj4RrpxnNklBnOuvv JCKqllQy4e76Tduvq/N8kVd0SkYf2QZAC+j1IqUPFQe8CNA0CfUrHZdiS4TDDVv4sf0V1c6UBj7zT 7leCQxAdgpOg/2Cxc= </SignatureValue>
When the receiver gets the message, the signature is decrypted using
the sender’s public key, the verified digest, and by
verifying the sender’s signature. In the following
listing, the <KeyInfo>
element holds the decryption key:
<KeyInfo Id="EnvelopedSig.KeyInfo"> <KeyValue> <RSAKeyValue> <Modulus> AIvPY8i2eRs9C5FRc61PAOtQ5fM+g3R1Yr6mJVd5zFrRRrJzB/awFLXb73kSlWqHao+3nxuF38r RkqiQ0HmqgsoKgWChXmLuQ5RqKJi1qxOG+WoTvdYY/KB2q9mTDj0X8+OGlkSCZPRTkGIKjD7rw4 Vvml7nKlqWg/NhCLWCQFWZ </Modulus> <Exponent>AQAB</Exponent> </RSAKeyValue> </KeyValue> </KeyInfo>
Note that the XML signature doesn’t address trust of
such key information. The application has to determine how
trustworthy the key is. Unless there is another way to verify that
the supplied decryption key does belong to the sender, there is
little point to the process. Anyone could intercept the message,
change its contents, regenerate a public/private key pair, and
re-sign the document (asserting that the public key belongs to the
sender). This is when digital certificates come into play. The
certificate contains the binding between the identity of the public
key’s owner and the key itself. If
<KeyInfo>
is omitted, the recipient is
expected to identify the key that will be used, based on the
application context. This type of issue is addressed in the XKMS
specification, which is discussed in the later Section 10.3.2. Using XKMS or another PKI
infrastructure, the recipient of the message can obtain the digital
certificate, extract the public key from it, and verify that this key
does belong to the sender.