Version 5

    Disclaimer:  This article does not talk about the implementation of any cryptographic modules. It talks about the usage of a simple library util that uses the Apache XML Security library (http://santuario.apache.org/Java/index.html) to provide XML Encryption support (http://www.w3.org/TR/xmlenc-core) for any XML Document.

     

    Introduction:  When you transmit XML Documents from one end (sender) to the other end (recipient), you would like to encrypt some elements in the document such that any sniffers along the way do not see sensitive information. Things include credit card numbers, bank account information etc.   As part of the JBoss Identity project, there is an utility class called as XMLEncryptionUtil that can be used to encrypt/decrypt documents.

     

    The sender needs to have the Public Key of the recipient.  The sender creates a SecretKey to encrypt.  Then this SecretKey is encrypted using the Public Key of the recipient and the encrypted key is sent as part of the encryption payload in the document.  At the recieving end, the receiver uses his Private Key to decrypt the SecretKey and then decrypts the document.  As you can see, the SecretKey is safe during transport.

     

    Details:

     

    Let us the usage of this util class.

     

    // Some imports
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PublicKey;
    
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.xml.namespace.QName;
    
    import org.jboss.identity.federation.core.saml.v2.util.DocumentUtil;
    
    import org.jboss.identity.federation.api.util.XMLEncryptionUtil;
    
    
    //Define some arbitrary xml
    String myXML = "<somexml><a><b></b></a></somexml>";
          
    KeyPair kp = this.getKeyPair("RSA");
    SecretKey sk = this.getSecretKey();
          
    PublicKey publicKey = kp.getPublic();
          
    Document doc = DocumentUtil.getDocument(myXML);
    QName qname = new QName("urn:test", "encryptedA", "someprefix");
          
    QName elementAQname = new QName("a");
          
    XMLEncryptionUtil.encryptElement(elementAQname, doc,
                publicKey, sk, 256, qname, true);
          
    //Let us verify the document:
    //The original document that has been passed has been updated
    NodeList nl = doc.getElementsByTagNameNS(XMLEncryptionUtil.XMLENC_NS,
                  XMLEncryptionUtil.ENCRYPTED_KEY_LOCALNAME);
    assertTrue(nl != null && nl.getLength() == 1); 
          
    Node wrappedNode = doc.getDocumentElement().getFirstChild();
    assertEquals(wrappedNode.getLocalName(),qname.getLocalPart());
    assertEquals(wrappedNode.getNamespaceURI(), qname.getNamespaceURI());
    assertEquals(wrappedNode.getPrefix(), qname.getPrefix());
    
    //Let us decrypt the document
    PrivateKey privateKey = kp.getPrivate();
    Element decryptedElement = XMLEncryptionUtil.decryptElementInDocument(
                              doc, privateKey);
    assertEquals("a", decryptedElement.getLocalName());
    

     

    In this example, we encrypt the xml element "a"  and wrap the encrypted element using "someprefix:encryptedA" in the updated document.  The important thing to note is that the document during encryption gets updated with the encrypted element as a replacement to the original element.

     

    During decryption, we pass the document and the private key.  Then the document gets updated with the original element as a replacement to the encrypted element.

     

    XML Encrypted Document in transit:

     

    <?xml version="1.0" encoding="UTF-8"?>
    <somexml>
      <someprefix:encryptedA xmlns:someprefix="urn:test">
       <xenc:EncryptedData
          xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
          Type="http://www.w3.org/2001/04/xmlenc#Element">
          <xenc:EncryptionMethod
     Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"
     xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
     <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
      <xenc:EncryptionMethod
    Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
    <xenc:CipherData
      xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
    <xenc:CipherValue
      xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
    c6s3T8jEqJ7d6+J6vZ/OuFy7W6/nm9TT/oL0FLgQ3812IQY7vjDyLn8YUtWcXFhkAzoCCzTWiG+P
    DsPjqhCs9PVHyxQ5Nx8hNZY0KpFDoULyf9oaY+wdSFXClpjgQWFktFALk02EXC3EyLmci0hd7GGK
    N32/ONrcuHDMucogrww=
    </xenc:CipherValue>
    </xenc:CipherData>
    </xenc:EncryptedKey>
    </ds:KeyInfo>
    <xenc:CipherData
      xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
      <xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
    HUmkblyEnC5+Lo2uqGeatG5WVpAdSEIZPRAqVAFQT6c=</xenc:CipherValue>
    </xenc:CipherData>
    </xenc:EncryptedData>
    </someprefix:encryptedA>
    </somexml>
    

     

    Caution:

    • Please do not do any "pretty print" of the encrypted document because decryption will fail as the document could be messed up with white spaces. 
    • Additionally, the SecretKey can be decrypted only with the PrivateKey of the holder whose PublicKey was used in encrypting the key.
    • If you are running the application in a JBoss Application Server or any other container environment, you may probably get the dependencies (Apache XML Security etc) from the container.

     

    Installation:

    1. Download the JBoss Identity distribution from : http://www.jboss.org/jbossidentity/downloads/
    2. Download the Apache XML Security 1.4.2 library (or better) from the Apache website or the JBoss maven repository here: http://repository.jboss.org/maven2/org/apache/xmlsec/1.4.2/xmlsec-1.4.2.jar
    3. Ensure that the Endorsed Jars exist (Xerces, XML APIs, Xalan etc)

     

    Future Roadmap:

    Even though I have shown one typical usage of xml encryption, there are opportunities to improve the XMLEncryptionUtil class further.

     

    Reference:

    1. XMLEncryptionUtil source: http://anonsvn.jboss.org/repos/jbossidentity/identity-federation/trunk/identity-fed-api/src/main/java/org/jboss/identity/federation/api/util/XMLEncryptionUtil.java
    2. XMLEncryptionUtilTestCase: http://anonsvn.jboss.org/repos/jbossidentity/identity-federation/trunk/identity-fed-api/src/test/java/org/jboss/test/identity/federation/api/util/XMLEncryptionUnitTestCase.java

     

    Related Information:

    JBoss Web Services with WS-Security support does have support for XML Encryption.