WS Security

As mentioned earlier, the WS Security specification and an addendum to it were initially published by IBM, Microsoft and VeriSign and have now been submitted to OASIS for further development as a standard. At the time of finalizing this chapter (May 2003), the OASIS Technical Committee has not published the final specification. So our discussion here is going to be based on the original proposed specification and the addendum to it. It goes without saying that there are no standard Java APIs for it.

Why bother covering WS Security if it is yet not a standard and there are no standard Java APIs for it? The reason has to do with its significance to Web services security. Transport-level security is just not adequate for a number of Web services-based applications and there is no other credible alternative standard for message-level security. A number of implementations of the current WS Security specification are already in existence and early adopters are either piloting or even using WS Security in production systems as it is.

The aim of WS Security specification is to specify SOAP Header elements for quality of protection of a single SOAP message or certain parts of it through message integrity, confidentiality and authentication. Toward this, it allows various types of security tokens, or collection of client-made statements, to be embedded within a SOAP message. A security token could be signed, such as X.509 certificate or a Kerberos ticket. It also allows SOAP message elements to be signed, encrypted or signed and encrypted using XML Signature and XML Encryption standards. This is how the goal of message integrity, confidentiality and authentication are met.

WS Security itself is not a security protocol involving the exchange of multiple messages between two communicating parties, although it does allow development of such protocols. Being message-oriented, it enables end-to-end security, even in the presence of intermediate gateways that might do transport protocol conversion and/or need to examine certain portions of the message.

We do not present a detailed discussion of the WS Security specification but instead focus on using a WS Security library built on top of VeriSign's TSIK, the same toolkit that we used for XML-Signature and XML-Encryption in Chapter 7, Securing the Message. Executing the programs written using this library would give us an opportunity to examine the output and understand the structure of messages protected with WS Security.

VeriSign's WS Security library can be downloaded from the same location where we got TSIK, i.e., http://www.xmltrustcenter.org. The download consists of a single jar file, wssecurity.jar and the corresponding source file WSSecurity.java.

If you are keen on knowing more about WS Security, you should read the specification documents and go through the source file WSSecurity.java. As you do so, you will find that WSSecurity.java doesn't implement all options of the WS Security specification. In line with TSIK philosophy, WS Security implementation is designed more for ease-of-use than the completeness of features.

Our objective in this section is to learn about WS Security specification and the VeriSign's API to perform WS Security operations on SOAP messages. We do so by looking at signature creation and verification programs written using VeriSign's WSSecurity class. These programs operate on SOAP messages stored in a file.

The signature creation program, WSSSign.java, is shown in Listing 11-4, that takes a file with a SOAP message as input and produces another file with WS Security compliant SOAP message as output. The output SOAP message has the SOAP body signed and the signature element and the verification key information placed in the SOAP header. We also write a verification program, WSSVerify.java, to verify the signed SOAP message. These source files can be found in srcjsbookch11wss directory.

Listing 11-4. Source File WSSSign.java
// File: srcjsbookch11wssWSSSign.java
public class WSSSign {
  public static void main(String[] args) throws Exception {
    String datafile = args[0];
    outfile = args[1];

    String keystore = "my.keystore";
    String storepass = "changeit";
    String kstype = "JCEKS";
    String alias = "mykey";

    System.out.println("Signing XML data in file "" + datafile + """);
    System.out.println("Using private key in keystore "" +
            keystore + "" ...");

    java.io.FileInputStream fis = new java.io.FileInputStream(keystore);
    java.security.KeyStore ks =
            java.security.KeyStore.getInstance(kstype);
    ks.load(fis, storepass.toCharArray());
    java.security.PrivateKey key = (java.security.PrivateKey)
            ks.getKey(alias, storepass.toCharArray());
    java.security.cert.X509Certificate cert =
          (java.security.cert.X509Certificate)ks.getCertificate(alias);

    org.w3c.dom.Document doc = XmlUtility.readXML(datafile);
    com.verisign.xmlsig.SigningKey sk =
						com.verisign.xmlsig.SigningKeyFactory.makeSigningKey(key);
						com.verisign.xmlsig.KeyInfo ki = new com.verisign.xmlsig.KeyInfo();
						ki.setCertificate(cert);
						com.verisign.messaging.WSSecurity wss =
						new com.verisign.messaging.WSSecurity();
						wss.sign(doc, sk, ki);

    XmlUtility.writeXML(doc, new java.io.FileOutputStream(outfile));
    System.out.println("... Wrote the output to file: "" +
            outfile + """);
  }
}

A bit of explanation is required for this program. First of all, note the use of XmlUtility class introduced in Chapter 7, Securing the Message, for reading and writing XML documents. Another point worth noting is the use of a Java keystore to retrieve a private key and the corresponding certificate. As you know, you need a private key for signing. The certificate is needed for embedding the verification key information in the signature through the KeyInfo object. The actual signing is done by the sign() method of the WSSecurity class. This method signs the SOAP body, and inserts the signature and other relevant information in SOAP Header. We see a sample WS Security-compliant signed SOAP document shortly.

Compiling and executing this program requires both tsik.jar and wssecurity.jar to be in CLASSPATH. Once the program is compiled, let us run it with the following soap.xml input file:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
  <ns1:echo
    soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:ns1="http://www.pankaj-k.net/jsbook/examples/">
   <arg0 xsi:type="xsd:string">Hi, How are you?</arg0>
  </ns1:echo>
 </soapenv:Body>
</soapenv:Envelope>

Assuming that the CLASSPATH has tsik.jar and wssecurity.jar, and the keystore my.keystore is properly initialized with a private key and certificate, issue the following command to run WSSSign program:

C:ch11wss>java WSSSign soap.xml signed.xml
Signing XML data in file "soap.xml"
Using private key in keystore "my.keystore" ...
... Wrote the output to file: "signed.xml"

The signed SOAP message is saved in the signed.xml file. This file is reproduced in Listing 11-5. In this listing, text in different font-weight is used to group the logically related information.

Listing 11-5. WS Security-compliant signed SOAP message
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Header>
   <wsse:Security
						xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext"
						soapenv:mustUnderstand="1">
     <wsse:BinarySecurityToken ValueType="wsse:X509v3"
         EncodingType="wsse:Base64Binary"
         Id="wsse-04554370-7798-11d7-9a53-3d469a48eb3e">
         ... base64 encoded binary data ...
     </wsse:BinarySecurityToken>
     <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
       <ds:SignedInfo>
         <ds:CanonicalizationMethod
             Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
         <ds:SignatureMethod
             Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
         <ds:Reference URI="#wsse-0433b1b0-7798-11d7-9a53-3d469a48eb3e">
           <ds:Transforms>
             <ds:Transform
                 Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
           </ds:Transforms>
           <ds:DigestMethod
                 Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
           <ds:DigestValue>GvYITJtrR35QAvfi08qiTmWmP9A=</ds:DigestValue>
         </ds:Reference>
         <ds:Reference URI="#wsse-042d9730-7798-11d7-9a53-3d469a48eb3e">
           <ds:Transforms>
             <ds:Transform
                 Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
           </ds:Transforms>
           <ds:DigestMethod
               Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
           <ds:DigestValue>WNZ9INu1/7kBC4alIDjcl7RBZ7Q=</ds:DigestValue>
         </ds:Reference>
       </ds:SignedInfo>
            <ds:SignatureValue>base64 encoded binary data</ds:SignatureValue>
       <ds:KeyInfo>
         <wsse:SecurityTokenReference>
           <wsse:Reference
               URI="#wsse-04554370-7798-11d7-9a53-3d469a48eb3e"/>
         </wsse:SecurityTokenReference>
       </ds:KeyInfo>
     </ds:Signature>
   </wsse:Security>
						<wsu:Timestamp
						xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility">
     <wsu:Created
         wsu:Id="wsse-042d9730-7798-11d7-9a53-3d469a48eb3e">
       2003-04-26T03:34:41Z
     </wsu:Created>
   </wsu:Timestamp>
 </soapenv:Header>
 <soapenv:Body
     wsu:Id="wsse-0433b1b0-7798-11d7-9a53-3d469a48eb3e"
     xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility">
   <ns1:echo
       soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
       xmlns:ns1="http://www.pankaj-k.net/jsbook/examples/">
     <arg0 xsi:type="xsd:string">Hi, How are you?</arg0>
   </ns1:echo>
 </soapenv:Body>
</soapenv:Envelope>

WS Security signing has introduced two SOAP Header elements: wsse:Security and wsu:Timestamp. The best way to visualize these elements, their children and their relationship is to look at Figure 11-4.

Figure 11-4. WS Security elements and their relationships.


From this diagram, it is quite clear that the signature has been computed over two elements: the SOAP Body element and the Timestamp Header element inserted by WS Security. The tamper-evident Timestamp provides a limited amount of protection against replay attacks as the recipient can detect duplicates. Another point to note is that the verification key information is not part of KeyInfo element of XML Signature, but rather points to the WS Security element BinarySecurityToken.

The program to verify a WS Security signed SOAP message is in Java source file WSSVerify.java, as shown in Listing 11-6.

Listing 11-6. Source File WSSVerify.java
// File: srcjsbookch11wssWSSVerify.java
public class WSSVerify {
  public static void main(String[] args) throws Exception {
    String datafile = args[0];

    String keystore = "my.keystore";
    String storepass = "changeit";
    String kstype = "JCEKS";

    System.out.println("Verifying SOAP data in file "" + datafile +
          "" using trusted certs");
    System.out.println("in keystore "" + keystore + "" ...");

    java.io.FileInputStream fis = new java.io.FileInputStream(keystore);
    java.security.KeyStore ks =
            java.security.KeyStore.getInstance(kstype);
    ks.load(fis, storepass.toCharArray());

    org.w3c.dom.Document doc = XmlUtility.readXML(datafile);
    org.xmltrustcenter.verifier.TrustVerifier verifier =
						new org.xmltrustcenter.verifier.X509TrustVerifier(ks);
						com.verisign.messaging.WSSecurity wss =
						new com.verisign.messaging.WSSecurity();
						com.verisign.messaging.MessageValidity[] resa =
						wss.verify(doc, verifier, null);

    for (int i = 0; i < resa.length; i++){
      System.out.println("result[" + i + "] = " + resa[i].isValid());
    }
  }
}

This program uses the public key of the signer from the keystore for signature verification. As the certificate of the signer is included in the wsse:Security element, one could use the public key from this certificate as well. This is what happens if you specify null in place of verifier in the verify() method of WSSecurity class. However, if you want to trust only those certificates that are in your truststore or are signed by CAs whose certificates are in your truststore, then you should specify an appropriate verifier.

If you look into the directory srcjsbookch11wss, you find programs to do WS Security-based encryption, decryption, signing and encryption, and validation processing, where validation processing refers to signature verification for a signed document, decryption for an encrypted document, and decryption and signature verification for a signed and encrypted document. Look at their source code and play with these programs, analyze their output the same way we analyzed the signed SOAP message. For running encryption or decryption programs, you need a JCE provider that supports RSA encryption. We have already talked about one such provider, Bouncy Castle JCE Provider, and have used it in Chapter 7, Securing the Message.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.62.197