Java API for XML Encryption

The state of a standard Java API for the XML Encryption is no better than that of the XML Signature. A Java Specification Request, JSR-106 titled XML Digital Encryption APIs, was accepted by JCP at the same time as the JSR for the XML Signature. However, at the time of writing this chapter (March 2003), no public specification has been published.

We used VeriSign's TSIK for writing XML Signature earlier in this chapter. This toolkit also supports XML Encryption, following the same structure of API classes as the XML Signature. Again, the emphasis is on ease of use, and not on comprehensive support for the complete specification.

Let us use TSIK to perform XML Encryption operations.

XML Encryption with TSIK

The best way to understand the XML Encryption TSIK API is to look at the source code of the working program Encrypt.java, shown in Listing 7-13 and available with the JSTK software in the subdirectory srcjsbookch7ex3. This class takes the XML file of Listing 7-1 as the input, encrypts the element with ID value of book_info with a secret key and produces the XML document shown in Listing 7-11 as output.

Listing 7-13. XML Encryption with TSIK
// File: srcjsbookch7ex3Encrypt.java
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import org.w3c.dom.Document;
import javax.crypto.SecretKey;

import com.verisign.xmlenc.Encryptor;
import com.verisign.xmlenc.AlgorithmType;
import com.verisign.xpath.XPath;

public class Encrypt {
  public static void main(String[] args) throws Exception {
    String datafile = "book.xml";
    String encfile = "enc.xml";
    XPath encloc = new XPath("id('book_info')");
    System.out.println("XML file: " + datafile + ", elem. : bookinfo");

    String keyfile = "3des.key";
    FileInputStream fis = new FileInputStream(keyfile);
    ObjectInputStream ois = new ObjectInputStream(fis);
    SecretKey key = (SecretKey)ois.readObject();
    System.out.println("Read key from file: " + keyfile);

    Document doc = XmlUtility.readXML(datafile);
    Encryptor encryptor =
							new Encryptor(doc, key, AlgorithmType.TRIPLEDES);
							Document encryptedDoc = encryptor.encrypt(encloc);
    XmlUtility.writeXML(encryptedDoc, new FileOutputStream(encfile));

    System.out.println();
    System.out.println("Encryption SUCCESSFUL!!");
    System.out.println("Encrypted doc. written to file: " + encfile);
  }
}

The class com.verisign.xmlenc.Encryptor is the main class to do encryption as per the XML Encryption. In the above code, its constructor takes the following arguments: the document with the element to be encrypted, a secret key and the encryption algorithm. The key should be generated for the algorithm with which it is going to be used. In the above code, the key is read from 3des.key file. Actual encryption takes place in the method encrypt(), which takes the XPath expression identifying the to-be-encrypted element.

Although key file 3des.key is pregenerated and is part of the JSTK distribution, you can easily create this file or any other key file using JSTK utility crypttool, as discussed in Chapter 3, Cryptography with Java, by issuing the following command from the JSTK home directory:

C:jstk>bincrypttool genk -algorithm desede -keysize 112 
							-action save -file 3des.key
SecretKey written to file: 3des.key

The program Encrypt.java can be compiled and run the same way as the other XML Signature programs. Assuming that the JSTK subdirectory srcjsbookch7 is copied into c:ch7, go to c:ch7ex3 directory, setup the CLASSPATH environment variable so that it has tsik.jar and the current directory (i.e., ".") as components and issue the following commands:

C:ch7ex3>javac Encrypt.java
C:ch7ex3>java Encrypt
XML file: book.xml, elem. : bookinfo
Read key from file :3des.key

Encryption SUCCESSFUL!!
Encrypted doc. written to file: enc.xml

The encryption performed by the Encrypt class encrypts the whole bookinfo element. What if you wanted only the element content to be encrypted? This is easily accomplished by calling setContentEncryption(true) on the encryptor object before invoking the encrypt() method.

The method encrypt() returns a copy of the XML document with the specified element or element content replaced by the EncryptedData element. There exists another method, encryptInPlace(), which modifies the current document. Wherever appropriate, using this method results in significant memory saving and time speedup. It can also be invoked more than once, each invocation specifying a separate element, to produce multiple EncryptedData elements in the same document.

Let us now turn our attention to the reverse operation—decryption. The program to accomplish this operation is quite similar to the one that performs encryption. Here we show only a small portion of the code. The complete program can be found in file Decrypt.java, located in the same directory within the JSTK installation that holds the file Encrypt.java:

// encfile: name of the XML file that has an EncryptedData element.
// key: the same secret key used for encryption.
// decfile: name of the file to store decrypted data.
Document doc = XmlUtility.readXML(encfile);

String[] ns = {"xenc", "http://www.w3.org/2001/04/xmlenc#"};
							XPath encloc = new XPath("//xenc:EncryptedData", ns);
							Decryptor decryptor = new Decryptor(doc, key, encloc);
							Document decryptedDoc = decryptor.decrypt();

XmlUtility.writeXML(decryptedDoc, new FileOutputStream(decfile));

This code is fairly straightforward—the Decryptor constructor takes the document, the decryption key and the XPath expression identifying the EncryptedData element in the document as arguments. Method decrypt() returns a copy of the document, replacing the EncryptedData element with the decrypted element or element content. Compilation and execution steps are same as the earlier Encrypt.java program.

As we have seen, the XML Encryption specification also supports asymmetric encryption of the secret key used to encrypt the data. This process needs not only a secret key but also a public key. The code fragment illustrating this is given below. The complete working program can be found in source file Encrypt1.java.

// datafile: name of the XML datafile.
// encloc: location of the element (an XPath) to be encrypted.
// key: the secret key to encrypt element identified by encloc.
// pubkey: the public key to encrypt the secret key.

Document doc = XmlUtility.readXML(datafile);
Encryptor encryptor = new Encryptor(doc,
							key, AlgorithmType.TRIPLEDES, pubkey, AlgorithmType.RSA1_5);
							Document encryptedDoc = encryptor.encrypt(encloc);
						

Note that the Encryptor constructor takes a public key and an asymmetric encryption algorithm as input. The algorithm used here, and the only one supported in TSIK 1.7, is RSA. As the JCE (Java Cryptographic Extension) provider bundled with Sun's J2SE v1.4 does not include RSA encryption, you would need a JCE provider that supports RSA encryption to run this program. The JCE Provider from Legions of Bouncy Castle is one such provider. We have already gone through the steps of installing and configuring this JCE Provider in Chapter 3, Cryptography with Java. If you do not have this provider installed on your machine and you want to compile and run class Encrypt1 then you should get the JCE provider from http://www.bouncycastle.org.

You also need a public-private key pair. The public key encrypts the secret key and the private key decrypts the encrypted secret key. However, unlike XML Signature, where the verification is done by the public key and can be included with the Signature element, the decryption key cannot be included in the EncryptedData element, for that would defeat the very purpose of encryption.

To generate a public-private key pair, you can use the JSTK utility crypttool with genkp option, as shown below:

C:jstk>crypttool genkp -algorithm RSA -action save –file test.kp
KeyPair written to file: test.kp

The output file test.kp stores the serialized KeyPair object with PublicKey and PrivateKey as members.

The decryption program corresponding to the above encryption program is in source file Decrypt1.java. The relevant portion of the code is shown below:

// encfile: name of the XML file with EncryptedData.
// prvkey: the public key to encrypt the secret key
Document doc = XmlUtility.readXML(encfile);

String[] ns = {"xenc", "http://www.w3.org/2001/04/xmlenc#"};
XPath encloc = new XPath("//xenc:EncryptedData", ns);
Decryptor decryptor = new Decryptor(doc, prvkey, encloc);
Document decryptedDoc = decryptor.decrypt();

The compilation and execution steps for Encrypt1 and Decrypt1 programs are left as reader exercises.

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

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