Skip to Content
Technical Articles
Author's profile photo Sunny Kapoor

How to encrypt/decrypt XML payload with AES256-CBC and RSA Algorithm in SAP Cloud Integration

In one of my proof of concept work, the requirement was to decrypt a XML payload using SAP Cloud Integration. This XML payload is encrypted as per the W3C Recommendation i.e. XML-Signature Syntax and Processing, W3C Recommendation 12 February 2002 and XML Encryption Syntax and Processing, W3C Recommendation 10 December 2002

XML is encrypted using the SECXML_XENCRYPTION  standarad executable ABAP Report with the following specification:

  • AES256-CBC algorithm to encrypt data
  • RSA v1.5 algorithm to encrypt the AES key

 

Encrypted XML:

<Person xmlns:nm="http://www.sap.com/saphr/person/1_0" xmlns:prx="urn:sap.com:proxy:HP1:/1SAI/TASC1D8B7EB3CD3DF9DE517:731">
        <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <xenc:EncryptedKey Type="http://www.w3.org/2001/04/xmlenc#EncryptedKey">
                    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
                    <xenc:CipherData>
                        <xenc:CipherValue>Ib7QIaQ1fA5EA2GAaoai8LEK47b7An3eoDESS7VWnjL+CBJqe9t97HeSuJZCYsVRSmBvRNy4yc1C6G80KOt30+mi2+N7TS9xcdVXfHJGAfmVkshKgJkca7w4kH2jBFspMtn4XopNZZHdFedRXoFZgQ5smaOHfutWdBOJBBWsnQ5bNPwG9NHDhs44pDEGOfTFJFFW8/RodqvyaLChHUR3FxxQmuoEtlX5CRd1+3FSJbWfLtk21EysuBcBBZSwFMtEp4YvMgXRKaE13HgUzxKMpho6LPxI69+wBmUPZCZcc/K9J0LfcJA+Q3DN+lSZEDwPfMNT77Qli9XskOjkt1HIsA==</xenc:CipherValue>
                    </xenc:CipherData>
                </xenc:EncryptedKey>
            </ds:KeyInfo>
            <xenc:CipherData>
                <xenc:CipherValue>uAd59MSd+3+lutSPgP1rWIpE02erC8uIV7V3+Db0ePy5qQdmmbg9q5HpgTH2rZDEChdwg4gLhIQtYP8qyN3DdxMrMBgysRdNl3ka+h22nfPAgQXrGGoJgDph4nnD27UEG3DWbeQrQxaN29S75DnvPfP+NLvN+trSrrkY7Ew7YY+QMAfbWrazGTT06bQIZLN6hDJv2HaGWa05aAcAR9b0yD0wuTDI+t2tfhyD+jB9w76h9ar/17tZRuUNETeg12hutoNkKjDsnNuttUJrEGYgMDusyVdGt/3lYCAKhZzxpyk5OnTQ2zXDfmlzl5Z2w6vkiBMtnst3DhYm5NdFxxSQ9B/ctdLU32GnHo8wgnvAY6mYr378HZVhtAUz5vP+lLFjDrHqGoTn3F+IYV3DA1qyCNI8c5iY56ZwaSH9Lh3JUBLRO2SRYWSLTgv3FrZV/jyXiUUhAhjYbIudi0gyGAQ8lNrFZE2NME34U7N1Q2eZbaXHPzcC8zamJD992wkA1yFueR/29rEP8PldnOJ1PcG2PoeIvMCXADG5gskMjyIzzmoousZOugCM1l/6GlLvTAi9bGYI+uH+iCTh6RME4wp/zV3LfgfzoUOTdkNY5sObiMruEsfKNri3PEW+8egzNIVWkrje/2thunXjtmssW6PkA290A51RWYZben/TIyltPu/akLQ2W6GlrRHLp+hZlrae</xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
</Person>

 

Solution:

As there is no encryption/decryption flow step in Cloud Integration for XML messages, there are two possible solution to decrypt the above XML using SAP Cloud Integration:

  1. Use a Groovy Script flow step with standard JAVA JCE/JCA Classes.
  2. Use a Groovy Script flow step with third party jar i.e. Apache Santuario . The Apache XML Security for Java library supports XML-Signature Syntax and Processing, W3C Recommendation 12 February 2002 and XML Encryption Syntax and Processing, W3C Recommendation 10 December 2002.

The advantage of using Apache Santuario jar is, it is written as per the W3C recommendation, so you only need to pass the Encrypted XML, it automatically finds the encrypted key + algorithm and encrypted data + algorithm to give you the final decrypted XML.

Where as in 1st solution, we need to find the encrypted key first, decrypt it and then use the decrypted key to decrypt the data and finally append it to the original XML structure. But this approach do not require any external jars.

In this blog, first solution is used.

Integration Flow:

As you can see in the above screenshot, we receive the encrypted XML payload via SOAP adapter then log the payload and finally send the payload to XML Decryption groovy script flow step to get the decrypted XML.

The algorithm to decrypt the XML with standard JAVA JCE/JCA Classes is as follows:

  1. To decrypt the AES key which is encrypted via RSA algorithm, first we need to get the private key pair from the Cloud Integration keystore.
  2. Then extract the encrypted AES key and AES Data(Encrypted XML) from the given XML.
  3. Decrypt the AES Key string using the private key which we got in step 1.
  4. Decrypt the AES Data string(Encrypted XML) using the AES key which we got in step 3.
  5. Append the Decrypted XML to the original XML Structure.

XML Decryption Groovy Script:

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import com.sap.it.api.ITApiFactory;
import com.sap.it.api.keystore.KeystoreService;
import java.security.cert.Certificate;
import java.security.KeyPair;
import java.security.PrivateKey;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import org.apache.commons.codec.binary.Base64;
import groovy.xml.Namespace;
import groovy.util.XmlParser;
import groovy.xml.XmlUtil;

def Message processData(Message message) {
    KeystoreService service = ITApiFactory.getApi(KeystoreService.class, null);
    Certificate cert = service.getCertificate("rover");
    KeyPair keypair = service.getKeyPair("rover");
    PrivateKey privateKey = keypair.getPrivate();
    
    //Body 
    def body = message.getBody(java.lang.String) as String;
    def person = new XmlParser(false,false).parseText(body);
    
    def xencns = new groovy.xml.Namespace("http://www.w3.org/2001/04/xmlenc#",'xenc')
    def dsns = new groovy.xml.Namespace("http://www.w3.org/2000/09/xmldsig#",'ds');
   
    String encryptedAESKey = person[xencns.EncryptedData][dsns.KeyInfo][xencns.EncryptedKey][xencns.CipherData][xencns.CipherValue].text();
    String encryptedXMLData = person[xencns.EncryptedData][xencns.CipherData][xencns.CipherValue].text();
    
    SecretKey aes_key = decryptAESKey(encryptedAESKey, privateKey);
    String decryptedXMLData = decryptAESData(encryptedXMLData, aes_key);
    
    decryptedXMLData = "<root>" + decryptedXMLData + "</root>";
    
    def childNode = new XmlParser(true,true).parseText(decryptedXMLData);
    
    person[xencns.EncryptedData].replaceNode{};
 
    childNode.each{child ->
        person.append(child);
    }
    
    def messageLog = messageLogFactory.getMessageLog(message);
    messageLog.addAttachmentAsString("Certificate", cert.toString(), "text/plain");
    messageLog.addAttachmentAsString("Encrypted AES Key", encryptedAESKey, "text/plain");
    messageLog.addAttachmentAsString("Encrypted XML Data", encryptedXMLData, "text/plain");
    messageLog.addAttachmentAsString("Decrypted AES Key", aes_key.getEncoded().toString(), "text/plain");
    messageLog.addAttachmentAsString("Decrypted XML Data", decryptedXMLData, "text/plain");
    
    message.setBody(XmlUtil.serialize(person));
    return message;
}

SecretKey decryptAESKey(String encryptedAESKey, PrivateKey privateKey){
    byte[] decryptedAESKey = null;
    SecretKey aes_key = null;
    try {
        // get an RSA cipher object and print the provider
        final Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        // decrypt the text using the private key
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
     
        decryptedAESKey = cipher.doFinal(Base64.decodeBase64(encryptedAESKey));
        aes_key = new SecretKeySpec(decryptedAESKey, "AES");
    } catch (Exception e) {
        throw new Exception(e.getMessage());
    }
    
    return aes_key;
}

String decryptAESData(String encrypted, SecretKey key)  {
    int ivLen = 16;
	byte[] ivBytes = new byte[ivLen];
	byte[] encryptedBytes = Base64.decodeBase64(encrypted);
	System.arraycopy(encryptedBytes, 0, ivBytes, 0, ivLen);		
	IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
	
	Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
	
    cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
    
    String decrypted = new String(cipher.doFinal(encryptedBytes, ivLen, encryptedBytes.length - ivLen));
    
    return decrypted;
}

 

SOAP Request:

SOAP Response:

Assigned Tags

      3 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ricardo Viana
      Ricardo Viana

      Hi Sunny Kapoor,

      First of all Xmas for you and thanks for such nice blog.

      I would like to ask something, I will need also to produce POC for encryption and sign XML using CPI standard functions:

      "As there is no encryption/decryption flow step in CPI for XML messages, there are two possible solution to decrypt the above XML using SAP CPI:"

      Why you could not used it instead of go for custom solution using groovy.

      I was not able to check those functionalities but I tired in the past produce POC using the SOAP adapter with encrypt and sign and not works proper with SAP PO.

      Thanks and happy new year.

      Viana.

      Author's profile photo Sunny Kapoor
      Sunny Kapoor
      Blog Post Author

      Hi Ricardo Viana

      Kindly excuse me for replying you late on this.

      As I have mentioned in the blog, there is a specification for XML Encryption/Decryption from W3C

      XML Encryption Syntax and Processing, W3C Recommendation 10 December 2002

      As of today there is no flowstep in CPI which understand the encrypted XML and can encrypt/decrypt the XML payload as per the specification.

      In an existing example the XML data is encrypted via AES256-CBC symmetric algorithm, where key is encrypted via RSA - asymmetric algirthm and is part of the XML payload itself.

      You can encrypt the entire XML or part of it.

      PGP and PKCS7 decryptor do not understand the encrypted XML specification and syntax and therefore cannot be used.

      Where as Signer is used for creating a digital signature and has a different concept and usage than encryption.

      Kindly go through the specification to understand this in detail.

      I hope this will help.

       

      Regards,
      Sunny

      Author's profile photo Noveen Bacchu
      Noveen Bacchu

      Hi Sunny,

       

      Can you please let us know the Ciphers suites supported by SAP CPI Neo?

      Regards