Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Managing XML Encryption with Java : Page 5

XML is a text format, and as such, provides no wire security by itself; however, using standard Java encryption techniques, you can transmit and receive XML securely.




Application Security Testing: An Integral Part of DevOps

Performing XML Encryption using Apache XML Security
The EncryptTool class reads input from a file, encrypts the contents of the file, and then stores the encrypted file to disk. The tool uses the Apache XML framework to create two symmetric keys for the following purposes:

  • to encrypt the actual XML file data
  • to encrypt the key used to encrypt the XML file data
The tool writes both the encrypted data and the encrypted encryption key to disk. You need the following imports statements in your code:

package com.jeffhanson.security.encryption; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.security.Key; import javax.crypto.SecretKey; import javax.crypto.KeyGenerator; import org.apache.xml.security.keys.KeyInfo; import org.apache.xml.security.encryption.XMLCipher; import org.apache.xml.security.encryption.EncryptedData; import org.apache.xml.security.encryption.EncryptedKey; import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.xml.transform.TransformerFactory; import javax.xml.transform.Transformer; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.OutputKeys; public class EncryptTool {...}

First, initialize the Apache XML framework—in this case, to the default values.

static { org.apache.xml.security.Init.init(); }

Next, use the following method to read and parse the XML file to be encrypted. The method creates and returns a DOM document.

private static Document parseFile(String fileName) throws Exception { javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse(fileName); return document; }

You need to generate the key used to encrypt the data-encryption tool. The generated key is necessary to store and/or transport the data-encryption tool securely.

private static SecretKey GenerateKeyEncryptionKey() throws Exception { String jceAlgorithmName = "DESede"; KeyGenerator keyGenerator = KeyGenerator.getInstance(jceAlgorithmName); SecretKey keyEncryptKey = keyGenerator.generateKey(); return keyEncryptKey; }

To store the key-encryption key, use the following method, which writes the key-encryption key to a file. The decryption tool can then retrieve it later and use it to decrypt the encrypted data.

private static void storeKeyFile(Key keyEncryptKey) throws IOException { byte[] keyBytes = keyEncryptKey.getEncoded(); File keyEncryptKeyFile = new File("keyEncryptKey"); FileOutputStream outStream = new FileOutputStream(keyEncryptKeyFile); outStream.write(keyBytes); outStream.close(); System.out.println("Key encryption key stored in: " + keyEncryptKeyFile.toURL().toString()); }

Next, you generate the symmetric data-encryption key using the following method.

private static SecretKey GenerateSymmetricKey() throws Exception { String jceAlgorithmName = "AES"; KeyGenerator keyGenerator = KeyGenerator.getInstance(jceAlgorithmName); keyGenerator.init(128); return keyGenerator.generateKey(); }

And finally, you write the encrypted document to a file as follows:

private static void writeEncryptedDocToFile( Document doc, String fileName) throws Exception { File encryptionFile = new File(fileName); FileOutputStream outStream = new FileOutputStream(encryptionFile); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no"); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(outStream); transformer.transform(source, result); outStream.close(); System.out.println( "Encrypted XML document written to: " + encryptionFile.toURL().toString()); }

Controlling the Encryption
In the sample code, the main method performs the necessary steps to encrypt an XML file and store the encrypted form of the file to disk, along with the encrypted key needed to decrypt the file.

public static void main(String args[]) throws Exception { Document document = parseFile(args[0]); Key symmetricKey = GenerateSymmetricKey(); Key keyEncryptKey = GenerateKeyEncryptionKey();

The code follows the steps shown earlier. It retrieves and parses the XML file to be encrypted. Then, it generates the symmetric key that will be used to encrypt the data. Next, it generates the symmetric key that will be used to encrypt the data-encryption key, and stores it to a file.

The following block creates and initializes a cipher with the key-encryption key. Depending on the value of the first parameter, the init method initializes the cipher for one of the following four operations:

  • Encryption
  • Decryption
  • Key wrapping
  • Key unwrapping
For the key-encryption key, set the mode to WRAP_MODE, which will convert the key to bytes, allowing it to be transferred securely from one place to another—in this case, the file system.

XMLCipher keyCipher = XMLCipher.getInstance( XMLCipher.TRIPLEDES_KeyWrap); keyCipher.init(XMLCipher.WRAP_MODE, keyEncryptKey); EncryptedKey encryptedKey = keyCipher.encryptKey(document, symmetricKey);

Now, you specify the element to be encrypted. Remember, to encrypt the entire file, specify the root element; otherwise, retrieve and specify the specific child element you want to encrypt:

Element rootElement = document.getDocumentElement(); Element elementToEncrypt = rootElement; if (args.length > 2) { elementToEncrypt = (Element) rootElement.getElementsByTagName( args[2]).item(0); if (elementToEncrypt == null) { System.err.println("Unable to find element: " + args[2]); System.exit(1); } }

The following block creates and initializes a cipher with the data-encryption key. In this case, the mode is set to ENCRYPT_MODE, because it will be used to encrypt the data.

XMLCipher xmlCipher = XMLCipher.getInstance(XMLCipher.AES_128); xmlCipher.init(XMLCipher.ENCRYPT_MODE, symmetricKey);

The following code adds the encrypted key's key-info to the encrypted data element being built.

EncryptedData encryptedDataElement = xmlCipher.getEncryptedData(); KeyInfo keyInfo = new KeyInfo(document); keyInfo.add(encryptedKey); encryptedDataElement.setKeyInfo(keyInfo);

At this point, you can call the doFinal method to do the actual encryption.

boolean encryptContentsOnly = true; xmlCipher.doFinal(document, elementToEncrypt, encryptContentsOnly);

And finally, write the encrypted document to a file.

writeEncryptedDocToFile(document, args[1]); } }

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date