
Implementing XML Encryption in Java
by Bilal Siddiqui
April 21, 2004
In the first
column of this series, we presented a high-level WSS4J API, which
we wish to implement in this series of columns. In the second
column, we discussed the various Java components we are going
to use in implementing the WSS4J API. The most important component is XML Security
Suite for Java (XSS4J) from IBM alphaWorks. The second
column also demonstrated how to use XSS4J for XML encryption.
In this column, we will use the XSS4J concepts discussed in the previous
column to implement the XML encryption features in our WSS4J API.
Before we start the discussion, we would like to point out a
name clash issue. There's an open source Web Services Security project at
SourceForge.net (recently moved to Apache's web site) that shares the same
WSS4J name. The WSS4J API we are developing in this series of columns is purely for educational purposes
and aims at demonstrating the use of WSS in Java applications. The WSS4J open
source project at SourceForge (now at Apache) is an independent project and is
not part of our effort.
A WSS Message Before and After XML Encryption
We are going to add support for both symmetric and asymmetric keys in our WSS4J API.
Listing 1 shows a simple SOAP message we will use as sample input to our XML encryption process. We will encrypt a portion of Listing 1 to demonstrate the working of our WSS4J API.
We are going to perform three types of XML encryption. Listings 2, 3, and 4 are three WSS messages that show
the outcome of our encryption process. Listings 2, 3, and 4 are slightly different from each
other. As we have already covered the details of WSS format in our Web Services Security series (especially in Part
4), we will not go into the details of WSS format. Here we will
only highlight the differences between Listings 2, 3, and 4:
Listing 2 shows the following:
- If you look at the contents of the SOAP body in Listings 1 and 2, you will see that the first
Parameter element of Listing 1 has been
replaced by an EncryptedData element in Listing 2. The
EncryptedData element contains the encrypted form of the
Parameter element. The encryption algorithm used for this XML
encryption is triple DES as specified by the EncryptionMethod
child of the EncryptedData element.
-
The
EncryptedData element in Listing 2 does not contain any key
information. The corresponding key information resides inside the
wsse:Security element in the SOAP header, which contains an
EncryptedKey element. The EncryptedKey element wraps
a symmetric triple DES secret key in encrypted form. Notice from Listing 2 that the
EncryptionMethod used to produce the EncryptedKey is
RSA and the key used for this RSA encryption is the tour operator's public
key. We covered the details of such encrypted keys in Step 2 of the Using
XSS4J for XML Encryption section in the second column.
- How do we relate an
EncryptedData element with its
corresponding key used for encryption? Look at the ReferenceList
element inside the EncryptedKey element of Listing 2. The
ReferenceList element has a child element named
DataReference, whose URI attribute points to the
EncryptedData element we produced using the encrypted key.
The EncryptedKey element is a security token in WSS terms.
Although the XML encryption specification simply calls it an encryption key, the WSS specification talks about abstract (or more general) tokens. This
means we can treat cryptographic keys as a type of security token. Therefore,
while implementing WSS, we will treat an EncryptedKey structure as
a type of token and call it an encrypted key token.
Now look at Listing 3, which is a very
slightly modified form of Listing 2. The
only difference between Listings 2 and 3 is that the EncryptedData element in Listing 3
contains a KeyInfo element, which wraps a SecurityTokenReference element. The
ecurityTokenReference element has a Reference child
element, whose URI attribute refers to the wsu:Id of
the EncryptedKey that was used to produce the
EncryptedData.
If there are more than one EncryptedData and
EncryptedKey elements in a WSS message, then it is computationally
more expensive to find the EncryptedKey corresponding to a
particular EncryptedData structure in Listing 2 as compared to Listing 3. That's because in Listing 2 you have to look into
the ReferenceList elements of several EncryptedKey
structures until you find the required EncryptedKey structure. On
the other hand, if you have to find the EncryptedData structure
corresponding to a particular EncryptedKey Listing 3, you can read the
URI attribute value of the Reference element and jump
directly to the required EncryptedKey structure.
We will call Listing 3 as an
encrypted key token with cross reference.
Now look at Listing 4, which shows the following:
- The
EncryptedData element in Listing 4 contains a KeyName element, which specifies the name of the key used for encryption. Here we are assuming that the recipient of this message can locate the actual key corresponding to this name. Therefore, we are not concerned about how an application will map a key name to the actual key.
- There's no
EncryptedKey element inside the wsse:Security header. Instead we just have a ReferenceList element that refers
to the EncryptedData element inside the SOAP body. This type of
ReferenceList element does not specify the key used for producing
the EncryptedData element. This ReferenceList only
specifies the order in which different actions take place in the header (e.g.
if you encrypt and then sign a portion of a message, the
ds:Signature element will appear before the
ReferenceList element. For details please refer to the discussion
accompanying Listings 7
and 8
in the fourth article of my Web Services Security series).
We will call this ReferenceList element a reference list only token.
We will implement the first two types of tokens (encrypted key token and encrypted key token with cross reference) in this column and the third type (reference list only token) in the next column of this series.
Implementing the Encrypted Key Token
Now let's see how to implement and use an encrypted key token. In order to implement and use an encrypted key token, we'll need to do the following:
- Implement the
Token interface we presented in Listing 3 of the first column of this series. The Token interface contains several methods and we'll need to implement each of them in a Java class named EncryptedKeyToken.
- Implement the constructor of the
WSSMessage class we introduced in Listing 2 of the first column of this series.
- Implement the
encryptElement() and encryptElementWithXPath() methods of the WSSMessage class.
Let's do these steps one by one.
[1] [2] Next