Encrypting all or parts of an XML message

Camel's XML Security Component is used when you need to encrypt and decrypt all or parts of an XML message. A Data Format provided by this component handles transformation between an encrypted and decrypted message.

The XML Security Component supports both symmetric and asymmetric encryption of XML messages as outlined by the W3C Recommendation XML Encryption Syntax and Processing. In symmetric encryption, a password shared by the sender and receiver is used to encrypt and decrypt a message. Using asymmetric encryption, the public key of the message recipient is used to encrypt the message, thereby only permitting the intended recipient to decrypt it.

This Camel component allows you to provide an XPath that points to a node, or set of nodes, in the document that will be encrypted; if none is provided the entire document will be encrypted.

This recipe will show you how to configure full asymmetric encryption of XML message payloads. It will show you how to encrypt and decrypt a fragment of an XML message by providing an XPath to the node to be encrypted.

Getting ready

The Java code for this recipe is located in the org.camelcookbook.transformation.xmlsecurity package. The Spring XML files are located under src/main/resources/META-INF/spring and prefixed with xmlsecurity.

To use Camel's XML Security Component, you need to add a dependency on the Camel XML Security Component that provides an implementation for the XML Security Data Format using the Apache XML Security (Santuario) library.

Add the following to the dependencies section of your Maven POM:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-xmlsecurity</artifactId>
  <version>${camel-version}</version>
</dependency>

Before using the cryptographic capabilities available in Camel to encrypt and decrypt fragments of an XML message you will need:

  • A pair of encryption keys (public and private) held in a keystore for use by the decrypting party
  • A copy of the encrypting party's public encryption key, held in a truststore that is accessible by the encrypting party

For the purposes of this example we will use the keytool utility that is included as part of the Java Development Kit (JDK) to generate these keys and place them into the appropriate stores:

  1. Generate the keystore that contains both public and private key certificates for the receiving system:
    # keytool -genkeypair -v -keyalg RSA -alias system_a -keystore xml_keystore.jks -dname 'CN=Scott,O=camelcookbook.org'-storepass keystorePassword -validity 3650 -keypass keyPasswordA

    Note

    The -keyalg argument specifies the use of the RSA algorithm. This option needs to be set for asymmetric encryption.

  2. Export the public key certificate:
    # keytool -export -alias system_a -keystore xml_keystore.jks -rfc -file selfsignedcert_xml_a.cer -storepass keystorePassword
  3. Import the public key into the truststore of the sending system:
    # keytool -import -noprompt -alias system_a -file selfsignedcert_xml_a.cer -keystore xml_truststore.jks -storepass truststorePassword

How to do it...

To encrypt, and subsequently decrypt an XML fragment in a document on the exchange, perform the following steps:

  1. To perform XML encryption, first define a reference to the truststore that contains the public key of the message recipient.

    If using Spring, define a keyStoreParameters tag outside of the camelContext element:

    <beans ...
        xmlns:camel="http://camel.apache.org/schema/spring"
        xsi:schemaLocation="...
          http://camel.apache.org/schema/spring 
            http://camel.apache.org/schema/spring/camel-spring.xsd">
    
      <camel:keyStoreParameters 
          id="trustStoreParams"
          resource="xml_truststore.jks" 
          password="truststorePassword"/>
    
      <camelContext ...>
    </beans>

    The resource setting is a Camel resource path, so in this example it will look on the classpath for xml_truststore.jks. To find a truststore on the filesystem or on an HTTP server, you prefix the location with file: or http: respectively.

    Note

    The key password is shown in plain text so as to not complicate the example. In a real-world scenario, the password should be injected as an encrypted property. See the Encrypting configuration properties recipe for a description of how to do this.

    If using Java, add the following code inside the configure() method of your RouteBuilder implementation:

    KeyStoreParameters trustStoreParameters =
         new KeyStoreParameters();
    trustStoreParameters.setResource("xml_truststore.jks");
    trustStoreParameters.setPassword("truststorePassword");
  2. Within your route, use the secureXML data format to marshal the unencrypted XML body of the exchange. This will perform the encryption step.

    Using the XML DSL, this is done as follows:

    <from uri="direct:encrypt"/>
    <marshal>
      <secureXML 
          secureTag="/booksignings/store/address"
          secureTagContents="true"
          recipientKeyAlias="system_a"
          xmlCipherAlgorithm=
            "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
          keyCipherAlgorithm=
            "http://www.w3.org/2001/04/xmlenc#rsa-1_5"
          keyOrTrustStoreParametersId="trustStoreParams"/>
    </marshal>
    <to uri="direct:decrypt"/>

    The secureTag attribute contains the XPath of the message fragment to encrypt (use an empty String for the entire document).

    The xmlCipherAlgorithm is a reference to the algorithm used to encrypt the XML.

    The keyCipherAlgorithm is the algorithm that was used when the keys were generated in the Getting ready section of this recipe (RSA).

    The same route is expressed in the Java DSL as follows:

    from("direct:encrypt")
      .marshal()
        .secureXML(
            "/booksignings/store/address", // secure tag
            true,                 // secure tag contents
            "system_a",           // recipient key alias
            XMLCipher.TRIPLEDES,  // xml cipher
            XMLCipher.RSA_v1dot5, // key cipher
            trustStoreParameters)
      .to("mock:marshalResult");

    Note

    Unlike in the XML DSL where we reference the id of the keyStoreParameters tag through the keyOrTrustStoreParametersId attribute, in the Java variant we pass in the KeyStoreParameters object directly.

  3. To decrypt an encrypted XML document, define a reference to the keystore that contains the public and private keys of the message recipient.

    If using Spring, again define a keyStoreParameters tag outside of the camelContext element:

    <beans ...
        xmlns:camel="http://camel.apache.org/schema/spring"
        xsi:schemaLocation="...
          http://camel.apache.org/schema/spring 
            http://camel.apache.org/schema/spring/camel-spring.xsd">
    
      <camel:keyStoreParameters 
          id="keyStoreParams" 
          resource="xml_keystore.jks" 
          password="keystorePassword"/>
    
      <camelContext ...>
    </beans>

    If using Java, add the following code inside the configure() method of your RouteBuilder implementation:

    KeyStoreParameters keyStoreParameters =
         new KeyStoreParameters();
    keyStoreParameters.setResource("xml_keystore.jks");
    keyStoreParameters.setPassword("keystorePassword");
  4. Within your route, use the secureXML data format to unmarshal the encrypted XML body of the exchange. This will perform the decryption step.

    Using the XML DSL this is done as follows:

    <from uri="direct:decrypt"/>
    <unmarshal>
      <secureXML 
          secureTag="/booksignings/store/address"
          secureTagContents="true"
          recipientKeyAlias="system_a"
          xmlCipherAlgorithm=
              "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
          keyCipherAlgorithm=
              "http://www.w3.org/2001/04/xmlenc#rsa-1_5"
          keyOrTrustStoreParametersId="keyStoreParams"
          keyPassword="keyPasswordA"/>
    </unmarshal>
    <to uri="mock:out"/>

    The same route is expressed in the Java DSL as follows:

    from("direct:decrypt")
      .unmarshal()
        .secureXML(
            "/booksignings/store/address", // secure tag
            true,                          // secure tag contents
            "system_a",                    // recipient key alias
            XMLCipher.TRIPLEDES,           // xml cipher
            XMLCipher.RSA_v1dot5,          // key cipher
            keyStoreParameters,
            "keyPasswordA")                // key password
      .to("mock:out");

How it works...

The XML Security Component uses the Apache Santuario library to perform the XML encryption operations.

Given the following payload:

<booksignings>
  <store>
    <address>
      <street>123 Main St</street>
      <city>Boston</city>
    </address>
    <authors>
      <author>Scott Cranton</author>
    </authors>
  </store>
  <!-- … -->
</booksignings>

The encrypted version will appear as:

<booksignings>
  <store>
    <address>
      <xenc:EncryptedData 
          xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
          Type="http://www.w3.org/2001/04/xmlenc#Content">
        <xenc:EncryptionMethod 
            Algorithm=
              "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
        <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
          <xenc:EncryptedKey>
            <xenc:EncryptionMethod 
                Algorithm="http://www.w3.org/2001/04/xmlenc#kw-tripledes"/>
            <xenc:CipherData>
              <xenc:CipherValue>
i19aQxl9a5QV7cVym/5gV9Ih67Jklt6oc3Aph2ec6/zpui+0MC8YJw==
              </xenc:CipherValue>
            </xenc:CipherData>
          </xenc:EncryptedKey>
        </ds:KeyInfo>
        <xenc:CipherData>
          <xenc:CipherValue>
RvUlpr8CN51DcUx+Y3C7msQoprtoqc5vx9CplhmBqstZGHj5ThVuvJArFMaVXloXZs6cd7w4N1bF/9E1Xa85CAB7uYwKwSFjzRgigndEXV4=
          </xenc:CipherValue>
        </xenc:CipherData>
      </xenc:EncryptedData>
    </address>
    <authors>
      <author>Scott Cranton</author>
    </authors>
  </store>
  <!-- ... -->
</booksignings>

This use of message encryption allows you to create routes that can encrypt sensitive information early within your message processing. All subsequent downstream message-processing steps will only have access to the encrypted contents. Through the use of partial message encryption, you can ensure that the most sensitive parts are hidden while still allowing content based routing and other message processing operations based on the non-sensitive parts of the message.

There's more...

The XML Security Component also easily handles documents containing XML namespaces. Consider the following payload:

<?xml version="1.0" encoding="UTF-8"?>
<booksignings 
    xmlns="http://camelcookbook.org/schema/booksignings">
  <store>
    <address>
      <street>123 Main St</street>
      <city>Boston</city>
    </address>
    <authors>
      <author>Scott Cranton</author>
    </authors>
  </store>
  <!-- ... -->
</booksignings>

To encrypt this message using the XML DSL, you define an XML namespace on the camelContext element:

<camelContext 
    xmlns="http://camel.apache.org/schema/spring"
    xmlns:c="http://camelcookbook.org/schema/booksignings">

You can then use the c: namespace in your XPath Expression:

<secureXML 
    secureTag="/c:booksignings/c:store/c:address"
    secureTagContents="true"
    recipientKeyAlias="system_a"
    xmlCipherAlgorithm=
      "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
    keyCipherAlgorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"
    keyOrTrustStoreParametersId="trustStoreParams"/>

To encrypt the message using the Java DSL, you define a Map of prefixes to namespace URIs inside your RouteBuilder implementation:

Map<String, String> namespaces = new HashMap<String, String>();
namespaces.put("c","http://camelcookbook.org/schema/booksignings");

You then provide Map as an additional argument to the secureXML DSL statement. This allows you to use the c: namespace prefix in your XPath Expression to identify the node to be encrypted.

.secureXML(
    "/c:booksignings/c:store/c:address", // prefixed XPath 
    namespaces,
    true,                                  // secure tag contents
    "system_a",                            // recipient key alias
    XMLCipher.TRIPLEDES,                   // xml cipher
    XMLCipher.RSA_v1dot5,                  // key cipher
    trustStoreParameters)
..................Content has been hidden....................

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