Skip to Content
Author's profile photo senthilprakash selvaraj

Digital Signing XML’s in SAP PI with Xades Extensions

Dynamic Digital Signature

There was a requirement from one of the banks from European region to digitally sign all electronic payments sent across from SAP PI with Xades Extensions.

We learnt that, as per European Union Directive all electronic payments sent to Banks should be digitally signed in compliance with eIDAS regulation.

In this line all XML payment files sent to Bank via web service calls or as XML files (Pain 001.001.003 format) from SAP PI should be digitally signed using Xades extensions.
Xades stands for “XML Advanced Electronic Signature”.

Unfortunately, SAP PI/PO does not support Xades out of the box as of now. 

If I am correct, we do have Xades capabilities in SCI (SAP Cloud Integration Platform).

Currently SAP PI supports only OASIS Web Service Security standards.

Link: Security Settings for the Receiver SOAP Adapter


Sample Input/Output Payload screenshots:



Below screenshot shows how an XML looks before and after its been digitally signed in SAP PI.

In below examples we will be using ISO standard Payment structure (Pain 001.001.003) as input.
Input XML file Before digitally singed with Xades extension:


Output XML file After digitally singed with Xades extension

Field <ds:Signature> gets added in the end of XML with encrypted digital signature properties and values, this can be validated by the Bank which will have our corresponding public key.

Prerequisite
  1. Take help from Basis and create a JKS key pair and share the Public key with the Bank.
  2. Place the private JKS key in SAP PI server file path location and make sure no one else has access to this location except for SAP PI.By default, in SAP PI, import Archive permits max size 12 mb, kindly change this property in SAP PI to accommodate higher size archive:
  3. By default, in SAP PI, import Archive permits max size 12 mb, kindly change this property in SAP PI to accommodate higher size archive: Property Name: "icm/P4/max_request_size_KB".
  4. NWDS with appropriate version.
  5. This code uses JDK 1.7+ and APACHE MAVEN 3+ (SD-DSS libraries). You must import the correct packages for Maven libraries from google and deploy them into your package.
  6. must google and deploy missing packages into your project.
  7. Create a new Maven Project in NWDS and modify below code according to the package and class name.

Code Snippet:

package <your Package Name>;

/*If any of the below packages are highlighted with errors, then please copy the package name into google, download the package and deploy in NWDS most of the Maven libraries used below you will need to download*/

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import com.sap.aii.mapping.api.AbstractTransformation;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.mapping.api.TransformationInput;
import com.sap.aii.mapping.api.TransformationOutput;
import eu.europa.esig.dss.DSSDocument;
import eu.europa.esig.dss.DigestAlgorithm;
import eu.europa.esig.dss.InMemoryDocument;
import eu.europa.esig.dss.SignatureLevel;
import eu.europa.esig.dss.SignaturePackaging;
import eu.europa.esig.dss.SignatureValue;
import eu.europa.esig.dss.ToBeSigned;
import eu.europa.esig.dss.token.AbstractSignatureTokenConnection;
import eu.europa.esig.dss.token.DSSPrivateKeyEntry;
import eu.europa.esig.dss.token.JKSSignatureToken;
import eu.europa.esig.dss.validation.CommonCertificateVerifier;
import eu.europa.esig.dss.x509.CertificateToken;
import eu.europa.esig.dss.xades.XAdESSignatureParameters;
import eu.europa.esig.dss.xades.signature.XAdESService; 

/**
 
 * XML Advanced Electronic Signature.
 * 
 * This example is based on SD-DSS library.
 * This Program is to digitally sign any XML given as input.
 * Output of this will be XML digitally signed with Xades format protocol standard.
 * As per European union bank standards, all XML documents should be signed digitally with Xades extensions.
 * Currently is not supported natively in SAP PI.
 * This Program will be deployed in SAP PI - Java Mapping which will perform Xades digital signature within PI.
 * Digital sign private key (.jks) will be placed in secured specified location to which no one else will have access.
 *
 */
public class XadesSignature extends AbstractTransformation  {
	
	public TransformationOutput transformationOutput;
	public OutputStream out;
	String temp = null;

	
@Override
	  public void transform(TransformationInput transformationInput, TransformationOutput transformationOutput)
	  throws StreamTransformationException {
try{
	/*Getting Input Stream and writing out as Output in XML*/
	String InputXML ="";
	String line ="";
	/*Digital Signing Starts from here*/
	// this file holds the signing key
/*Below are three parameterised mapping variables used to get 3 inputs 
1. JKS private Key file location 
//example input path: /sapmnt/PID/DigitalSignatureTest/
2. JKS private key File Name and 
3. JKS private key password at runtime from ICO.*/
	String PrivateKeyPath = transformationInput.getInputParameters().getString("PrivateKey_Path");
	String PrivateKeyName = transformationInput.getInputParameters().getString("PrivateKey_Name");
	String keystorePassword = transformationInput.getInputParameters().getString("PrivateKey_Password");
	String keystoreFile = PrivateKeyPath + PrivateKeyName;
	DSSDocument signDocument;
	InputStream ins = transformationInput.getInputPayload().getInputStream();
	BufferedReader br = new BufferedReader(new InputStreamReader(ins));
	
	while ((line=br.readLine())!=null) 
		InputXML+=line;
	br.close();	
	
	signDocument=this.signDocument(InputXML, keystoreFile, keystorePassword);
	transformationOutput.getOutputPayload().getOutputStream().write(((InMemoryDocument) signDocument).getBytes());
}
catch (Exception exception) {  
    throw new StreamTransformationException(exception.toString());  
}  
	}
		
	public DSSDocument signDocument(String pathToDocument, String keystore, String password) throws Exception {

		DSSDocument toSignDocument = new InMemoryDocument(pathToDocument.getBytes());
		// Create a token connection based on a JKS file (PKCS11, PKCS12 and MSCAPI are also 
		// available - see subclasses of class AbstractSignatureTokenConnection)		
		AbstractSignatureTokenConnection token; 
		try (FileInputStream is = new FileInputStream(keystore)) {
			token = new JKSSignatureToken(is, password);
		}
		catch (Exception exception) {  
            throw new StreamTransformationException(exception.toString());  
        }  
		// Obtaining the first private key entry from the keystore. This is demo code, 
		// you should implement more advanced mechanism to select the private key
		DSSPrivateKeyEntry privateKey = token.getKeys().get(0);

		// Get the certificate corresponding to the key
		CertificateToken signingCertificate = privateKey.getCertificate(); 
		
		// Preparing parameters for the XAdES signature
		XAdESSignatureParameters parameters = new XAdESSignatureParameters();
		
		// ! The required level of the signature is XAdES Baseline Profile, B-level
		parameters.setSignatureLevel(SignatureLevel.XAdES_BASELINE_B);
		
		// ! The required type of the signature is ENVELOPED
		parameters.setSignaturePackaging(SignaturePackaging.ENVELOPED);
		
		// We set the digest algorithm to use with the signature algorithm. You must use the same 
		// parameter when you invoke the method sign on the token. 
		// ! Recommended value is SHA256
		parameters.setDigestAlgorithm(DigestAlgorithm.SHA256);
			// Add signing certificate
		parameters.setSigningCertificate(signingCertificate);
			// Create common certificate verifier
		CommonCertificateVerifier commonCertificateVerifier = new CommonCertificateVerifier();
				// Create XAdES service for signature
		XAdESService service = new XAdESService(commonCertificateVerifier);
		// Get the SignedInfo XML segment that need to be signed.
		ToBeSigned dataToSign = service.getDataToSign(toSignDocument, parameters);
		// This function obtains the signature value for signed information using the
		// private key and specified algorithm
		SignatureValue signatureValue = token.sign(dataToSign, parameters.getDigestAlgorithm(), privateKey);
		// We invoke the service to sign the document with the signature value obtained
		// in the previous step.
		DSSDocument signedDocument = service.signDocument(toSignDocument, parameters, signatureValue);
		// THE DOCUMENT IS SIGNED AT THIS POINT		
		return signedDocument;
	}
}

 

Once this is done, export the package as JAR and deploy the same via Imported Archive into SAP PI.

Call this imported archive into a Operation mapping and activate.

Once activated, in Test mode under Parameters tab, please fill the 3 input parameters which actually need to be given via ICO (parameter mapping).





If everything done proper, you should get output file digitally signed in the Receiver.


Hence with above code and libraries, we can digitally sign any XML with Xades extensions with in SAP PI.

Note: if we further investigate SD-DSS based Maven library, we can see that any type of digital signature process can be executed and embeded within SAP PI.

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Daniel Graversen
      Daniel Graversen

      Hi

      Yes encryption is pretty difficult to setup for such a case.

      If you have that large dependencies for project it is proably a better idea to add it as a module where you have the imported archive.

       

      Have you tried adding the certificates to the NWA keystore, it is a better place to save/access certificates. I have also been doing hte JKS file it is not easy to maintain.

       

      Author's profile photo senthilprakash selvaraj
      senthilprakash selvaraj
      Blog Post Author

      Yes, i can deploy the JKS into Keystore and call it instead. i will mod the code later. but for now i was more concentrating on providing an solution for the customer :).

      Author's profile photo Kimmo Sirpoma
      Kimmo Sirpoma

      Did you solved the problem or have more enhanced your solution? We are having similar requirement. <ds:Signature> element needs to be added in mapping after the main business content. We receive the XML-file from a source system without the signature element but the schema is the same. In our case the requirement is XML-file as well, not SOAP message. We already have the key in the NWA keystore because the connection uses SFTP with RSA Keypair authentication and that works.

      Is Java the only way to do this in SAP PI/PO? I'd wish there would be something like functionality 'Add signature' in the PI mapping tool which would then ask for the key entry in the keystore.

       

      Author's profile photo Fernando Maria Vega Villasante
      Fernando Maria Vega Villasante

      Hello,

      Your solution seems very interesting to me, but I am having problems with the library classes.

      Could you tell me which are the correct libraries to compile and run the JM.

      Thank you