In this column, we start implementing the WSS4J API. The first section
of this column discusses the role of different Java components in implementing
the WSS4J API. One of the components is XML Security Suite for Java
from IBM alphaWorks. The second section will provide a comprehensive
tutorial demonstrating how to accomplish XML encryption using the XML
Security Suite.

Java Components in WSS4J implementation

We are going to need several Java components to implement our
API. We will explain three components: the Java API for XML Processing
(JAXP), Java Cryptographic Architecture (JCA), and IBM's XML Security
Suite for Java (XSS4J). Future columns of this series will introduce
more components as the need arises.

Java API for XML Processing

We will use Java API for XML
Processing (JAXP) to fulfill XML processing and authoring requirements
of WSS4J. JAXP is an API for XML processing, authoring, and transformations.
Using JAXP, Java programmers can develop XML applications that do not
rely on a particular XML processing engine.

Xerces-Java
(from Apache) is an XML processing engine that includes an implementation
of the W3C DOM specification. At the moment, the JAXP reference implementation
from Sun uses Xerces as its default XML parser.

It is not feasible to cover the details of low level XML processing
with JAXP in this column. Please refer to the resources
section for more details of JAXP.

WSS4J will depend on JCA and JCE for low level cryptographic support.
JCA is the basic cryptographic architecture in Java, and JCE is an extensibility
mechanism for JCA. JCE allows cryptographic implementations (called
providers) from third party vendors to be plugged into JCA. This allows
application developers to rely only on the JCA/JCE API for application
development without worrying about vendor-specific interfaces. Refer
to the resources section for further details
of JCA/JCE. JDK 1.4 includes a reference implementation of JCA along with a default
JCE provider from Sun. We are going to demonstrate the use of both symmetric and asymmetric
keys for XML encryption in this and the next column. (Recall our brief
discussion on symmetric and asymmetric keys in the second
article of my series on Web Services Security.) Perhaps the most
popular encryption algorithm that uses asymmetric keys is RSA,
which we are going to use for our XML encryption demo in this article.

Unfortunately, the default JCE provider from Sun that ships with JDK
1.4 does not support RSA. You need to download a third party
provider that supports RSA. A good choice is to use the open source
implementation from Bouncy Castle.
A
tutorial at IBM developerWorks explains how to use Bouncy Castle's
provider with your JDK 1.4.

Note an important point about the use of keys in WSS4J. The Web Services
Security specification by OASIS does not dictate or define the process
of distributing cryptographic keys. This means that the WSS specification
does not answer key management questions like "how will I fetch the
public key of my business partner?" or "how can I map a key name to
the actual key?" Key management and distribution is a separate topic and therefore not
the focus of the WSS specification. You can use any key management and
distribution mechanism (like PGP
or XKMS, for instance) with
WSS. That's the reason our WSS4J implementation will also not care about
the source of a particular key. We'll rely on the application to provide
us the required key (the public key of my business partner, for example).

We are going to use the Java key store mechanism to store keys. This
mechanism allows storing keys privately as normal files on your hard
disk. Even if someone has access to a key store file, he will not be
able to hack the key unless he knows the password of your key in the
key store.

As we said earlier, our WSS4J implementation does not care where a particular
key came from. So for the sake of demonstration, you can generate a
key using the following command line use of the Java keytool utility:

This command generates a key store file named "tourOperatorRSAKey",
which contains an RSA public-private key pair whose alias (name) is
"myTourOperatorKey", it belongs to the "HotelBookings" business unit
of a company called "myTourOperator". The password of the key is "myKeyPass",
while the password of the key store is "myKeyStorePass".

You may generate this key using the command line as given above, as
you'll shortly need this key. Or you may use the key that I have included
in the sample code download of this article.

XML Security Suite for Java (XSS4J) from IBM alphaWorks

XSS4J implements XML signature and XML encryption specifications. We
will use XSS4J for low level XML signature and XML encryption support
while implementing the WSS4J API. You can say that WSS4J will use XSS4J
in the same manner as the WSS specification by OASIS makes use of the
low level functionality of XML Signature and XML Encryptions specifications
by W3C (refer to the second
article of my series on Web Services Security for more details).

You can download a
copy of XSS4J from alphaWorks' site. We tested all code of this
column with the version of XSS4J that was released on January 27, 2003
(latest for now) and therefore called xss4j-20030127.

Apart from the JDK, JCE, and Xerces, XSS4J also requires one additional
component called International Components for Unicode for Java (ICU4J).
XSS4J uses ICU4J for some text normalization algorithms. You can download
ICU4J from here.
We tried the code of this column with version 2.4 of ICU4J. Later versions
of ICU4J are not directly compatible with the current XSS4J implementation.
So use ICU4J version 2.4 to try the code of this column. ICU4J does
not require any special installation steps. Just include the icu4j.jar
file in your classpath.

XSS4J plays a vital role in our WSS4J implementation. Therefore,
the rest of this column is a step-by-step tutorial that demonstrates
the use of XSS4J for XML encryption. Once we know how to use XSS4J,
we will devise and implement a strategy to integrate XSS4J in our WSS4J
implementation.

Using XSS4J for XML Encryption

Have a look at the XMLEncryptionSample class of Listing
1, which implements a four step strategy that you can follow to
XML-encrypt an element using XSS4J. We have used a very simple sequence
of operations in Listing 1 to demonstrate
the process of XML encryption. We have hard coded different file names
in Listing 1 just for the sake
of simplicity.

Step 1:

The first step is to author the complete plain text form of the XML
data, part or whole of which you wish to XML encrypt. In actual real
world applications, the plain text form of the XML data may come from
many sources: the result of some server side processing,
or it may be available from some XML data repository. In any case, in
order to use XSS4J to encrypt whole or part of any XML resource, you
first need to load the plain text form into a W3C DOM object.

Have a look at Listing 1, where
we have authored a simple SOAP message with an empty header and a SOAP
body with a GetSpecialDiscountedBookingForPartnersResponse
child element. We are assuming that a hotel's business logic server
is authoring this SOAP message for a special customer, i.e. the tour
operator who is the owner of the key named "myTourOperatorKey" that
we generated using the Java keytool utility. The tour
operator is entitled to a special, confidential discount in room reservations.
Therefore, the hotel would like to keep the discount confidential and
therefore will encrypt the entire GetSpecialDiscountedBookingForPartnersResponse
element of the SOAP body.

Look at Listing 2, which shows
the SOAP message that is a result of XML authoring in step 1 of Listing
1. Notice from step 1 of Listing
1 that the GetSpecialDiscountedBookingForPartnersResponse
element of Listing 2 corresponds
to the Java object named hotelBookingResponse in Listing
1. This is the element that we are shortly going to encrypt using
XSS4J.

Step 2:

The XML encryption classes of XSS4J work on the idea of an encryption
template. Therefore, the second step is to load an encryption template
into a DOM object. The encryption template will specify complete information
about the EncryptedData element that will result after
encrypting the GetSpecialDiscountedBookingForPartnersResponse
element of Listing 2.

For example, look at Listing 3,
which shows an EncryptedData element along with its child
nodes. Notice that the EncryptedData element of Listing
3 is itself a complete XML encrypted structure, except just one
thing: The two CipherValue tags in Listing
3 are empty, i.e. they don't contain any cipher data. That's because
Listing 3 is a template. It shows
the structure and provides complete information about the XML encrypted
structure, but does not contain the actual cipher data. This means later
steps in our XML-encryption strategy will just fill in the cipher values
inside the CipherValue tags.

Try to gather what bits of information the encryption template of Listing
3 provides:

The Id attribute of the EncryptedData element specifies
an identifier for the EncryptedData element.

The Type attribute of the EncryptedData
element specifies the type of encryption (i.e. encrypt an XML element).

The Algorithm attribute of the EncryptionMethod
element specifies the encryption algorithm that we are going to
use during our XML encryption.

The KeyInfo element (which belongs to the XMLDS namespace)
specifies the key used for encryption. Listing
3 contains two KeyInfo elements. The first KeyInfo
element is the direct child of the EncryptedData element
and wraps an EncryptedKey element, which in turn contains
the second KeyInfo element. The EncryptedKey
element inside the outer KeyInfo element specifies
that the outer KeyInfo element actually wraps an encrypted
key. The inner KeyInfo element specifies the key used
to produce the encrypted key. Notice that the inner KeyInfo
element has a child named KeyName, which wraps a string
"myTourOperatorKey". This means that the hotel will use the public
key of the tour operator to encrypt a randomly generated key. The
outer KeyInfo element is actually a symmetric key and
the inner KeyInfo element is an asymmetric key. You
can use this nested hierarchy of KeyInfo-EncryptedKey-KeyInfo
elements whenever you wish to use an asymmetric key (the public
key of the recipient of the XML encrypted message) to encrypt a
symmetric key (normally a randomly generated number).

Step 2 in Listing 1 shows the Java
code that loads the XML structure of Listing
3 into a DOM object. We saved Listing
3 as an XML file named "EncryptionTemplate.xml" in the same directory
from where we compiled the "XMLEncryptionSample" class
of Listing 1. The lines of Java
code in step 2 of Listing 1 will
load the complete EncryptedData structure of Listing
3 (the "EncryptionTemplate.xml" file) into an element node named
encryptionTemplate. We will need the encryptionTemplate
node later in step 4.

The third step is to instantiate a KeyInfoResolver object.
KeyInfoResolver is an XSS4J interface. This interface represents
a mechanism, which resolves a KeyInfo element to a key
value. The KeyInfoResolver object takes a KeyInfo
element along with all information required to resolve the value of
the key. It then resolves the KeyInfo element to its value.

For example, let's assume the public key corresponding to the inner
KeyInfo element (whose name is "myTourOperatorKey") sits
inside a Java key store. Therefore, you will need to tell the password
of the key to the KeyInfoResolver object, so that the KeyInfoResolver
object could fetch the key from the store.

The KeyInfoResolver interface contains an important method
name resolve(), which resolves a KeyInfo element
to the actual key. We don't need to call this method anywhere. The XSS4J
framework will internally fetch the KeyInfo element from
the encryption template and then pass on the KeyInfo element
to the KeyInfoResolver.resolve() method call.

You will need to implement the KeyInfoResolver interface
according to the key resolution mechanism that you want to use in your
application. For example, if you want to use the encryption template
of Listing 3 in your application,
your key resolution mechanism should be able to do the following:

Read name of the asymmetric key from the KeyName element of the
inner KeyInfo element.

Fetch the actual key corresponding to the name of the asymmetric
key. The mechanism used to fetch the key depends upon how the key
is stored. For example, if the key is stored in a Java key store,
you will need to access the correct key store, provide the key access
password, and fetch the key.

Generate a random number. The random number is the key that you
will use to encrypt the plain text data.

Encrypt the random number with the asymmetric key you obtained from
the key store. You will wrap the encrypted form of the random number
inside the CipherValue tag (which is the grand child
of the EncryptedKey element in Listing
3).

You need to implement the above stated four step strategy in the resolve()
method of the KeyInfoResolver implementation corresponding
to the encryption template of your choice. Naturally you will need a
different implementation of the KeyInfoResolver interface
for every type of KeyInfo structure that you wish to use
in your XML encryption application. For example, the XSS4J implementation
comes with a class named KeyStoreKeyInfoResolver, which
is capable of performing the four steps described above (including reading
from Java key stores).

Therefore, you just need to instantiate the correct KeyInfoResolver
object. Once you have the required object, you will simply tell the
XSS4J framework to use the object for KeyInfo-to-key mapping.
Let's see how we do this in our XMLEncryptionSample application.
Have a look at the code following the "Step 3" comment line in Listing
1:

First you have to load a key store into a KeyStore
object. You call the KeyStore.getInstance() static method
to instantiate a KeyStore object, then you create a
File object corresponding to the key store file that
you want to use, then you read the contents of the file into an
input stream, and finally you load the input stream into the KeyStore
object.

Next you create a new KeyStoreKeyInfoResolver object
by calling its constructor. The constructor takes the KeyStore
object as a parameter.

Then you create an instance of the AlgorithmFactoryExtn
class, which is similar to the factory classes that Java programmers
are quite familiar with. The XSS4J framework will internally use
this factory object to instantiate algorithm specific classes corresponding
to the algorithms that the encryption template specifies.

Next you call the setAlgorithmFactory() method of the
KeyStoreKeyInfoResolver object. This method sets the
factory object for use by the KeyStoreKeyInfoResolver
object during the key resolution process.

Next we have to tell the password of the key to the KeyStoreKeyInfoResolver
object. The Java KeyStore object will not let the key
KeyStoreKeyInfoResolver object to fetch the key unless
it knows the correct password. Therefore, we have to call the putAliasAndPassword()
method of the KeyStoreKeyInfoResolver class and pass
on the alias (name) and password of the tour operator's key along
with the method call. The putAliasAndPassword() method
will store the alias and the password of the key in memory inside
the KeyStoreKeyInfoResolver object.

You can use the KeyStoreKeyInfoResolver class for both
encryption and decryption, but the behavior of this class is different
while encrypting and decrypting. Here we are only demonstrating
encryption (we will have a separate column to demonstrate and explain
decryption in our WSS4J implementation). So, you have to tell the
KeyStoreKeyInfoResolver object that you wish to use
this object for encryption. Therefore, you have to call the setOperationMode()
method of the KeyStoreKeyInfoResolver object passing
KeyInfoResolver.ENCRYPT_MODE as its value (which means
we are using this object for encryption).

Now the KeyStoreKeyInfoResolver object is all set, ready
to be used in step 4 of our XML encryption strategy.

Step 4:

In this step, we prepare an EncryptionContext object. The
EncryptionContext class forms the core of XML encryption
framework in XSS4J. This is the place where we put the pieces together
and perform the actual encryption:

First instantiate the EncryptionContext class. The
constructor does not take any parameter.

Next we call the setAlgorithmFactory() method of the
EncryptionContext class to specify which algorithm
factory we wish to use in our encryption application.

Next we call the setKeyInfoResolver() method of the
EncryptionContext class to set the key resolver object
to be used to resolve the key value from a KeyInfo
element.

Next we call the setData() method of the EncryptionContext
class and pass the element node that we want to XML encrypt along
with the method call (in our case, we want to encrypt the hotelBookingResponse
element node, which corresponds to the GetSpecialDiscountedBookingForPartnersResponse
of Listing 2).

Next we call the EncryptionContext.setEncryptedType()
method, which is meant to specify encryption details for EncryptionContext
object. The setEncryptedType() method takes four parameters. The
first parameter specifies the encryption template that we want to
use (e.g. the EncryptedData element of Listing
3, which we loaded into the encryptionTemplate
element node in step 2). The second parameter specifies the type
of encryption, the third parameter specifies the KeyInfo
element, and the fourth element specifies the EncryptionMethod
element that we wish to use during XML encryption. Notice that the
encryption template of Listing
3 already contains all the information about our required XML
encryption (the type of encryption, the encryption method, and the
KeyInfo element). Therefore, we just need to pass on
the encryptionTemplate element as the first parameter
and can pass null for rest of the three parameters.

We are all set to do the actual encryption. The EncryptionContext.encrypt()
method encrypts the GetSpecialDiscountedBookingForPartnersResponse
element of Listing 1 and produces
an EncryptedData element. The EncryptionContext.replace()
method replaces the plain text GetSpecialDiscountedBookingForPartnersResponse
element with the EncryptedData element.

Listing 4 shows the final XML encrypted
version of Listing 2, which was
produced by the Java file of Listing
1. You can compare Listings 2 and 4. You will find that the GetSpecialDiscountedBookingForPartnersResponse
element in Listing 2 has been replaced
by an EncryptedData element in Listing
4.

Conclusion

We have learned about the major components required to implement the
WSS4J API. We have also learned about the use of XSS4J for XML encryption.
Next time, we'll use XSS4J and implement the WSSMessage.encryptElement()
method of our WSS4J API that we presented in Listing 2 of the first
column of this series.

Resources

Download the source code zip of this
article. The zip contains the source as well as the compiled form
of the code. It also contains the encryption template, the key store
file, and a readme.txt file that will help you compile
and run the XMLEncryptionSample class.

Read the first
column of this series, which introduced the WSS4J API. Also
check out the first,
second,
third,
and fourth
parts of the series of article on Web Services Security from the
same author.