Using W3C's DSig 1.0 Reference Implementation

This document is work in progress, please mail your comments to w3c-dsig-ask@w3.org.

Contents

This note describes how an application programmer can use the DSig reference implementation to create and verify DSig 1.0 digital signatures on PICS labels. This document adds to the JavaDoc source code documentation and other available documentation and is supposed to give short and concise description of the basic API functionality.

This text does not cover the non DSig specific handling of PICS labels, please refer to the appropriate PICS implementation documentation for that. It also does not describe how to extend the capabilities of the reference implementation by adding additional signature suites or certificate types to it, which is described in the source code documentation of the classes in w3c.www.dsig.

NOTE: please read the "README" file on to setup and run the DSig demo. Also visit W3C DSig implementation website at http://www.w3.org/PICS/refcode/DSig for the latest update.

General Information

The W3C DSig Reference Implementation is written in Java 1.1. The core DSig code is part of W3C's Java library and contained in the w3c.www.dsig package. It depends on a number of other W3C classes, like utility classes in w3c.tools.codec, w3c.tools.sexpr, and w3c.tools.sorter packages. The core DSig implementation w3c.www.dsig can be invoked by two separate PICS parsers, namely w3c.www.pics and w3c.pics.parser with a common interface w3c.www.dsig.DSigLabelInterface. Hence any PICS parser implementing the interface is able to use the DSig core package directly. Note that w3c.pics.label PICS parser package is better documented and well debugged, so we encourage you to use this version of PICS parser.

Verifying a DSig Digital Signature

This is a step-by-step explanation of how to verify a PICS label using the W3C DSig implementation.

NOTE: w3c.www.pics.SigLabel class and w3c.pics.parser.Label class can be used interchangably, depending on which PICS parser library you use. The document below uses w3c.www.pics.SigLabel.

NOTE: All verification methods use tri valued logic to report the verification result. You might want to read about tri valued logic in the appendix before you proceed.

Step 1: Preparation step. Create an object of the w3c.www.pics.SigLabel, which is the main DSig class and a subclass of w3c.www.pics.PICSLabel. The resulting object will be called label1 throughout the rest of this section. Use the constructor SigLabel(PICSLabel), or the static methods SigLabel.newSigLabel(InputStream) or SigLabel.newSigLabel(String) depending on your input data.

Example:

SigLabel label1 = SigLabel.newSigLabel(new FileInputStream(filename));
Step 2: Quick verification of the label. If you are interested in a simple and easy way to verify the label you can use the methods verify() and verifyAll() of the SigLabel class. These methods are provided as a way to make signature verification as simple as possible. If you prefer a more flexible and possibly more efficient verification skip this step and continue with 3 and 4.

The verifyAll() method computes the verification result as an logical AND of all signature and hash verification results in tri valued logic, i.e. it will only return TRUE if all tests succeed. The verify() method performs signature and message digest verification according to the user's default policy. Currently this is defined to be the same as verifyAll() but it is anticipated that in the future this function will truely execute the user configured verification policy.

Example:

Trivalue result = label1.verify();
System.out.println("The verification result is: " + result.toString());
Step 3: Verify the ResInfo extension. The ResInfo contains one or more cryptographic hashes which are used to establish the cryptographic link between the SigLabel and the document it signs. Use label1.getResInfo() to obtain the label's ResInfo object. The ResInfoExtension class defines a number of methods to verify the hashes:
  1. verifyAll(SigLabel) and verifyAll(InputStream). These methods will verify all message digests contained in this ResInfo and return the trivalued AND of the individual results. The data to be hashed will either be read from the given input stream or from the URL specified in the 'for' option of the given label.
  2. verify(SigLabel) and verify(InputStream). Verify according to the user's default policy, currently hardcoded to be verifyAll().
  3. verify(String, SigLabel) and verify(String, InputStream). Verify just the hash with the given algorithm name. Returns unknown if a hash for that algorithm is not present.
Example:
ResInfoExtension resinfo = label1.getResInfo();
Trivalue result = resinfo.verify();
System.out.println("The resinfo verification result is: " + result.toString());
Step 4: Verify the SigBlock extension. The SigBlock contains the AttribInfo with zero or more certificates and the Signatures section with one or more digital signatures, possibly from multiple signers and/ or using multiple signature algorithms. Use label1.getSigBlock() to obtain the label's SigBlock object.

Again, there are methods verifyAll(SigLabel) to verify all signatures in this signature block, and verify(SigLabel) to perform verification as specified by the user's default policy. Additionally, there is a method verify(SigLabel, String) to verify only all signatures created using the given signature algorithm. If more flexibility is desired, the application can fetch a particular signature object using getSigSuites(String) or sigSuites() and then operate freely on this object. For more information, read the source code documentation.

Example:

SigBlockExtension sigblock = label1.getSigBlock();
Trivalue result = sigblock.verify();
System.out.println("The sigblock verification result is: " + result.toString());

Creating a DSig Digital Signature

Step 1: Preparation step. Create an instance of the class w3c.www.pics.SigLabel. Use the constructor SigLabel(PICSLabel), or the static methods SigLabel.newSigLabel(InputStream) or SigLabel.newSigLabel(String) depending on your input data.

Example:

SigLabel label1 = SigLabel.newSigLabel(new FileInputStream(filename));
Step 2: Build the ResInfo. Add one or more hashes of the labeled document to the ResInfo of the label. To do this first obtain (initially empty) ResInfoExtension object of your label by calling getResInfo Then add a digest using one of the addDigest methods:
  1. addDigest(String alg, SigLabel label, ISODate date) will add a digest calculated from the URL specified in the 'for' option of the label. using the algorithm alg and add it to this ResInfo with date as its date. If date is null, no date will be added.
  2. addDigest(String alg, InputStream ins, ISODate date) will add a digest calculated from the data in the InputStream ins using the algorithm alg and add it to this ResInfo with date as its date. If date is null, no date will be added.
  3. addDigest(String alg, String val, ISODate date) will add a the pre-calculated digest val of the algorithm alg and add it to this ResInfo with date as its date. If date is null, no date will be added.
Example:
ResInfoExtension resinfo = label1.getResInfo();
resinfo.addDigest("http://www.w3.org/TR/1998/REC-DSig-label/MD5-1_0", label1, null);
resinfo.addDigest("http://www.w3.org/TR/1998/REC-DSig-label/SHA1-1_0", label1, new ISODate());
Step 3: Add signatures to your sigblock. First choose the signature suite you want to use for signing. The class w3c.www.dsig.SigSuiteRegistry can queried for the installed signature suites and to obtain an instance of this class (for more information please refer to the JavaDoc generated API documentation). To obtain an instance of a particular signature suite for signing call SigSuiteRegistry.getInstance(String) where the string argument is the URL identifying the algorithm.

To compute the signature just call SigLabel_object.sign(SigSuite_object, PrivateKey) with your private key for this algorithm. Then you should add information about yourself (the signer) to the Signature Suite. In DSig, the signer can either be identified via his name, his public key, or the hash of his public key. Use setBy("ByName",String), setBy("ByKey",PublicKey), or setBy("ByHash",PublicKey). Note that individual signature suites need not support all three types and can also support additional forms of By*. However, usually at least these three will be supported.

Example:

SigBlockExtension sigblock = label1.getSigBlock();
sigdss = SigSuiteRegistry.getInstance("http://www.w3.org/TR/1998/REC-DSig-label/DSS-1_0");
label1.sign(sigdss, myDsaPrivateKey);
sigdss.setBy("ByName", "My name");
Step 4: Add certificates to the AttribInfo of your SigBlock. First obtain the SigBlock's current AttribInfo using sigblock.getAttribInfo(), then add all desired certificates to it by repeatedly calling addCert(SigCert).

Example:

AttribInfo attribinfo = sigblock.getAttribInfo();
attribinfo.addCert(myCert);
attribinfo.addCert(CaCert);
Step 4: You now have a signed SigLabel. Call label1.toString() for its canonical string representation or label1.prettyPrint() for a more readable representation.

Example:

System.out.println("The signed label is:\n" + label1.prettyPrint());

Appendix

Tri-valued Logic

The W3C DSig implementation employs tri-valued logic to indicate the result of operations. Tri-valued logic is boolean (true/ false) logic extended by a third value called "unknown."

The handling of tri-valued logic is implemented via the class w3c.www.dsig.Trivalue.

A value of TRI_TRUE denotes that the verification was successful, the value TRI_FALSE signifies that the verification result was negative, and a value of TRI_UNKNOWN means that the verification could not be completed successfully because of missing or currently unavailable information. In case the verification function has to conduct several tests, the resulting value obeys to the AND function for three-valued logic. That is, it returns only TRI_TRUE if all tests gave the result TRI_TRUE, TRI_FALSE if at least one result was TRI_FALSE, and TRI_UNKNOWN otherwise (i.e. at least one result was TRI_UNKNOWN, possible some TRI_TRUE but none TRI_FALSE). An application is free to decide how to handle TRI_UNKNOWN results, it is recommended to treat them as TRI_FALSE if no special handling is possible or desired. 


Andreas Sterbenz, sterbenz@iaik.tu-graz.ac.at