Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS...

77
Secure XML messaging with JMS, Part 2: Using XSS4J to implement XML Security Enhance your enterprise applications by integrating these technologies Skill Level: Intermediate Bilal Siddiqui ([email protected]) CTO WaxSys 21 Feb 2005 Java Message Service (JMS) is a Java language-based messaging API. XML provides a simple, human-readable data format for information exchange, and is a popular syntax for the formating of enterprise data. Therefore, integrating XML into JMS applications can provide significant advantages in enterprise applications. This tutorial demonstrates the use of XML Security Suite for Java (XSS4J) to achieve secure XML messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial demonstrates the use of Java Messaging Service (JMS) for secure XML messaging in enterprise applications. JMS is a set of Java-based messaging APIs developed under the Java Community Process (JCP) against Java Specification Request (JSR) number 914 (see Resources). The focus of this tutorial series is to demonstrate, step-by-step, how to extend JMS functionality to incorporate support for authoring and processing secure XML Using XSS4J to implement XML Security © Copyright IBM Corporation 1994, 2008. All rights reserved. Page 1 of 77

Transcript of Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS...

Page 1: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Secure XML messaging with JMS, Part 2: UsingXSS4J to implement XML SecurityEnhance your enterprise applications by integrating thesetechnologies

Skill Level: Intermediate

Bilal Siddiqui ([email protected])CTOWaxSys

21 Feb 2005

Java Message Service (JMS) is a Java language-based messaging API. XML providesa simple, human-readable data format for information exchange, and is a popularsyntax for the formating of enterprise data. Therefore, integrating XML into JMSapplications can provide significant advantages in enterprise applications. This tutorialdemonstrates the use of XML Security Suite for Java (XSS4J) to achieve secure XMLmessaging over an existing JMS network.

Section 1. Before you start

About this tutorial series

This two-part tutorial demonstrates the use of Java Messaging Service (JMS) forsecure XML messaging in enterprise applications. JMS is a set of Java-basedmessaging APIs developed under the Java Community Process (JCP) against JavaSpecification Request (JSR) number 914 (see Resources).

The focus of this tutorial series is to demonstrate, step-by-step, how to extend JMSfunctionality to incorporate support for authoring and processing secure XML

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 1 of 77

Page 2: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

messages. While doing this, I will explain and demonstrate the following:

1. The architecture of JMS

2. How client applications use JMS functionality

3. How to extend JMS functionality to include the authoring and processingof secure XML messages

4. How to use X.509 certificates for security in XML messages

5. How to use a random number as an encryption key in XML messages

6. How to use XML Security Suite for Java (XSS4J) from IBM alphaWorks toauthor and process secure XML documents

7. How to integrate XSS4J into a JMS application for secure XMLmessaging

8. How to develop a sample JMS-based messaging application that uses thesecurity features of XSS4J

About this tutorial

Part 1 covered everything in the list above except XSS4J, so Part 2 focusesprimarily on using XSS4J.

Prerequisites

This tutorial is aimed at Java programmers, so you should have a solidunderstanding of the Java language. (For more background on this topic, visit thedeveloperworks New to Java technology page.) Specific knowledge of JMS is notnecessary but helpful.

You also need to understand XML at least to the extent of being able to manuallyread and write XML files. (Visit the developerWorks New to XML page for morebackground.) You need to know how the Document Object Model (DOM) works onlyif you wish to change the code in this tutorial to suit your own applications. However,if you just wish to understand the material in this tutorial, you don't need to knowDOM.

It is helpful (but not necessary) for you to be familiar with basic concepts of security

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 2 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 3: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

such as private and public keys, signatures, and encryption.

Should I take this tutorial?

This tutorial does not discuss all the details of how to use JMS for normal enterprisemessaging. If you wish to learn how to use JMS, you can refer to the following IBMdeveloperWorks articles:

• "Introducing the Java Message Service" (June 2004)

• " JMS, XML, and the heterogeneous enterprise" (April 2000)

• " JMS 1.1 simplifies messaging with unified domains" (August 2002)

Tutorial topics

Part 2 is divided into the following sections:

1. Tutorial introduction.

2. Demonstration of how to use XML Security Suite for Java (XSS4J) to signXML data. This section comprehensively explores the XML signatureauthoring features of XSS4J. At the end of this section, I use XSS4J tobuild signature authoring support into the SecureXMLMessage class ofXML-JMS that I started to build in Part 1.

3. Discussion on using XSS4J to verify the XML signature that you authoredin the previous section. This section will conclude by implementing thesignature verification logic in the SecureXMLMessage class.

4. Demonstration of how to use XSS4J for XML encryption. This sectionwraps up by implementing the XML encryption functionality in theSecureXMLMessage class.

5. Explanation of how to use XSS4J to decrypt the XML data that youencrypted in the previous section. This section concludes by puttingtogether all the concepts of signature, verification, encryption, anddecryption in secure XML messaging applications.

6. Summary of the tutorial series.

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 3 of 77

Page 4: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Code samples and installation requirements

The code for this tutorial works with any JMS 1.1-compliant implementation. I listseveral JMS implementations in Resources, which you can download and try.

I ran the code in this tutorial with these JMS implementations:

• The reference implementation that comes with Java 2 Enterprise EditionSoftware Development Kit (J2EE SDK) version 1.4.1 from Sun. You candownload J2EE SDK from the J2EE Web site.

• OpenJMS, an open source JMS implementation, which you can downloadfrom the OpenJMS Web site.

For any JMS implementation to work, you need to have a Java Development Kit(JDK) installed in your computer. I tried the samples in this tutorial with JDK version1.5.0, which you can download from Sun's Web site (see Resources).

You also need to download and install XSS4J from the IBM alphaWorks Web site(see Resources).

Section 2. Implementing XML signature authoring

An introduction to XSS4J

XML Security Suite for Java (XSS4J) from IBM alphaWorks is an open sourceimplementation of XML security specifications. (See Resources for a link.) XSS4Jprovides the following features:

• An XML Digital Signature (XMLDS) implementation that includes supportfor signing XML elements and verifying XML signatures.

• An implementation of the XML Encryption (XEnc) specification. You canuse XSS4J to encrypt your data, wrap it inside an XML format, anddecrypt the encrypted XML data.

• An Abstract Syntax Notation One (ASN.1, a notation commonly used todefine the data format for Internet standards) library developed by the

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 4 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 5: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

IBM Zurich Research Lab. This library allows XSS4J to translate ASN.1data (for example, an X.509 certificate) into XML format and back.

• Support for Base64 encoding and decoding (recall the "Author theReference element" section of Part 1 where I mentioned the use of base64 encoding and decoding). XSS4J can directly wrap binary data (such asa digest or a signature value) into an XML document.

• Ability to work with cryptographic classes in Java code. For example, ifyour certificate is loaded into an X509Certificate object (which isincluded in the java.security.cert package of Java 2 Platform,Standard Edition, or J2SE), XSS4J can internally process your certificateto extract the required information.

• Ability to canonicalize XML data (recall the "Author theCanonicalizationMethod element" section of Part 1, where Idiscussed canonicalization). XSS4J uses its canonicalization classesinternally while authoring and processing XML signatures.

XSS4J handles all of these issues, so you don't need to worry about handlinglow-level issues like ASN.1 syntax, canonicalization, and base64 encoding whileworking with XSS4J.

In this section, I show you how to use XSS4J to implement signature authoringsupport in the SecureXMLMessage class that I introduced in the "Add signaturesupport to the XMLMessage class" section of Part 1. Therefore, it makes sense tostart by exploring how to use XSS4J.

Signing an XML message using XSS4J

Recall from the "Signing XML messages" section of Part 1 that signing an XMLmessage involves several steps. However XSS4J relieves you of most of the difficultprocessing. You need to perform the following simple steps to use XSS4J for XMLsignature authoring:

1. Prepare a template generator. The template generator authors an XMLtemplate signature to start with. The template defines the structure of theXML signature that you want to author. Then you tell XSS4J whatcanonicalization, digest, and signature algorithms you intend to use forXML signing. You also set the input XML document (which contains theelement you want to sign) into the template generator.

2. Use XSS4J to create a reference from the XML signature to the data

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 5 of 77

Page 6: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

being signed.

3. Load your certificate from a key store using J2SE classes and set yourcertificate into the template generator. XSS4J internally extracts thesubject name from the certificate and authors a KeyInfo elementaccordingly.

4. Instantiate a signature context. XSS4J uses the signature context to wrapthe entire process of authoring an XML signature. The signature contextuses the template signature and several lower-level classes forcanonicalization, base64 encoding, cryptography, and other processes toproduce the required signature.

5. Finally, produce the XML signature using signature context and appendthe newly produced XML signature to the input XML document.

Next, you will see a demonstration of each of these five steps.

Preparing the template generator

XSS4J has a class named TemplateGenerator that provides the followingfunctionality:

• It can author a template or a skeleton signature. The template signaturedescribes the structure of an XML signature.

• It takes canonicalization, digest, and signature algorithm values and setsthem in the template signature.

• It wraps a KeyInfo element in the signature template.

Listing 1 shows a template signature that contains several TBDs (things To BeDone). I will show you how to use XSS4J to replace these TBDs with their actualvalues.

Listing 1. A template XML signature

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">

<SignedInfo>

<CanonicalizationMethod Algorithm = "TBD">

</CanonicalizationMethod>

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 6 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 7: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

<SignatureMethod Algorithm = "TBD">

</SignatureMethod>

<Reference URI="TBD">

<DigestMethod Algorithm = "TBD">

</DigestMethod>

</Reference>

</SignedInfo>

<KeyInfo>

<X509Data>TBD </X509Data>

</KeyInfo>

</Signature>

Now you will see the programmatic steps you need to take to author this signaturetemplate using the TemplateGenerator class.

Step 1: First, instantiate the TemplateGenerator class.

TemplateGenerator templateGenerator = new TemplateGenerator();

Next, instantiate a DOM document object and set it in the TemplateGeneratorinstance. The template signature that the TemplateGenerator class authors willbelong to this DOM document. Here you can also use the DOM representation of theinput XML document that contains the element to be signed.

DocumentBuilder documentBuilder = DOMParserNS.createBuilder();

documentBuilder.setErrorHandler(new StandardErrorHandler());

Document document = documentBuilder.parse(new File("input.xml"));

templateGenerator.setDocument(document);

Step 2: In Listing 1, the CanonicalizationMethod element contains an attributenamed Algorithm. Now you need to set the value of this attribute.

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 7 of 77

Page 8: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

templateGenerator.setCanonicalizer(Canonicalizer.W3C2);

XSS4J provides a class named Canonicalizer which handles canonicalization.The Canonicalizer.W3C2 field used in the setCanonicalizer() methodshown above is a static field of the Canonicalizer class. This field refers to theW3C canonicalization specification. XSS4J internally uses the Canonicalizerclass according to the canonicalization algorithm specified to thesetCanonicalizer() method.

In this section, I demonstrate XML signature authoring. Canonicalization is just oneoperation of the signature authoring process. However, if you just want tocanonicalize your XML document, you can use the Canonicalizer classes ofXSS4J directly, as shown here:

W3CCanonicalizer2 w3CCanonicalizer2 = new W3CCanonicalizer2();

w3CCanonicalizer2.canonicalize(aDOMNode, anOutputStreamObject);

Step 3: Next, you need to set the value of the Algorithm attribute of theSignatureMethod element shown in Listing 1:

templateGenerator.setSignatureMethod(SignatureMethod.RSA);

XSS4J contains a class named SignatureMethod that represents theSignatureMethod element. The SignatureMethod class contains static fields torepresent popular signature algorithms like RSA, DSA, and HMAC. While signing,XSS4J internally uses the specified algorithm to calculate the signature value.

Step 4: Now you set the digest algorithm to be used while signing the XML:

templateGenerator.setDefaultDigestMethod(DigestMethod.SHA1);

XSS4J has a class named DigestMethod, which is responsible for authoring the

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 8 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 9: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

DigestMethod element. It contains static fields to represent popular digestalgorithms like SHA1, SHA256, and SHA512. XSS4J uses the DigestMethod classinternally to calculate the digest value according to the specified algorithm and toauthor the complete DigestMethod element.

So you have prepared the template generator and set the values of thecanonicalization, signature, and digest algorithms in the template generator. Thetemplate generator will use these values to author the signature, but it cannotproduce the signature until you create the Reference element shown in Listing 1.That's what you will do in the next section, after which you will be able to see the firstversion of the generator's output.

Creating a reference

In Listing 1, the Reference element has an attribute named URI. This attributerefers to the XML element you want to sign.

XMLDS allows several referencing schemes including fragment identifiers andXPath. In this tutorial, you only use fragment identifiers to refer to the XML elementto be signed.

The TemplateGenerator class has a method named createReference() thatauthors a Reference element. The createReference() method takes just oneparameter -- the value of the URI attribute. Since you use fragment identifiers here,you need to pass a fragment identifier along with the createReference() methodcall:

Reference reference = templateGenerator.createReference("#"+elementID);

XSS4J provides a class named Reference that represents the Referenceelement. The createReference() method returns an instance of the Referenceclass.

You created the Reference element, but the newly-created reference is still notpart of the template. Call an addReference() method to add the Referenceelement to the signature template:

templateGenerator.addReference(reference);

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 9 of 77

Page 10: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

The TemplateGenerator class has a method namedgetSignatureElement(), which returns the DOM representation of the templatesignature.

Element signatureElement = templateGenerator.getSignatureElement();

At this point, if you call getSignatureElement() as shown above, you will getthe Signature element shown in Listing 2:

Listing 2. The template signature after authoring the Reference element

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">

<SignedInfo>

<CanonicalizationMethod

Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315">

</CanonicalizationMethod>

<SignatureMethod

Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1">

</SignatureMethod>

<Reference URI="#cost-021">

<DigestMethod

Algorithm="http://www.w3.org/2000/09/xmldsig#sha1">

</DigestMethod>

<DigestValue></DigestValue>

</Reference>

</SignedInfo>

<SignatureValue></SignatureValue>

</Signature>

If you compare Listing 2 to Listing 1, you can see that Listing 2 contains values forall the algorithms as well as the Reference element. However, it lacks a KeyInfo

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 10 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 11: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

element and values for DigestValue and SignatureValue elements.

In the next couple of sections you will learn how to use XSS4J to author a KeyInfoelement and insert it into the signature template.

Working with certificates in Java code

I discussed X.509 certificates in the "X.509 certificates" section of Part 1. Since I amabout to show you how to use a certificate to sign XML messages, now is a goodtime to discuss how to use certificates in Java applications.

First, you need to know how to fetch a certificate. A certificate is issued by aCertificate Authority (CA). An enterprise can host its own CA. Resources containslinks to some CA implementations that you can use as an enterprise CA.

CAs are also available as hosted services through certain service providers. I alsoincluded links to some of these service providers in Resources.

The Java language has its own tool for generating, storing, and managingcertificates. The tool is called a keytool, and I'll now show you how to use it togenerate a certificate:

X:\>keytool

-genkey

-alias ishtiaq

-keyalg RSA

-dname "CN=Ishtiaq Hussain, OU=ProductionDepartment,

O=ManufacturingEnterprise, C=PK"

-keypass my-key-pass

-keystore MyKeyStore

-storepass my-key-store-pass

When you run the keytool as a Java application as shown above, provide thefollowing parameters:

• The genkey parameter specifies that you want to use keytool togenerate a new certificate.

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 11 of 77

Page 12: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

• The alias parameter provides an alias or name for the certificate. Thecertificate resides inside a key store (along with many other certificates)and the alias identifies the certificate in the key store. You can chosewhatever alias you like. The alias is only relevant as long as the certificateresides within the key store; the alias is not applicable outside the keystore.

• The keyalg parameter specifies the type of the cryptographic key that'sused by the newly generated certificate.

• The dname parameter specifies a distinguished subject name (or justsubject name, for short) of the certificate owner. Note that the subjectname is different from the alias. The alias is only relevant while identifyingthe certificate among the other certificates in the same store, while thesubject name always remains the same for a particular certificate, nomatter which store you use to keep the certificate.

• The keypass parameter specifies a password that you will later use toaccess the private key of the certificate.

• The keystore parameter is the name of the store in which you want tokeep the newly generated certificate. keytool is intelligent: It will try tolocate the key store; if it can't find one, it will automatically create a newone.

• The storepass parameter specifies a password that you provide everytime you want to access any certificate in the store.

You can load a key store in a Java object named KeyStore. First you need toinstantiate the KeyStore object:

KeyStore keyStore = KeyStore.getInstance("JKS");

The getInstance() static method shown above returns a KeyStore object.

In this tutorial, you will use the default key store that comes with JDK1.5.0. Sinceyou have passed the "JKS" string to the getInstance() method, that means youare using the default Java Key Store.

You can load the store into the KeyStore object by providing the store password:

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 12 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 13: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

keyStore.load( new FileInputStream("MyKeyStore"),

"my-key-store-pass".toCharArray() );

Now you can access any certificate in the key store:

X509Certificate x509Certificate =(X509Certificate) keyStore.getCertificate("ishtiaq");

Note the use of the X509Certificate class, which is part of the"java.security.cert" package. The X509Certificate class exposes many usefulmethods for extracting the different data fields of an X.509 certificate. Later, inLooking for a certificate in your key store, I will demonstrate the use of somemethods of the X509Certificate class.

You also need the private key that's associated with the certificate. The following lineof code fetches the private key for you:

Key key = keyStore.getKey("alias", "my-key-pass".toCharArray() );

Notice from this code that the getKey() method takes the alias of the certificatesand the password to access the private key as parameters. It returns the private keythat's associated with the certificate. Later, I'll show you how to use this private keyto sign an XML element.

Preparing the KeyInfo element

Now you'll author a KeyInfo element, which wraps the subject name of yourcertificate.

XSS4J has a class named KeyInfo, which can author a KeyInfo element for you.You just have to follow these five simple steps:

1. Instantiate the KeyInfo class:

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 13 of 77

Page 14: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

KeyInfo keyInfo = new KeyInfo();

2. Instantiate another class named X509Data, which is an inner class ofKeyInfo:

KeyInfo.X509Data x509Data = new KeyInfo.X509Data()

The X509Data class handles the authoring of the X509Data child of theKeyInfo element.

3. Set the certificate parameters that you want to include in the X509Dataelement:

x509Data.setParameters (x509Certificate, false, false, true);

The first parameter in the setParameters() method is your certificate.The other three parameters are Boolean type.

If the second parameter is true, the certificate issuer information (whichpertains to the CA who issued the certificate) will be included in theX509Data element.

If the third parameter is true, a subject key identifier for your certificate willbe included in the X509Data element. Note that I am not discussingcertificate issuer information and subject key identifier fields in thistutorial, as they are too complex to cover in a tutorial of this length. Iinclude a link to an article in Resources that explains all the fields ofX.509 certificates.

If the fourth parameter is true -- as it is in the example above -- thesubject name of the certificate will be included in the X509Data element.

4. Set the X509Data object in the KeyInfo object of step 1. For thispurpose, the KeyInfo class has a method named setX509Data():

keyInfo.setX509Data( new KeyInfo.X509Data[] { x5Data } );

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 14 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 15: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Note that XMLDS allows any number of X509Data elements to appearinside a single KeyInfo element. That's why the setX509Data()method takes an array of X509Data objects.

5. Finally, you insert the KeyInfo element into the signature template thatyou prepared earlier at the end of Preparing the template generator:

keyInfo.insertTo(signatureTemplate);

After you insert the KeyInfo element, the template signature looks like that inListing 3:

Listing 3. The template signature after inserting the KeyInfo element

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">

<SignedInfo>

<CanonicalizationMethod

Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315">

</CanonicalizationMethod>

<SignatureMethod

Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1">

</SignatureMethod>

<Reference URI="#cost-021">

<DigestMethod

Algorithm="http://www.w3.org/2000/09/xmldsig#sha1">

</DigestMethod>

<DigestValue></DigestValue>

</Reference>

</SignedInfo>

<SignatureValue></SignatureValue>

<KeyInfo>

<X509Data>

<X509SubjectName>

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 15 of 77

Page 16: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

CN=Ishtiaq Hussain,

OU=ProductionDepartment,

O=ManufacturingEnterprise,

C=PK

</X509SubjectName>

</X509Data>

</KeyInfo>

</Signature>

Note that only the DigestValue and SignatureValue elements in Listing 3 donot have values. The rest of the signature is complete. In the next section, you willuse XSS4J to produce the values of these two elements.

Putting it all together

XSS4J provides a class named SignatureContext, which wraps the entireprocess of signature authoring. Now you'll instantiate the SignatureContextclass:

SignatureContext signatureContext = new SignatureContext();

At this stage, you also need a class that can resolve (or dereference) the URIattribute value of the Reference element (refer to Creating a reference where Ishowed you how to author the URI attribute value). The SignatureContext classwill use this resolver class to dereference the URI to find the XML element that youwish to sign.

The dereferencing mechanism depends upon what referencing scheme you wish touse while authoring the URI attribute value. Here, you will use a fragment identifieras the URI attribute value.

XSS4J has a very flexible architecture for dereferencing the URI attribute value. Itdefines an interface named IDResolver, which contains just one method namedresolveID().

You will implement the URI dereferencing logic according to your own referencing

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 16 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 17: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

scheme in the resolveID() method of your resolver class. You will set a resolverobject in the SignatureContext class, which will automatically call theresolveID() method to dereference the URI attribute value.

XSS4J also provides a few implementations of the IDResolver interface accordingto some popular referencing schemes. One of the implementations (a class namedAdHocIdResolver) is suitable for dereferencing a fragment identifier. So, you setan AdHocIdResolver object in the SignatureContext object:

signatureContext.setIDResolver( new AdHocIDResolver(document));

The document parameter of the AdHocIdResolver constructor is a DOMdocument. It should be the input XML document that contains the element to besigned.

Note that whenever you wish to locate an element with a particular ID attribute valuein an XML document, you can directly use the AdHocIdResolver class to find therequired element.

AdHocIDResolver adHocIDResolver = new AdHocIDResolver (document);

Element requiredElement = adHocIDResolver.resolveID(document, elementID );

Next, provide the signature template and the private key to thesignatureContext.sign method:

signatureContext.sign( signatureTemplate, key );

This gives you the complete XML signature, as shown in Listing 4:

Listing 4. The complete XML signature

<quotation>

<items>

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 17 of 77

Page 18: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

<item Id="item-021">

<model>PF486</model>

<description>Power factor controller</description>

<quantity>95</quantity>

<unit>Nos.</unit>

</item>

<item Id="item-022">

<model>KN34</model>

<description>Voltage controller</description>

<quantity>15</quantity>

<unit>Nos.</unit>

</item>

</items>

<costs>

<cost Id="cost-021" currency="rupees" itemRef="#item-021">

454,567.6

</cost>

<cost Id="cost-022" currency="rupees" itemRef="#item-022">

231,165.3

</cost>

</costs>

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="Signature-021">

<SignedInfo>

<CanonicalizationMethod

Algorithm=http://www.w3.org/TR/2001/REC-xml-c14n-20010315 />

</CanonicalizationMethod>

<SignatureMethod

Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1">

</SignatureMethod>

<Reference URI="#cost-021">

<DigestMethod

Algorithm="http://www.w3.org/2000/09/xmldsig#sha1">

</DigestMethod>

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 18 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 19: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

<DigestValue>mnL7YAiloQng/NqQQbed9R3RWVc=</DigestValue>

</Reference>

</SignedInfo>

<SignatureValue>

GLa2Z/21piLmk3WHIf3NkrVY8nvt2HXrCJ7TZ1MvjhHw2dPm1

4xqmzRqCXfJUvy6tfPhCSq2DQwoZjx8CKVUcea2wfYScQGYokc

FTKmpNc79w0pWdUSGePENcOJWfP09T3rP+YS6NG0tXAp0

87XOziHnXIyYrNOuSV0/jjBYFx4=

</SignatureValue>

<KeyInfo>

<X509Data>

<X509SubjectName>

CN=Ishtiaq Hussain,

OU=Production Department,

O=Manufacturing Enterprise,

L=LHR,ST=PU,C=PK

</X509SubjectName>

</X509Data>

</KeyInfo>

</Signature>

</quotation>

Finally, extract the document element from the XML document and append theSignature element as its last child.

Element root = document.getDocumentElement();

root.appendChild(signatureElement);

Let me summarize what you did to produce the XML signature. First you prepared atemplate signature using the TemplateGenerator class. The template defined thestructure of the XML signature that you were about to author.

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 19 of 77

Page 20: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Then you created a Reference element and added it to the template. Next, youobtained your private key from a key store and prepared a KeyInfo element.

Finally, you used the SignatureContext class to put everything together andproduce the required XML signature.

I have included a sample application named SignWithXSS4J in the source codedownload for this tutorial. This application contains all the code demonstrated in thissection so far.

Preparing a test arrangement for SecureXMLMessage

Now it's time to implement signature authoring support in the SecureXMLMessageclass.

It is not wise to debug the security features of the SecureXMLMessage class in areal JMS messaging environment. That's because developing security featuresinvolves trying your code in small chunks over and over again. If you are doing thisin a real JMS environment, you will need to startup and shutdown your JMS serverdozens of times, which is very time consuming even on reasonably fast machines.

A better technique is to prepare a test class that acts as a "test jig" to debug theSecureXMLMessage class. Later in Running a secure XML-JMS application (nearthe end of this tutorial), you will try SecureXMLMessage in a real JMS environment.

I prepared a simple test class named SampleSigningClient to test and debugthe XML signing capability of the SecureXMLMessage class. Listing 5 shows theSampleSigningClient class.

Listing 5. The SampleSigningClient class

public class SampleSigningClient

{

private String keyName = new String("ishtiaq");

private String keyPass = new String("my-key-pass");

private String storeName = new String("MyKeyStore");

private String storePass = new String("my-key-store-pass");

private String elementID = new String("cost-021");

private String digestAlgo = new String("http://www.w3.org/2000/09/xmldsig#sha1");

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 20 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 21: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

private String signatureID = new String("Signature-021");

private String signatureAlgo =new String("http://www.w3.org/2000/09/xmldsig#rsa-sha1");

private String canonicalAlgo =new String("http://www.w3.org/TR/2001/REC-xml-c14n-20010315");

public SampleSigningClient(){

try{

DocumentBuilder documentBuilder = DOMParserNS.createBuilder();

documentBuilder.setErrorHandler(new StandardErrorHandler());

Document doc = documentBuilder.parse("input.xml");

TextMessage tm = new TextMessage();

SecureXMLMessage sxm = new SecureXMLMessage (tm);

sxm.setXMLDOMDocument (doc);

sxm.loadCertificateStore (storeName, storePass, keyName, keyPass);

sxm.sign(elementID,

signatureID,

keyName,

keyPass);

}catch(Exception e){

e.printStackTrace();

}

}

public static void main(String [] args){

SampleSigningClient signingClient = new SampleSigningClient();

}

}

The SecureXMLMessage class requires an object that exposes thejavax.jms.TextMessage interface. An object exposing this interface is notavailable outside the JMS environment. Therefore, I also wrote a class namedTextMessage which contains methods and functionality required by the

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 21 of 77

Page 22: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

SecureXMLMessage class. Listing 6 shows the TextMessage class:

Listing 6. The TextMessage class

package com.jms.xml;

public class TextMessage {

private String textMessage = null;

public TextMessage(){

}

public void setText(String message){

this.textMessage = message;

}

public String getText(){

return textMessage;

}

}

The source code download for this tutorial contains the SampleSigningClientand TextMessage classes in both source code and compiled form. Later inRunning a secure XML-JMS application, I will also test the completeSecureXMLMessage class in a real JMS messaging environment.

Implementing signature support in SecureXMLMessage

You can see the following methods in the SecureXMLMessage class in Listing 7.

• loadCertificateStore()

• getCertificateFromAlias()

• getPrivateKeyFromAlias()

• createKeyInfo()

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 22 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 23: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

• sign()

Listing 7. The signing methods in the SecureXMLMessage class

//loadCertificateStore()

public void loadCertificateStore (

String storeName,

String storePassword,

String keyName,

String keyPass

)throws KeyStoreException, FileNotFoundException,

IOException, NoSuchAlgorithmException,

CertificateException {

KeyStore keystore = KeyStore.getInstance("JKS");

keystore.load(new FileInputStream(storeName),

storePassword.toCharArray());

CertificateStoreAndKey csk = new CertificateStoreAndKey(keystore,

keyName,

keyPass);

certificateStores.add(csk);

}//loadCertificateStore()

private X509Certificate getCertificateFromAlias(String keyName)throws KeyStoreException

{

X509Certificate x509Certificate = null;

CertificateStoreAndKey csk = new CertificateStoreAndKey();

for (int i=0; i < certificateStores.size();i++)

{

csk = (CertificateStoreAndKey) certificateStores.elementAt(i);

certificateStore = csk.getCertificateStore();

x509Certificate = (X509Certificate)certificateStore.getCertificate(keyName);

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 23 of 77

Page 24: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

if (x509Certificate != null)

break;

}

return x509Certificate;

}//getCertificateFromAlias()

public Key getPrivateKeyFromAlias(String keyName, String keyPassword)

throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException

{

Key key = certificateStore.getKey( keyName,

keyPassword.toCharArray());

return key;

}//getPrivateKeyFromAlias()

private com.ibm.xml.dsig.KeyInfo createKeyInfo( X509Certificate x509Certificate) {

KeyInfo keyInfo = new KeyInfo();

KeyInfo.X509Data x5Data = new KeyInfo.X509Data();

x5Data.setParameters(x509Certificate, false, false, true);

keyInfo.setX509Data(new KeyInfo.X509Data[] { x5Data });

return keyInfo;

}//createKeyInfo

public void sign( String elementID,

String signatureID,

String keyName,

String keyPassword

) throws SignatureStructureException, KeyStoreException,

XSignatureException,NoSuchAlgorithmException,

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 24 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 25: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

UnrecoverableKeyException {

//prepare the template generator

templateGenerator = new TemplateGenerator();

templateGenerator.setDocument(xmldoc);

templateGenerator.setCanonicalizer(Canonicalizer.W3C2);10:49 AM 12/21/2005

templateGenerator.setSignatureMethod(SignatureMethod.RSA);

templateGenerator.setDefaultDigestMethod(XSignature.SHA1);

//create the Reference element

Reference reference = templateGenerator.createReference ("#"+elementID);

templateGenerator.addReference(reference);

Element signatureElement =

templateGenerator.getSignatureElement();

createId ( signatureElement, signatureID);

this.x509Certificate = getCertificateFromAlias(keyName);

if (x509Certificate == null) {

System.out.println("Certificate not found in KeyStore ");

return;

}

//prepare the KeyInfo element

KeyInfo kInfo = createKeyInfo(x509Certificate);

kInfo.insertTo(signatureElement);

key = getPrivateKeyFromAlias(keyName, keyPassword);

if (key == null) {

System.out.println("Key not found in certificate");

return;

}

//prepare the SignatureContext

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 25 of 77

Page 26: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

SignatureContext sigContext = new SignatureContext();

sigContext.setIDResolver(new AdHocIDResolver(xmldoc));

sigContext.sign(signatureElement, key);

//insert the XML signature into the secure XML message

Element root = xmldoc.getDocumentElement();

root.appendChild(signatureElement);

}//sign()

I have already discussed all the low-level details of XML signing using XSS4J, asshown in the methods in Listing 7, so I will only briefly describe the high-level view ofwhat these methods do.

The loadCertificateStore() method loads the user's certificate store into anarray of stores. The loadCertificateStore() method implementation isdesigned to allow an application to call this method any number of times. Each timean application calls this method, it adds a new certificate store to the array. Thisallows the SecureXMLMessage class to work with multiple certificate stores.

As you saw in Listing 7, the loadCertificateStore() method also takeskeyName and keyPass parameters. The keyName and keyPass parameterscorrespond to a private key that you will use later in Decrypting XML data. For themoment, the loadCertificateStore() method just stores these parametersalong with the certificate store in an inner class namedCertificateStoreAndKey for later use.

The getCertificateFromAlias() method looks for a particular certificate fromall the stores loaded into the SecureXMLMessage class. It returns the certificate asan X509Certificate Java object.

Similarly, the getPrivateKeyFromAlias() method returns the private key to beused for signing.

The createKeyInfo() method authors a KeyInfo element and wraps the subjectname of the certificate in that element.

The sign() method authors the complete XML signature. While authoring, itperforms the following tasks:

1. It prepares the template generator.

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 26 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 27: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

2. It creates the Reference element and adds it to template generator.

3. It prepares the KeyInfo element and inserts it into the templategenerator.

4. It prepares the signature context and uses it to author the XML signature.

5. Finally, it inserts the XML signature into the secure XML message.

Section 3. Implementing XML signature verification

Verifying an XML signature, step-by-step

Recall from the "Signing XML messages" section of Part 1 that authoring an XMLsignature involves several steps. Upon receiving an XML message, the recipientapplication needs to verify the signature. The steps required to verify the signature(as outlined by the XML Digital Signature specification) can be logically deducedfrom the signature authoring steps.

While signing, you produced a digest value of the XML data being signed andwrapped the digest value inside a DigestValue element. The recipient applicationwill follow the same procedure to calculate the digest value and compare the digestvalue with the value wrapped inside the DigestValue element. If the two digestvalues match, the signature verification procedure continues; otherwise it fails.

Now the recipient application uses the public key of the signer to verify the XMLsignature. The signature verification procedure is as follows:

1. The recipient application extracts the KeyInfo element from the XMLsignature. For example, look at the KeyInfo element in Listing 8. Itcontains an X509Data element that specifies the subject name of thesigner.Listing 8. A sample Signature element wrapping a KeyInfo element

<Signature Id="Signature-021" xmlns="http://www.w3.org/2000/09/xmldsig#">

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 27 of 77

Page 28: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

<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="//*[@Id=cost-021]">

<DigestMethod

Algorithm = "http://www.w3.org/2000/09/xmldsig#sha1" />

<DigestValue>up4NbeVuâ#¦â#¦</DigestValue>

</Reference>

</SignedInfo>

<SignatureValue>M2s$xb53h4Ch0Elf=...</SignatureValue>

<KeyInfo>

<X509Data>

<X509SubjectName>

CN=Ishtiaq Hussain,

O=ManufacturingEnterprise,

OU=ProductionDepartment,

C=PK

</X509SubjectName>

</X509Data>

</KeyInfo>

</Signature>

2. The recipient application reads the subject name of the signer's certificateand looks into its certificate store to find the certificate of the signer. Itthen extracts the signer's public key from the certificate.

3. Now the recipient application also extracts the signature algorithm fromthe SignatureMethod element shown in Listing 8.

4. The recipient application also extracts the SignedInfo element shown inListing 8. The complete SignedInfo element is the data for which thesignature needs to be verified.

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 28 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 29: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

5. The recipient application also extracts the signature value from theSignatureValue element shown in Listing 8. It base-64 decodes thesignature value to arrive at the actual bytes that represent the signature.

6. Finally, the recipient application verifies the signature over the completeSignedInfo element according to the signature algorithm in step 3.There are three inputs to the signature verification process:

• The public key (from step 2)

• The data for which signature is being verified (from step 4)

• The signature that is to be verified (from step 5)The result of signature verification process is either success or failure.

Using XSS4J to verify an XML signature

In this tutorial, you will use XSS4J to verify an XML signature. This relieves you fromdoing all the low-level XML and cryptographic processing tasks mentioned in theprevious section.

Note that signature verification using XSS4J entails several steps that are similar tothe signature authoring process that you saw in Signing an XML message usingXSS4J.

When you use XSS4J to verify an XML signature, you need to perform the followingtasks:

1. First, do a few initial preparations, like loading your XML document(containing the data for which you wish to verify a signature) into a DOMobject, extracting the Signature element that contains the signature,and loading your key store into a Java object. The key store contains thecertificates of your buddies, some of which may be used in signing theXML message.

2. Prepare a Key object that represents the key to be used in the XMLsignature process. This also requires a few small operations, likeextracting the key-related information from the Signature element,finding the corresponding key from the key store, and loading the key intoa Key Java object.

3. Instantiate a SignatureContext object and a resolver object. The

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 29 of 77

Page 30: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

SignatureContext object is a wrapper for the entire signatureverification process. The resolver object is part of the XSS4J frameworkthat I discussed in Signing an XML message using XSS4J. Once youhave the SignatureContext and the resolver objects, you call thedifferent methods of the SignatureContext object to verify the digestvalue as well as the signature.

The next few sections will elaborate on these three points.

The source code (see Download) for this tutorial contains a sample applicationnamed VerifySignatureWithXSS4J, which contains all the code that I explain inthe next few sections to demonstrate how to use XSS4J for signature verification. Itried VerifySignatureWithXSS4J with several input XML files, all of which areincluded in the source code download. Listing 9 shows one of the input files.

Listing 9. A sample secure XML message

<quotation>

<items>

<item Id="item-021">

<model>PF486</model>

<description>Power factor controller</description>

<quantity>95</quantity>

<unit>Nos.</unit>

</item>

<item Id="item-022">

<model>KN34</model>

<description>Voltage controller</description>

<quantity>15</quantity>

<unit>Nos.</unit>

</item>

</items>

<costs>

<cost Id="cost-021" currency="rupees" itemRef="#item-021">

454,567.6

</cost>

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 30 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 31: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

<cost Id="cost-022" currency="rupees" itemRef="#item-022">

231,165.3

</cost>

</costs>

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="Signature-021">

<SignedInfo>

<CanonicalizationMethod

Algorithm=http://www.w3.org/TR/2001/REC-xml-c14n-20010315 />

</CanonicalizationMethod>

<SignatureMethod

Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1">

</SignatureMethod>

<Reference URI="#cost-021">

<DigestMethod

Algorithm="http://www.w3.org/2000/09/xmldsig#sha1">

</DigestMethod>

<DigestValue>mnL7YAiloQng/NqQQbed9R3RWVc=</DigestValue>

</Reference>

</SignedInfo>

<SignatureValue>

GLa2Z/21piLmk3WHIf3NkrVY8nvt2HXrCJ7TZ1MvjhHw2dPm1

4xqmzRqCXfJUvy6tfPhCSq2DQwoZjx8CKVUcea2wfYScQGYokc

FTKmpNc79w0pWdUSGePENcOJWfP09T3rP+YS6NG0tXAp0

87XOziHnXIyYrNOuSV0/jjBYFx4=

</SignatureValue>

<KeyInfo>

<X509Data>

<X509SubjectName>

CN=Ishtiaq Hussain,

OU=Production Department,

O=Manufacturing Enterprise,

L=LHR,ST=PU,C=PK

</X509SubjectName>

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 31 of 77

Page 32: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

</X509Data>

</KeyInfo>

</Signature>

</quotation>

Preparing to verify an XML signature

Naturally the first step is to load your XML document (containing an XML signature)into a DOM object:

DocumentBuilder documentBuilder = DOMParserNS.createBuilder();

documentBuilder.setErrorHandler(new DefaultHandler());

Document xmlDoc = documentBuilder.parse(new File("input.xml"));

Now you will find the particular Signature element for which you wish to verify theXML signature. There are various ways of finding a particular element from an XMLdocument. For example, the XMLDS specification uses both fragment identifiers andXPath to refer to a particular element. In this tutorial, you'll work with fragmentidentifiers, which are allowed by XMLDS and also supported in XSS4J.

AdHocIDResolver adHocIDResolver = new AdHocIDResolver(xmlDoc);

Element signatureElement = adHocIDResolver.resolveID(xmlDoc, signatureID);

The next step is to load a certificate store as a Java object. I already discussed thedetails of using certificate stores in Working with certificates in Java code.

KeyStore ks = KeyStore.getInstance("JKS");

ks.load(new FileInputStream(storeName), storePassword.toCharArray());

This store is supported to contain the certificate (along with the public key) of the

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 32 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 33: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

signer. You will use the public key to verify the signature.

Parsing the KeyInfo structure

How do you find out which key to use for signature verification? Refer to Listing 9,which contains the XML signature to be verified. The KeyInfo element inside theXML signature contains an X509SubjectName element that defines which key isused for signature verification.

Notice that the X509Data element contains the subject name of the certificate touse for signature verification. Therefore, you need to use XSS4J to extract thesubject name from the KeyInfo element. This involves a few small steps. The firstis to extract the KeyInfo element from the XML signature:

Element keyInfoElementFromSignature = KeyInfo.searchForKeyInfo (signatureElement);

Notice that XSS4J has a class named KeyInfo, which wraps the functionalityrequired for key information processing. It is the same KeyInfo class that Idiscussed in Preparing the KeyInfo element. The KeyInfo class has a staticmethod named searchForKeyinfo(), which takes the DOM structure of aSignature element as a parameter, searches for a KeyInfo child of the signatureelement, and returns the DOM representation of the KeyInfo element.

Now you can instantiate a KeyInfo object, using the KeyInfo element as shownhere:

KeyInfo keyInfo = new KeyInfo (keyInfoElement);

Once you have the KeyInfo object, you can use its methods to extract the subjectname of the certificate to be used for signature verification.

KeyInfo.X509Data[] x509Data = KeyInfo.getX509Data();

Note the use of the getX509Data() method shown above. It returns all theX509Data elements present in the KeyInfo element. XMLDS allows any number

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 33 of 77

Page 34: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

of X509Data elements inside a KeyInfo element. This allows the signer of the datato place her X.509 certificate, as well as one or more pointers to the same certificate,in multiple X509Data elements inside a KeyInfo element. Therefore, the receivercan either use the X.509 certificate or a pointer to the same certificate to retrieve thesigner's public key information.

For each X509Data element, the getX509Data() method returns aKeyInfo.X509Data object. That's why you get an array of KeyInfo.X509Dataelements.

Now you can take each KeyInfo.X509Data object out of the array and extract anarray of X509Certificate objects out of each KeyInfo.X509Data object.

Note that the X509Certificate class does not belong to XSS4J; rather, it is aJ2SE class that's included in a package named "java.security.cert".

Why do you get an array of X509Certificate objects from eachKeyInfo.X509Data object? Why not just one X509Certificate object?Actually, an X509Data element can refer to a chain of certificates instead of singlecertificate. The concept of certificate chaining is used to share trust betweendifferent users. For this tutorial, I'm going to avoid discussing the details of certificatechaining and trust sharing. Therefore, you can assume that the X509Data elementpoints to just one certificate.

X509Certificate[] x509Certs = X509Data[0].getCertificates();

Now you can use the X509Certificate object to extract the subject name fromthe X509Certificate object.

String subjectName = x509Certs[0].getSubjectDN().getName();

You now have the subject name of the certificate whose public key was used to signthe XML namespace. The next task is to find the certificate in your key store.

Looking for a certificate in your key store

Recall from Working with certificates in Java code that you extracted your certificatefor signing through a simple call to the getCertificate() method of the

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 34 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 35: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

KeyStore class. However, the getCertificate() call cannot help you fetch thecertificate to verify somebody else's signature. Why?

The KeyStore.getCertificate() method takes the alias of the certificate as aparameter. However, you don't know the alias of the signer's certificate forverification; you only know the subject name of the certificate -- and there is no wayto know the alias from the subject name.

Therefore, to fetch a certificate with a particular subject name in a key store, youhave to iterate through every certificate in the store. You read the subject name ofevery certificate and compare it with the one you are looking for, returning when youfind the certificate you're after.

Finally you extract the public key from the certificate using theX509Certificate.getPublicKey() method.

Listing 10 implements this logic in a method namedgetPublicKeyFromSubjectName().

Listing 10. The getPublicKeyFromSubjectName() method

public PublicKey getPublicKeyFromSubjectName (String subjectDN)

{

try {

X509Certificate[] storeCerts = getX509Certificates(keystore);

X509Certificate x509Cert = null;

for (int j=0; j < storeCerts.length ; j++) {

String subject = storeCerts[j].getSubjectDN().getName();

if (subject.equals(subjectDN))

x509Certificate = storeCerts[j];

}

if (x509Cert != null)

return x509Certificate.getPublicKey();

}

catch (Exception e) {

e.printStackTrace();

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 35 of 77

Page 36: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

}

return null;

}

private X509Certificate[] getX509Certificates (KeyStore keyStore)

{X509Certificate[] x509Certs = new X509Certificate[0];

try

{

if (keyStore != null) {

Vector vAliases = new Vector();

Enumeration e = keyStore.aliases();

while (e.hasMoreElements())

vAliases.addElement(e.nextElement());

x509Certs = new X509Certificate[vAliases.size()];

for (int i =0; i< vAliases.size(); i++)

x509Certs[i] = (X509Certificate) keyStore.getCertificate((String)vAliases.elementAt(i));

}//if}//try

catch (Exception e) {

e.printStackTrace();

}

return x509Certs;

}

Verifying the signature

Now that you have the public key, you can verify the XML signature.

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 36 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 37: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

As I explained in Putting it all together, the SignatureContext class works as awrapper for the signature authoring and verification process. Now you need toinstantiate the SignatureContext object:

SignatureContext signatureContext = new SignatureContext();

Next, instantiate an ID resolver and set it in the signature context. As I mentioned inPutting it all together, the SignatureContext class uses the ID resolver to locatethe data that is signed to produce the signature.

SignatureContext.setIDResolver(new AdHocIDResolver(xmlDoc))

Finally, call the verify() method of the SignatureContext class. Theverify() method returns a Validity object.

Validity validity = signatureContext.verify(signatureElement, signerPublicKey);

The Validity object contains several flags that the signature context sets duringthe signature verification process. You can call the getCoreValidity() method ofthe Validity object to check if complete signature verification was successful. Ifcomplete signature verification fails, you may call the getSignedInfoValidity()method to determine whether the digest value verification was successful or not:

if (validity.getCoreValidity())

System.out.println("Complete signature verification was successful");

else if (validity.getSignedInfoValidity())

System.out.println("Digest value verification was successful");

Implementing signature verification in SecureXMLMessage

The main signature verification functionality resides in the verify() method of theSecureXMLMessage class, as I explained in the "Add signature support to theXMLMessage class" section of Part 1. However, before you can implement the

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 37 of 77

Page 38: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

verify() method, you need to do some preparations in the SecureXMLMessageclass.

First, add a private helper method named getPublicKeyFromSubjectName() tothe SecureXMLMessage class. This method is similar to thegetPublicKeyFromSubjectName() method that I described earlier in Looking fora certificate in your key store, with one difference.

Since you want to include support for multiple certificate stores in theSecureXMLMessage class, implement the getPublicKeyFromSubjectName()method in such a way that it will take a subject name as a parameter and look for therequired certificate in all of the stores that an application has already loaded into theSecureXMLMessage class.

Listing 11 shows how to implement this functionality in thegetPublicKeyFromSubjectName() method of the SecureXMLMessage class.

Listing 11. The getPublicKeyFromSubjectName() method with multiple storeslookup functionality

private PublicKey getPublicKeyFromSubjectName (String subjectDN)

{

try {

CertificateStoreAndKey csk = new CertificateStoreAndKey();

for (int i=0; i < certificateStores.size();i++)

{

csk = (CertificateStoreAndKey) certificateStores.elementAt(i);

certificateStore = csk.getCertificateStore();

X509Certificate[] storeCerts = getX509Certificates(certificateStore);

X509Certificate x509Certificate = null;

for (int j=0; j < storeCerts.length ; j++) {

String subject = storeCerts[j].getSubjectDN().getName();

if (subject.equals(subjectDN)) {

x509Certificate = storeCerts[j];

System.out.println ("Certificate found with subjectname");

}

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 38 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 39: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

}

if (x509Certificate != null)

return x509Certificate.getPublicKey();

}

}

catch (Exception e) {

e.printStackTrace();

}

return null;

}//getPublicKeyFromSubjectName()

You also have to declare some integer values in the SecureXMLMessage class.The verify() method returns the integer values to tell the results of verification.The integer values are described in Table 1:

Table 1. Signature verification error codesName of variable Value Description

SIGNATURE_NOT_FOUND 0 The specified Signatureelement was not found in theXML document.

SIGNED_ELEMENT_NOT_FOUND1 The signed data referred to inthe Signature element wasnot found in the XML document.

KEYINFO_NOT_FOUND 2 The KeyInfo element was notfound in the Signatureelement.

X509CERTIFICATE_IDENTIFIER_NOT_FOUND3 The KeyInfo does not containa valid identifier for the signer'scertificate.

PUBLIC_KEY_NOT_FOUND 4 The key specified in theKeyInfo element was notfound.

DIGEST_SUCCESS 5 Only DigestValue verifiedsuccessfully; SignatureValueverification failed.

SIGVERIFY_FAILURE 6 Both DigestValue andSignatureValue verificationfailed.

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 39 of 77

Page 40: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

SIGVERIFY_SUCCESS 7 The signature verification wassuccessful. Both DigestValueand SignatureValuesuccessfully verified.

Now you are all set to implement the signature verification login in the verify()method of the SecureXMLMessage class.

Implementing the verify() method

Look at the verify() method implementation in Listing 12:

Listing 12. The verify() method of the SecureXMLMessage class

public int verify(String signatureID)

{

try {

/**** Step1: Get signature element from SecureXMLMessage ****/

AdHocIDResolver resolver = new AdHocIDResolver(secureXMLDoc);

Element signatureElement = resolver.resolveID(secureXMLDoc, signatureID);

if (signatureElement == null)

return SIGNATURE_NOT_FOUND;

/**** Step2: Check for signed element from SecureXMLMessage ****/

if (getSignedElement(resolver, signatureElement) == null)

return SIGNED_ELEMENT_NOT_FOUND;

/**** Step3: Locate Keyinfo from SecureXMLMessage ****/

KeyInfo keyInfo = new KeyInfo(KeyInfo.searchForKeyInfo(signatureElement));

if (keyInfo == null)

return KEYINFO_NOT_FOUND;

/**** Step4: Get X509Data from KeyInfo object ****/

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 40 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 41: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

KeyInfo.X509Data[] x509Data = keyInfo.getX509Data();

if (x509Data == null)

return X509CERTIFICATE_IDENTIFIER_NOT_FOUND;

/**** Step5: Search PublicKey associated with X509Certificate ****/

Key signerPublicKey = null;

if (x509Data[0].getSubjectNames() != null) {

String[] subjectNames = x509Data[0].getSubjectNames();

signerPublicKey = getPublicKeyFromSubjectName (subjectNames[0]);

} else if (x509Data[0].getSerialNumbers() != null) {

BigInteger[] serialNumbers = x509Data[0].getSerialNumbers();

signerPublicKey = getPublicKeyFromSerialNumber (

new Integer(serialNumbers[0].intValue()).toString());

} else if (x509Data[0].getCertificates() != null) {

X509Certificate[] x509Certs = x509Data[0].getCertificates();

String subjectName = x509Certs[0].getSubjectDN().getName();

signerPublicKey = getPublicKeyFromSubjectName(subjectName);

} else

return X509CERTIFICATE_IDENTIFIER_NOT_FOUND;

if (signerPublicKey == null)

return PUBLIC_KEY_NOT_FOUND;

/**** Step6: Instantiate SecureContext object ****/

SignatureContext signatureContext = new SignatureContext();

signatureContext.setIDResolver(new AdHocIDResolver(secureXMLDoc));

Validity signatureVerificationResults =

signatureContext.verify(signatureElement, signerPublicKey);

/**** Step7: Check validition results. ****/

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 41 of 77

Page 42: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

if ( !(signatureVerificationResults.getSignedInfoValidity()

&& signatureVerificationResults.getCoreValidity()))

return SIGVERIFY_FAILURE;

else if ( signatureVerificationResults.getSignedInfoValidity()

&& signatureVerificationResults.getCoreValidity())

return SIGVERIFY_SUCCESS;

else if ( signatureVerificationResults.getSignedInfoValidity()

&& !(signatureVerificationResults.getCoreValidity()))

return DIGEST_SUCCESS;

}catch( Exception e ) {

e.printStackTrace();

}

return SIGVERIFY_FAILURE;

}//verify()

The verify() method takes just one parameter-- the identifier of the Signatureelement you want to verify -- and performs the following steps:

1. It first locates the required Signature element (whose Id attribute valuematches the signatureId parameter) in the secure XML message. If itdoes not find the required Signature element, it returns aSIGNATURE_NOT_FOUND error code.

2. It then searches for a signed element in the secure XML message. If it isnot able to locate the element that was signed, it returns aSIGNED_ELEMENT_NOT_FOUND error.

3. It searches for the KeyInfo element in the XML signature. If it finds aKeyInfo element, it loads it into a KeyInfo object. If it does not find theKeyInfo element, it returns a KEYINFO_NOT_FOUND error.

4. Next it extracts the data related to the certificate used for signing from theKeyInfo object. If it can't find the appropriate identifier for the signer'scertificate, it returns an X509CERTIFICATE_IDENTIFIER_NOT_FOUNDerror.

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 42 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 43: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

5. It then searches for the public key associated with the certificate in thestores already loaded in the SecureXMLMessage class (assuming thatthe application using the SecureXMLMessage class has already calledthe loadCertificateStore() method the appropriate number oftimes to load all the certificates that might possibly be used by theverify() method). If it cannot find the required public key, it returns aPUBLIC_KEY_NOT_FOUND error code.

6. It instantiates a SignatureContext object, sets an ID resolver into thatobject, calls the verify() method, and saves the signature verificationresults in an object named signatureVerificationResults. It thenchecks the results to return one of the following error codes:

• DIGEST_SUCCESS -- if the digest value verifies successfully and thesignature verification fails.

• FAILURE -- if both the digest value and the signature verification fail.If everything goes all right and the signature verification completessuccessfully, then the verify() method returns SUCCESS.

Use the SecureXMLMessage class for signature verification

The source code for this tutorial (see Download) contains a sample applicationnamed SampleSignatureVerifyingClient that demonstrates how anapplication uses signature verification support in SecureXMLMessage. TheSampleSignatureVerifyingClient class uses the same testing arrangementthat I described in Preparing a test arrangement for SecureXMLMessage.

Listing 13 shows the code of the SampleSignatureVerifyingClient class:

Listing 13. The SampleSignatureVerifyingClient class

public class SampleSignatureVerifyingClient {

private String storeName = new String ("keystore");

private String storePass = new String ("storepass");

private String keyName = new String ("keystore");

private String keyPass = new String ("storepass");

private String storeName1 = new String ("keystore1");

private String storePass1 = new String ("storepass");

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 43 of 77

Page 44: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

private String keyName1 = new String ("keystore");

private String keyPass1 = new String ("storepass");

private String signatureID = new String ("Signature-021");

public SampleSignatureVerifyingClient () {

try {

DocumentBuilder documentBuilder = DOMParserNS.createBuilder();

documentBuilder.setErrorHandler(new StandardErrorHandler());

Document doc = documentBuilder.parse("SignedCostQuotation.xml");

TextMessage tm = new TextMessage();

tm.setText("");

SecureXMLMessage sxm = new SecureXMLMessage(tm);

sxm.setXMLDOMDocument(doc);

sxm.loadCertificateStore(storeName, storePass, keyName, keyPass);

sxm.loadCertificateStore(storeName1, storePass1, keyName1, keyPass1);

boolean valid = sxm.verify(signatureID);

System.out.println ("verified = "+valid);

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main (String [] args) {

SampleSignatureVerifyingClient verifyingClient =new SampleSignatureVerifyingClient ();

}

}

SampleSignatureVerifyingClient is very simple. It instantiates aSecureXMLMessage object with a hard-coded secure XML message. Thehard-coded message is the same as that shown earlier in Listing 9.

It then calls the loadCertificateStore() method a couple of times to load the

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 44 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 45: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

certificate stores. It then calls the verify() method several times to demonstratethe different error codes that are returned by the verify() method.

You can see that using SecureXMLMessage to verify XML signatures is quitestraightforward. You just need to have your secure XML message (containing thesignature to be verified) and your key stores (any one of which should contain thekey needed to verify the signature). If you have these two things, you can use theSecureXMLMessage class to verify the XML signature without worrying about anyof the low-level processing details. That's because the SecureXMLMessage classhides all the low-level details and exposes an easy-to-use interface.

Section 4. Using XSS4J for XML encryption

XML encryption, step-by-step

I discussed the XML format for encryption in the "Adding confidentiality to XMLmessage" section of Part 1. Now I will show you how to use XML Security Suite forJava (XSS4J) for XML encryption.

XSS4J provides comprehensive support for XML encryption. It works on the idea ofan encryption template, similar to the signature template that you saw earlier whileXML signing. XSS4J also has an EncryptionContext class that wrapscryptographic details, which allows you to avoid doing low-level programming.

Here are the steps to follow in order to use XSS4J for XML encryption:

1. Prepare an encryption template: An encryption template provides thebasic structure necessary to start the encryption process. The XMLencryption process adds the required data to the template. You will alsoset the required encryption algorithm in the encryption template. Thisconcept is similar to the signature template that you used earlier inPreparing the template generator.

2. Prepare a KeyInfo element: This KeyInfo element is different from theKeyInfo element that I authored earlier in Preparing the KeyInfoelement while authoring an XML signature. I discussed the KeyInfoelement for encrypted data in Listing 29 of Part 1.

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 45 of 77

Page 46: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

3. Prepare an encryption context: The encryption context wraps the entireXML encryption process. You set the encryption template as well as thecryptographic key into the encryption context. You then use theencryption context to produce the required encrypted data.

4. Prepare an encrypted key: I discussed this in the "Wrap an encryptedkey in XML format" section of Part 1. The process of authoring anencrypted key is similar to the process of encrypting data, with twodifferences.

• The KeyInfo structure in an encrypted key is different from that ofencrypted data.

• The encrypted key contains a ReferenceList element that is notfound in an encrypted data structure.

The next four sections will explore the details of these four steps.

Preparing an encryption template

Listing 14 shows the encryption template that you are going to prepare.

Listing 14. An encryption template

<EncryptedData Id="" Type="http://www.w3.org/2001/04/xmlenc#Element"

xmlns="http://www.w3.org/2001/04/xmlenc#">

<EncryptionMethod

Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>

<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">

<RetrievalMethod URI=""/>

</KeyInfo>

<CipherData>

<CipherValue/>

</CipherData>

</EncryptedData>

XSS4J has a class named EncryptedData which represents the EncryptedData

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 46 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 47: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

element of Listing 14. So your first step in preparing the encryption template is toinstantiate an EncryptedData object:

EncryptedData encryptedData = new EncryptedData();

Next, set the type of encryption that you want to do:

encryptedData.setType("http://www.w3.org/2001/04/xmlenc#Element");

This sets the Type attribute of the EncryptedData element that I discussed inListing 27 of Part 1.

Now look at the EncryptionMethod element in Listing 14. XSS4J has a classnamed EncryptionMethod that handles the EncryptionMethod element. Soyou need to instantiate an EncryptionMethod object, set the encryption algorithminto the EncryptionMethod object, and set the same into the EncryptedDataobject:

EncryptionMethod encryptionMethod = new EncryptionMethod();

encryptionMethod.setAlgorithm (EncryptionMethod.TRIPLEDES_CBC);

The CipherData element in Listing 14 has a child named CipherValue. XSS4Jhas classes named CipherData and CipherValue that handle these elements.So now you need to instantiate the CipherData and CipherValue objects and setthe CipherValue object into the CipherData object:

CipherData cipherData = new CipherData();

CipherValue cipherValue = new CipherValue();

The CipherData element is a child of the EncryptedData element in Listing 14,so now you need to set the CipherData object into the EncryptedData object:

encryptedData.setCipherData(cipherData);

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 47 of 77

Page 48: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Preparing a KeyInfo element

Now you will author a KeyInfo element. As you saw in Listing 14, the KeyInfoelement has just one child named RetrievalMethod. XSS4J has classes thathandle the KeyInfo and RetrievalMethod elements.

The first step is to instantiate the KeyInfo and RetrievalMethod objects:

KeyInfo keyInfo = new KeyInfo();

RetrievalMethod retrievalMethod = new RetrievalMethod();

Next, set the URI and Type attribute values of the RetrievalMethod element. Idiscussed these two attributes in Listing 29 of Part 1:

retrievalMethod.setURI("#"+idOfEncKey);

retrievalMethod.setType("http://www.w3.org/2001/04/xmlenc#EncryptedKey");

Now, set the RetrievalMethod object into the KeyInfo object:

keyInfo.addRetrievalMethod (retrievalMethod);

Finally, set the KeyInfo element into the EncryptedData object of the encryptiontemplate:

encryptedData.setKeyInfo( keyInfo );

Now that your encryption template is ready, it's time to create a new DOMdocument:

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 48 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 49: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

DocumentBuilder documentBuilder = DOMParserNS.createBuilder();

documentBuilder.setErrorHandler(new StandardErrorHandler());

Document document = documentBuilder.newDocument();

Pass the document to the EncryptedData object:

Element encryptionTemplate = encryptedData.createElement (document, true);

Note that the createElement() method shown above creates a DOM elementthat represents the EncryptedData element of the encryption template that youhave authored. As you might have guessed, the DOM element belongs to the DOMdocument you just created.

Preparing an encryption context

Next, prepare the encryption context and use it to produce the required XMLEncryptedData.

XSS4J has a class named EncryptionContext, which wraps the entire XMLencryption process. You will instantiate an EncryptionContext object and set theencryption template into the EncryptionContext object. TheEncryptionContext object will also generate an encryption key for you and usethe key for encryption. Therefore, you don't need to worry about low-levelcryptographic details during XML encryption. Now let me show you how to use theEncryptionContext class.

First, you instantiate an EncryptionContext object:

EncryptionContext encryptionContext = new EncryptionContext();

The EncryptionContext class requires cryptographic algorithm support fordifferent encryption algorithms from another helper class namedAlgorithmFactoryExtn. Instantiate the AlgorithmFactoryExtn class and setit into the EncryptionContext class:

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 49 of 77

Page 50: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

AlgorithmFactoryExtn algorithmFactoryExtn = new AlgorithmFactoryExtn();

encryptionContext.setAlgorithmFactory(algorithmFactoryExtn);

Next, set the encryption template and the data to be encrypted into theEncryptionContext class:

encryptionContext.setEncryptedType((Element)

(encryptionTemplate.cloneNode(true)), null, null, null);

encryptionContext.setData(plainText);

At this stage, you ask the EncryptionContext class to generate an encryptionkey for you. You use this key for encryption and later wrap an encrypted version ofthe key in an EncryptedKeyElement, as described in the "Wrap an encrypted keyin XML format" section of Part 1.

Key key = encryptionContext.generateKey();

encryptionContext.setKey(key);

Your encryption context is now ready for encryption, so you need to call theencrypt() method of the EncryptionContext class to encrypt the plain textdata, and then call the replace() method to replace the plain text element with theEncryptedData element:

encryptionContext.encrypt();

encryptionContext.replace();

Preparing an encrypted key

Now I'll show you how to prepare an encrypted key structure as shown in Listing 15:

Listing 15. An encrypted key structure

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 50 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 51: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

<EncryptedKey Id="" xmlns="http://www.w3.org/2001/04/xmlenc#">

<EncryptionMethod

Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>

<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">

<X509Data>

</X509Data>

</KeyInfo>

<CipherData>

<CipherValue></CipherValue>

</CipherData>

<ReferenceList>

<DataReference URI=""/>

</ReferenceList>

</EncryptedKey>

An encrypted key structure is very similar to the encrypted data structure that youjust authored, so the steps for authoring are also similar.

First, you prepare an encrypted key template using XSS4J classes. The onlydifference when authoring an encrypted key template is to use a class namedEncryptedKey instead of the EncryptedData class that you used in Preparing anencryption template.

EncryptedKey encryptedKey = new EncryptedKey();

encryptedKey.setType("http://www.w3.org/2001/04/xmlenc#Element");

EncryptionMethod encryptionMethod = new EncryptionMethod();

encryptionMethod.setAlgorithm(EncryptionMethod.RSA_1_5);

encryptedKey.setEncryptionMethod(encryptionMethod);

CipherData cipherData = new CipherData();

CipherValue cipherValue = new CipherValue();

cipherData.setCipherValue(cipherValue);

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 51 of 77

Page 52: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

encryptedKey.setCipherData(cipherData);

After you author the template, add an Id attribute to the EncryptedKey element.The Id attribute value will match the URI attribute of the RetrievalMethodelement that you authored in Preparing a KeyInfo element.

encryptedKey.setId(idOfEncKey);

Next, add a ReferenceList element to the encrypted key template. Recall that Idiscussed this ReferenceList element in my explanation of Listing 31 in Part 1.

ReferenceList referenceList = new ReferenceList();

DataReference dataReference = new DataReference();

dataReference.setURI("#" + idOfPlaintext);

referenceList.addDataReference(dataReference);

encryptedKey.setReferenceList(referenceList);

Now you need to author a KeyInfo element in the same manner that you used inPreparing a KeyInfo element during XML signature authoring:

KeyInfo keyInfo = new KeyInfo();

KeyName keyName = new KeyName();

keyName.setName(keyName);

keyInfo.addKeyName(keyName);

encryptedKey.setKeyInfo(keyInfo);

Next, instantiate an EncryptionContext object and set an AlgorithmFactoryobject, along with the encrypted key template, into the EncryptionContext:

EncryptionContext encryptionContext = new EncryptionContext();

encryptionContext.setAlgorithmFactory(algorithmFactoryExtn);

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 52 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 53: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

encryptionContext.setEncryptedType((Element)(encryptedKey.cloneNode(true)),

null, null, null);

Set the data to be encrypted into the EncryptionContext object. The key that youused in Preparing an encryption context is the data that you want to encrypt usingthe encrypted key structure:

encryptionContext.setData(plainText);

Next, set the public key (of the intended recipient of the XML message) into theEncryptionContext object. This object uses the public key to encrypt the key thatyou used earlier to produce the EncryptedData structure.

Key publicKey = x509Certificate.getPublicKey();

encryptionContext.setKey(publicKey);

When the intended recipient receives the message, she will decrypt the key usingher private key. Then she will then use the decrypted key to decrypt the data.

Finally, ask the EncryptionContext object to encrypt the key and return thecompleted EncryptedKey structure:

encryptionContext.encrypt();

Element completeEncryptedKeyStructure =

encryptionContext.getEncryptedKeyAsElement();

I have included a sample application named EncryptWithXSS4J in the sourcecode for this tutorial (see Download). This sample contains all the XML encryptioncode that I have discussed in this section so far.

Implementing encryption support in SecureXMLMessage

Now you will use XSS4J to implement XML encryption functionality in the

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 53 of 77

Page 54: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

SecureXMLMessage class. This involves implementing the encrypt() method asshown in Listing 16:

Listing 16. The encrypt() method

public int encrypt( String idOfPlaintext,

String idOfCyphertext,

String idOfEncKey,

String keyName) {

try {

AdHocIDResolver adHocIDResolver = new AdHocIDResolver(secureXMLDoc);

//Element that you want to encrypt in an XML DOM document

Element plainText = adHocIDResolver.resolveID(secureXMLDoc,idOfPlaintext);

//Check Id of plain text parameter

if (plainText == null)

return PLAINTEXT_DOES_NOT_EXIST;

//Check Id of Cipher text parameter

if (adHocIDResolver.resolveID(secureXMLDoc,idOfCyphertext) != null)

return CIPHER_ID_ALREADY_EXIST;

//Check Id of encrypted key

if (adHocIDResolver.resolveID(secureXMLDoc,idOfEncKey) != null)

return ENCRYPTEDKEY_ID_ALREADY_EXIST;

/**** Prepare an encryption template ****/

Element encryptionDataTemplate = authorEncryptedData(idOfCyphertext,

idOfEncKey);

/**** Prepare an encryption context ****/

EncryptionContext encryptionContext = new EncryptionContext();

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 54 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 55: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

AlgorithmFactoryExtn algorithmFactoryExtn = new AlgorithmFactoryExtn();

encryptionContext.setAlgorithmFactory (algorithmFactoryExtn);

encryptionContext.setEncryptedType ((Element)(encryptionDataTemplate.

cloneNode(true)),

null,null,null);

encryptionContext.setData(plainText);

Key key = encryptionContext.generateKey();

encryptionContext.setKey(key);

encryptionContext.encrypt();

encryptionContext.replace();

Element encryptedKeyTemplate = authorEncryptedKey(keyName,

idOfEncKey,

idOfPlaintext);

this.x509Certificate = getCertificateFromAlias(keyName);

Key publicKey = x509Certificate.getPublicKey();

//Checking public key of recipient

if(publicKey == null)

return KEY_NOT_FOUND;

encryptionContext = new EncryptionContext();

encryptionContext.setAlgorithmFactory(algorithmFactoryExtn);

encryptionContext.setData(key);

encryptionContext.setEncryptedType((Element)(encryptedKeyTemplate

.cloneNode(true)),

null,null,null);

encryptionContext.setKey(publicKey);

encryptionContext.encrypt();

Element encryptedKeyElement = encryptionContext.getEncryptedTypeAsElement();

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 55 of 77

Page 56: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

KeyInfo kInfo = createKeyInfo(x509Certificate);

NodeList nl = encryptedKeyElement.getElementsByTagName("KeyInfo");

Element keyInfo = (Element)(nl.item(0));

keyInfo = (Element)encryptedKeyElement.removeChild(keyInfo);

DocumentBuilder docBuilder =

(DocumentBuilderFactory.newInstance()).

newDocumentBuilder();

docBuilder.setErrorHandler(new DefaultHandler());

Document document = docBuilder.newDocument();

keyInfo = (Element) encryptedKeyElement.getOwnerDocument().importNode(

kInfo.getKeyInfoElement(document),

true);

encryptedKeyElement.appendChild(keyInfo);

//Inserting the EncryptedKey element in the XML DOM document

encryptedKeyElement = (Element) secureXMLDoc.importNode(

encryptedKeyElement, true);

secureXMLDoc.getDocumentElement().appendChild(encryptedKeyElement);

}//try

catch (Exception e) {

e.printStackTrace();

}//catch

return SUCCESS;

}

The encrypt() method first checks if the idOfPlainText parameter exists in thesecure XML message. If it does not exist, then the encrypt() method returns aPLAINTEXT_DOES_NOT_EXIST error code.

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 56 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 57: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

The encrypt() method then checks if idOfCipherText exists. If it does, then theencrypt() method returns a CIPHER_ALREADY_OCCUPIED error code.

The method then checks if an EncryptedKey element with idOfEncKey exists. If itdoes exist, then the encrypt() method returns anENCRYPTKEY_ID_ALREADY_OCCUPIED error code.

Next, encrypt() checks whether the public key of the intended recipient is found inthe available certificate stores. If it cannot find the required key, it returns aKEY_NOT_FOUND error code.

After checking these four parameters, the encrypt() method simply uses theconcepts explained in previous four sections.

I have marked the four steps in the encrypt() method of Listing 16. The first stepcorresponds to my discussion in Preparing an encryption template. Step 2corresponds to the discussion in Preparing a KeyInfo element. Similarly, steps 3and 4 correspond to the discussion in Preparing an encryption context andPreparing an encrypted key, respectively.

Testing the encrypt() method

Now you will try the SecureXMLMessage.encrypt() method that you developedin the previous section.

Listing 17 shows a SampleEncryptingClient application that uses the same testarrangement that I described in Preparing a test arrangement forSecureXMLMessage .

Listing 17. The SampleEncryptingClient application

public class SampleEncryptingClient

{

private String keyName = new String("ishtiaq");

private String keyPass = new String("my-key-pass");

private String storeName = new String("MyKeyStore");

private String storePass = new String("my-key-store-pass");

private String idOfEncKey = new String("encryptedKey");

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 57 of 77

Page 58: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

private String idOfPlaintext = new String("cost-021");

private String idOfCyphertext = new String("encryptedData");

public SampleEncryptingClient(){

try{

DocumentBuilder documentBuilder = DOMParserNS.createBuilder();

documentBuilder.setErrorHandler(new StandardErrorHandler());

Document doc = documentBuilder.parse("SignedCostQuotation.xml");

TextMessage tm = new TextMessage();

SecureXMLMessage sxm = new SecureXMLMessage(tm);

sxm.setXMLDOMDocument(doc);

sxm.loadCertificateStore(storeName, storePass, keyName, keyPass);

int msg = sxm.encrypt(idOfPlaintext,

idOfCyphertext,

idOfEncKey,

keyName);

System.out.println ("Encryption: "+msg);

}catch(Exception e){

e.printStackTrace();

}

}

public static void main(String [] args){

SampleEncryptingClient encryptingClient = new SampleEncryptingClient();

}

}

The source code for this tutorial contains the complete SampleEncryptingClientapplication in both source and compiled forms (see Download).

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 58 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 59: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Section 5. Decrypting XML data

Steps to XML decryption

This section demonstrates decryption of XML encrypted data.Listing 18 shows an XML document containing EncryptedData andEncryptedKey elements:

Listing 18. An XML document with EncryptedData and EncryptedKeystructures

<quotation Id="Q-123" xmlns="http://www.aManufacturingEnterprise.com">

<items>

<!-- item elements-->

</items>

<EncryptedData item="cost-021"xmlns="http://www.w3.org/2001/04/xmlenc#"

Type="http://www.w3.org/2001/04/xmlenc#Content">

<EncryptionMethodAlgorithm="http://www.w3.org/2001/04/xmlenc#3des-cbc"/>

<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">

<RetrievalMethod URI="#encryptedKey1"

Type="http://www.w3.org/2001/04/xmlenc#EncryptedKey" />

</KeyInfo>

<CipherData>

<CipherValue>DeX5hfXedRGhsâ#¦...</CipherValue>

</CipherData>

</EncryptedData>

<deliveryPeriods>

<!--Delivery data for items-->

</deliveryPeriods>

<EncryptedKey Id="encryptedKey1"xmlns="http://www.w3.org/2001/04/xmlenc#">

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 59 of 77

Page 60: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

<EncryptionMethodAlgorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>

<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">

<X509Data>

<X509SubjectName>

CN=Bilal Siddiqui, O=ManufacturingSecEnterprise,

OU=CommercialDept, S=PU, C=PK

</X509SubjectName>

</X509Data>

</KeyInfo>

<CipherData>

<CipherValue>XnkCPKha+zTiGJaHVD...kINuk=</CipherValue>

</CipherData>

<ReferenceList>

<DataReference URI="#cost-021"/>

</ReferenceList>

</EncryptedKey>

<!-- other quotation data-->

</quotation>

To decrypt the encrypted portion of an XML document, you need to perform thefollowing steps:

1. To start, extract the required EncryptedData element from the inputXML document.

2. Extract the RetrievalMethod child of the EncryptedData elementand read the URI attribute value of the RetrievalMethod element.

3. The URI attribute value ("encryptedKey1" in Listing 18) is thefragment identifier that points to the EncryptedKey element in Listing18. So now you should extract the EncryptedKey element from the inputXML document.

4. Once you have the EncryptedKey element, read its KeyInfo elementto learn which private key was used to encrypt the key.

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 60 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 61: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

5. Then fetch the required private key from available key stores.

6. Use the private key to decrypt the encrypted key. The decrypted key isthe random number that I discussed in the "Adding confidentiality to XMLmessages" section of Part 1.

7. Once you have the decrypted key, use it to decrypt the EncryptedDatastructure to see the XML data in plain text form.

XSS4J helps you perform these tasks. I'll now demonstrate how to perform thesetasks using XSS4J.

Using XSS4J for XML decryption

Now you'll perform the following simple tasks to decrypt your encrypted XML datausing XSS4J:

1. Create a decryption context, which wraps the entire decryption process.Set all the related information into the decryption context.

2. Create a key resolver object that can take a KeyInfo element and a keystore. The resolver reads key-related information from the KeyInfoelement and finds the corresponding key from the key store.

3. Set the resolver into the decryption context and use that context todecrypt your encrypted XML data.

Next, I'll show you how to perform these tasks.

Preparing a decryption context

This tutorial started by presenting a message exchange scenario in a manufacturingenterprise.

XSS4J provides a class named DecryptionContext that handles the entiredecryption process. So the first step is to instantiate the DecryptionContextclass:

DecryptionContext decryptionContext =

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 61 of 77

Page 62: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

new DecryptionContext();

Next, instantiate an algorithm factory and set it into the DecryptionContextobject. Note that this is the same algorithm factory that you used during encryption inPreparing an encryption context:

AlgorithmFactoryExtn algorithmFactoryExtn =

New AlgorithmFactoryExtn();

decryptionContext.setAlgorithmFactory(

algorithmFactory);

The DecryptionContext class also needs a key retriever. XSS4J provides aninterface named EncryptedKeyRetriever that exposes a method namedretrieve(). This method can retrieve an encrypted key according to the retrievalmethod in the EncryptedData element. The DecryptionContext class calls theretrieve() method during the decryption process.

XSS4J also provides an implementation of the EncryptedKeyRetriever interfacecalled SameDocumentEncryptedKeyRetriever. TheSameDocumentEncryptedKeyRetriever class is suitable for retrieving theEncryptedKey element in Listing 18.

Therefore, you instantiate the SameDocumentEncryptedKeyRetriever classand set the instance into the DecryptionContext object:

EncryptedKeyRetriever sameDocumentEncryptedKeyRetriever =

new SameDocumentEncryptedKeyRetriever();

decryptionContext.setEncryptedKeyRetriever(

sameDocumentEncryptedKeyRetriever

);

You also need to extract the EncryptedData element (that needs to be decrypted)from the input XML file and provide it to the DecryptionContext class:

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 62 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 63: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

AdHocIDResolver adHocIDResolver =

new AdHocIDResolver();

Element encryptedData =

adHocIDResolver.resolveID(idOfEncryptedData);

decryptionContext.setEncryptedType(

encryptedData,

null,

null,

null);

Note that the setEncryptedType() method used above takes four parameters tocompletely specify the type of encryption that you are going to decrypt. The firstparameter is the EncryptedData element. The second is a string that specifies thetype of encryption that I explained while discussing Listing 27 of Part 1. The thirdand fourth parameters take EncryptionMethod and KeyInfo elements,respectively.

However, the EncryptedData element in Listing 18 is self-explanatory, so youshould pass null as the other three parameters.

Implementing key store handling logic

The DecryptionContext class requires a key resolver that can take a KeyInfoelement and find the required private key from a key store. The private key is usedto decrypt the encrypted key. The DecryptionContext class internally uses thekey resolver to find the private key.

XSS4J has an interface named KeyInfoResolver that contains methods that theDecryptionContext uses to find (or resolve) the key. XSS4J also provides animplementation of the KeyInfoResolver interface in a class namedKeyStoreKeyInfoResolver. The KeyStoreKeyInfoResolver class containslogic to handle a key store.

However, there are two small obstacles to using the KeyStoreKeyInfoResolverclass to decrypt the EncryptedData in Listing 18:

• You want to provide support for multiple key stores in theSecureXMLMessage class. Therefore, when you implement thedecrypt() method of the SecureXMLMessage class later (in

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 63 of 77

Page 64: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Implementing decryption logic in SecureXMLMessage ), you will needthe logic to find the particular key store that contains the required privatekey to be used for decryption. Therefore, it is better to build the logic nowbefore you start to use the KeyStoreKeyInfoResolver class.

• The KeyStoreKeyInfoResolver class does not accept the KeyInfostructure shown inside the EncryptedKey element in Listing 18. Instead,it expects and accepts the KeyInfo structure with the KeyName elementshown in Listing 19. The KeyName element wraps the alias of thecertificate whose accompanying private key needs to be used fordecryption.

Listing 19. A KeyInfo structure with a KeyName element

<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">

<KeyName>

alias

</KeyName>

</KeyInfo>

Due to these reasons, you're going to implement a bit of key store handling logicbefore using the KeyStoreKeyInfoResolver class.

While implementing the key store handling logic, you need to do the following:

1. Read the URI attribute value of the RetrievalMethod grandchild of theEncryptedData element.

2. Find the corresponding EncryptedKey element.

3. Read the subject name from the KeyInfo element insideEncryptedKey.

4. Search for the corresponding certificate from all the available stores.

5. Find the name (alias) of the certificate.

6. And finally, author the KeyInfo element of Listing 19 that contains theKeyInfo with the KeyName that wraps the alias.

This might look like a lot of work, but it is not very difficult to implement, as shown in

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 64 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 65: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Listing 20:

Listing 20. Authoring the KeyInfo element of Listing 19

//Author the KeyInfo element

String kInfo = "<KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><KeyName>"

+ cks.getKeyName()

+ "</KeyName></KeyInfo>";

Preparing a key resolver

Now you have the KeyInfo structure required by theKeyStoreKeyInfoResolver class. So, replace the KeyInfo child of theEncryptedKey element with the KeyInfo structure of Listing 19 that you authoredin Listing 20:

InputStream byteData = new ByteArrayInputStream (kInfo.getBytes() );DocumentBuilder documentBuilder = DOMParserNS.createBuilder();documentBuilder.setErrorHandler(new DefaultHandler());Document document = documentBuilder.parse ( new InputSource(byteData));NodeList nl = encryptedKey.getElementsByTagName("KeyInfo");Element disgKeyInfo = (Element)(nl.item(0));disgKeyInfo = (Element)encryptedKey.removeChild(disgKeyInfo);Element cipherData = (Element)

encryptedKey.getElementsByTagName("CipherData").item(0);encryptedKey.insertBefore((Element) encryptedKey.getOwnerDocument().importNode(

document.getDocumentElement(), true),cipherData);

After performing the decryption steps, replace the KeyInfo structure with its originalform.

Next, instantiate the KeyStoreKeyInfoResolver class:

KeyStoreKeyInfoResolver keyStoreKeyInfoResolver =

new KeyStoreKeyInfoResolver (store);

And set the algorithm factory into the KeyStoreKeyInfoResolver object:

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 65 of 77

Page 66: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

keyStoreKeyInfoResolver.setAlgorithmFactory (

algorithmFactoryExtn);

You also need to provide the name (alias) and password for the private key to theKeyStoreKeyInfoResolver object. This object uses the private key fordecryption:

keyStoreKeyInfoResolver.putAliasAndPassword(alias, password);

Next, set the KeyStoreKeyInfoResolver object for decryption mode:

keyStoreKeyInfoResolver.setOperationMode (

KeyStoreKeyInfoResolver.DECRYPT_MODE);

The KeyStoreKeyInfoResolver object is now ready to be used by theDecryptionContext class.

Using the decryption context

Next, set the KeyStoreKeyInfoResolver object into the DecryptionContextobject:

decryptionContext.setKeyInfoResolver(

keyStoreKeyInfoResolver);

You can now use the DecryptionContext object for decryption:

decryptionContext.decrypt();

To fetch the decrypted data, you need to call the getData() method of the

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 66 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 67: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

DecryptionContext class. Read the data returned by the getData() methodinto an InputStream and later form a String object from the stream as shownbelow:

InputStream inputStream = (InputStream) decryptionContext.getData();byte [] temp = new byte[1];String plainText = new String();

while ((temp[0] = (byte)inputStream.read()) != -1)plainText += new String(temp);

Finally, replace the KeyInfo structure that you authored in Listing 20 with itsoriginal form:

NodeList nl = encryptedKey.getElementsByTagName("KeyInfo");Element keyInfo = (Element)(nl.item(0));keyInfo = (Element)encryptedKey.removeChild(keyInfo);cipherData = (Element) encryptedKey.getElementsByTagName("CipherData").item(0);encryptedKey.insertBefore(

(Element) encryptedKey.getOwnerDocument().importNode(disgKeyInfo, true),cipherData);

xmlDoc.normalize();

I have included all the decryption code in an application namedDecryptWithXSS4J, which is included in the source code for this tutorial (seeDownload).

Implementing decryption logic in SecureXMLMessage

Now, implement the decryption logic in the SecureXMLMessage class. Look at thedecrypt() method in Listing 21:

Listing 21. The decrypt() method

public String decrypt(String idOfEncryptedData){

String plainText = new String();

try {

AdHocIDResolver adHocIDResolver = new AdHocIDResolver(xmlDoc);

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 67 of 77

Page 68: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

//Element that you want to encrypt

Element encData = adHocIDResolver.resolveID(xmlDoc,idOfEncryptedData);

if (encData == null)

return new String("ENCDECRYPTEDDATA_ELEMENT_NOT_FOUND");

Element retrievalMethod =

(Element) encData.getElementsByTagName("RetrievalMethod").item(0);

String dataRefURIValue = retrievalMethod.getAttribute( "URI" ).substring(1);

Element encKey = adHocIDResolver.resolveID(xmlDoc,dataRefURIValue);

String subjectName = getSubjectNameFromEncryptedKey(encKey);

if(subjectName == null) {

System.out.println("Subject Name Not Found ....");

return null;

}

CertificateStoreAndKey certificateStoreAndKey =

getStoreFromSubjectName(subjectName);

if(certificateStoreAndKey == null)

return null;

String kInfo ="<KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><KeyName>"

+ cks.getKeyName()

+ "</KeyName></KeyInfo>";

InputStream inputStream = new ByteArrayInputStream (kInfo.getBytes() );

DocumentBuilder documentBuilder = DOMParserNS.createBuilder();

documentBuilder.setErrorHandler(new DefaultHandler());

Document document = documentBuilder.parse ( new InputSource ( inputStream ) );

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 68 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 69: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

NodeList nodeList = encKey.getElementsByTagName("KeyInfo");

Element disgKeyInfo = (Element)(nodeList.item(0));

disgKeyInfo = (Element)encKey.removeChild(disgKeyInfo);

Element cipherData =(Element) encKey.getElementsByTagName("CipherData").item(0);

Document factory = documentBuilder.newDocument();

encKey.insertBefore((Element) encKey.getOwnerDocument().importNode(

document.getDocumentElement(), true),

cipherData);

IDResolver idResolver = new AdHocIdResolver();

KeyStoreKeyInfoResolver keyStoreKeyInfoResolver =

new KeyStoreKeyInfoResolver(certificateStoreAndKey.getCertificateStore());

// Instantiate an algo factory.

AlgorithmFactoryExtn algorithmFactoryExtn = new AlgorithmFactoryExtn();

// Set the algo factory for use by the key resolver.

keyStoreKeyInfoResolver.setAlgorithmFactory(algorithmFactoryExtn);

keyStoreKeyInfoResolver.setIdResolver(idResolver);

keyStoreKeyInfoResolver.putAliasAndPassword (

certificateStoreAndKey.getKeyName(),

certificateStoreAndKey.getKeyPass().toCharArray());

keyStoreKeyInfoResolver.setOperationMode(KeyInfoResolver.DECRYPT_MODE);

EncryptedKeyRetriever encryptedKeyRetriever =

new SameDocumentEncryptedKeyRetriever(xmlDoc);

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 69 of 77

Page 70: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

DecryptionContext decryptionContext = new DecryptionContext();

decryptionContext.setAlgorithmFactory( algorithmFactoryExtn );

decryptionContext.setKeyInfoResolver( keyStoreKeyInfoResolver );

decryptionContext.setEncryptedKeyRetriever(encryptedKeyRetriever);

decryptionContext.setEncryptedType(encData, null, null, null);

decryptionContext.decrypt();

InputStream is = (InputStream) decryptionContext.getData();

byte [] temp = new byte[1];

while ((temp[0] = (byte)is.read()) != -1)

plainText += new String(temp);

nodeList = encKey.getElementsByTagName("KeyInfo");

Element keyInfo = (Element)(nodeList.item(0));

keyInfo = (Element)encKey.removeChild(keyInfo);

cipherData = (Element) encKey.getElementsByTagName("CipherData").item(0);

encKey.insertBefore((Element) encKey.getOwnerDocument().importNode (

disgKeyInfo, true),

cipherData);

xmlDoc.normalize();

return plainText;

}

catch ( Exception e ) {

e.printStackTrace();

}

return null;

}

The decrypt() method performs the following tasks:

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 70 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 71: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

1. It first checks to see if the EncryptedData element with the specified Idexists in the secure XML message. If it cannot resolve the Id into anEncryptedData element, it returns an ENCRYPTED_DATA_NOT_FOUNDerror code.

2. It then tries to find the encrypted key that was used to form theEncryptedData element. If it cannot find the encrypted key, it returns anENCRYPTED_KEY_NOT_FOUND error code.

3. It then tries to find the certificate mentioned in the KeyInfo child of theEncryptedKey element. If it cannot find the required certificate or itsaccompanying private key, it returns a PRIVATE_KEY_NOT_FOUND errorcode.

After performing these checks, it decrypts the EncryptedData using the conceptsthat you learned in the previous few sections and returns the decrypted data.

I included a sample application named SampleDecryptingClient (shown inListing 22) in the source code for this tutorial (see Download). TheSampleDecryptingClient application shows how to use the decryption logic ofthe SecureXMLMessage class.

Listing 22. The SampleDecryptingClient application

public class SampleDecryptingClient

{

private String keyName = new String("ishtiaq");

private String keyPass = new String("my-key-pass");

private String storeName = new String("MyKeyStore");

private String storePass = new String("my-key-store-pass");

private String idOfCyphertext = new String("encryptedData");

public SampleDecryptingClient(){

try{

DocumentBuilder documentBuilder = DOMParserNS.createBuilder();

documentBuilder.setErrorHandler(new StandardErrorHandler());

Document doc = documentBuilder.parse("input.xml");

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 71 of 77

Page 72: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

TextMessage tm = new TextMessage();

SecureXMLMessage sxm = new SecureXMLMessage(tm);

sxm.setXMLDOMDocument(doc);

sxm.loadCertificateStore(storeName, storePass, keyName, keyPass);

String plainText = sxm.decrypt(idOfCyphertext);

System.out.println("Decrypted Plaintext: " + plainText);

} catch(Exception e) {

e.printStackTrace();

}

}

public static void main(String [] args){

SampleDecryptingClient decryptingClient = new SampleDecryptingClient();

}

}

Running a secure XML-JMS application

I have now covered everything you need to know in order to accomplish secure XMLmessaging. It's time to try secure XML messaging over a JMS network.

I included a folder named "SecureXMLMessaging" in the source code download forthis tutorial. This folder contains the message sending and receiving JMSapplications that use XML-JMS for secure XML messaging. Try to run theseapplications according to the instructions in the Readme.txt file, which is alsoincluded in the source code (see Download).

Section 6. Wrap-up

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 72 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 73: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Summary

Part 1 of this two-part tutorial series introduced the idea of secure XML messagingover a JMS network.

Part 2 started by exploring how you can use XSS4J to sign XML data. Thisdiscussion concluded by implementing signature authoring support in theSecureXMLMessage class. Next, I showed you how to use XSS4J to verify XMLsignatures. I also built XML signature verification functionality into theSecureXMLMessage class. The last two sections discussed encryption anddecryption using XSS4J. Finally, I put all the pieces together by examining JMSclients that securely send and receive XML messages.

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 73 of 77

Page 74: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Downloads

Description Name Size Download method

Tutorial code samples x-secmes2-code.zip364KB HTTP

Information about download methods

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 74 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 75: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

Resources

Learn

• JMS 1.1 specification (JSR 914): Read the official spec at Sun's Web site.

• Here is a list of JMS resources on developerWorks:

• "Introducing the Java Message Service" (June 2004) provides a hands-onguide to help you start developing JMS applications.

• "JMS, XML, and the heterogeneous enterprise" (April 2000) demonstrateshow an XML-aware application can author and send XML messages usingJMS.

• "JMS 1.1 simplifies messaging with unified domains" (August 2002) byBobby Woolf shows you how to develop a JMS client using the unified JMSdomain model presented in JMS 1.1.

• Check out these open source JMS implementations:

• OpenJMS

• ActiveMQ

• JORAM

• JBossMQ

• mom4j

• Canonical XML: Link to this recommendation at the W3C.

• XML Canonicalization: Learn how to canonicalize XML messages in this two-partseries of articles by Bilal Siddiqui, this tutorial's author.

• Cryptography FAQ: Find out more about cryptography.

• Check out this XML Encryption series on developerWorks by Bilal Siddiqui:

• "Exploring XML Encryption, Part 1" (March 2002)

• "Exploring XML Encryption, Part 2" (August 2002)

• The official X.509 specification: Get background on X.509 certificates, which areused for security in XML messaging.

• "Manage X.509 certificates in your grid with Java Certificate Services"(developerWorks, October 2003): Author Vladimir Silva provides a set of Web

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 75 of 77

Page 76: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

and command line tools called Java Certificate Services that you can use tomanage user or host certificates on your development grids.

• "Signing Messages with XSS4J": Read this article by Bilal Siddiqui to learn howto sign an XML document using XSS4J.

• Check out these official specifications from the W3C:

• XML Signature and XML Encryption

• XPath

• DOM

• Cascading Style Sheets (CSS)

• "Writing multithreaded Java applications" (developerWorks, February 2001):Learn how to give your Java application an interactive feel.

• RFC2045: Find the link to the Base64 encoding specification from the InternetEngineering Task Force (IETF).

• RFC2253: Read an international standard from the IETF that defines a format forrepresenting distinguished names.

• RFC2437: Find out more about RSA-SHA1, the RSA signature algorithm with theSHA1 digest algorithm. This combination of digest calculation and signaturealgorithms is defined by the IETF.

• developerWorks XML and Java technology zones: Get more background on XMLor Java technology from a wide range of resources for all ability levels.

Get products and technologies

• XML Security Suite for Java (XSS4J) toolkit: Download this toolkit from IBMalphaWorks. It provides digital signing, encryption, and access control support forXML documents.

• OpenCA: Take a look at this full-featured open source CA implementation.

• EJBCA: Try this J2EE-based fully functional CA.

• Free SSL Trial Certificate: This certificate, signed by Verisign, allows you to testthe benefits of Secure Sockets Layer (SSL) technology in a test environment.

• CAcert.org: Get a free digital certificate here, too.

• Apache XML security suite for XMLDS and XEnc: Check out this open sourcetool from Apache.org.

developerWorks® ibm.com/developerWorks

Using XSS4J to implement XML SecurityPage 76 of 77 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 77: Secure XML messaging with JMS, Part 2: Using XSS4J to ...€¦ · messaging over an existing JMS network. Section 1. Before you start About this tutorial series This two-part tutorial

• Java 2 Enterprise Edition Software Development Kit (J2EE SDK): Download itfrom Sun.

• Java 2 Standard Edition (J2SE): Download the JDK from Sun.

Discuss

• Sun's JMS forum: Find lots of discussion material about JMS.

• The IBM alphaWorks XML Security Suite forum: Discuss XML security.

About the author

Bilal SiddiquiBilal Siddiqui is an electronics engineer, an XML consultant, and the co-founder ofWaxSys, a company focused on simplifying e-business. After graduating in 1995 with adegree in electronics engineering from the University of Engineering and Technology,Lahore, he began designing software solutions for industrial control systems. Later, heturned to XML and used his experience programming in C++ to build Web- andWAP-based XML processing tools, server-side parsing solutions, and serviceapplications. He is a technology evangelist and a frequently-published technicalauthor.

ibm.com/developerWorks developerWorks®

Using XSS4J to implement XML Security© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 77 of 77