In this blog, I will retrace the steps that I have used to encrypt and decrypt payload coming inside message tags using PGP encryption/decryption. After many searches and tries, I was able to find a blog by Sandeep using Bouncy Castle,
https://community.sap.com/t5/additional-blogs-by-members/pgp-encryption-decryption-using-java-code/b...
This is an update to the same blog where I have worked around the mentioned trick without using Bouncy Castle to add the encrypted payload within the messages.
For OpenPGP encryption and decryption, the requirement that I had was to convert the generated message through BCM(Bank Communication Management) by first encrypting with PGP encryption and then converting to base64 while having this within the payload.
/usr/sap/XXX/X00/<your_custom_folder>/privatekey.skr
package z001;
import java.io.InputStream;
import java.io.OutputStream;
import com.sap.aii.mapping.api.*;
import java.io.*;
import java.util.Base64;
import com.didisoft.pgp.PGPLib;
public class encrypt extends AbstractTransformation {
@Override
public void transform(TransformationInput transformationInput, TransformationOutput transformationOutput) throws StreamTransformationException {
try{
PGPLib pgp = new PGPLib();
String privateKeyFile = "/usr/sap/XXX/X00/<your_custom_folder>/privatekey.skr";
String privateKeyPassword = "<your_key_password>";
String publicEncryptionKeyFile = "/usr/sap/XXX/X00/<your_custom_folder>/bankkey.pkr";
InputStream inputStream = transformationInput.getInputPayload().getInputStream();
BufferedReader inpxml = new BufferedReader(new InputStreamReader(inputStream));
getTrace().addInfo("input received");
StringBuffer buffer = new StringBuffer();
String line="";
while ((line = inpxml.readLine()) != null)
{
buffer.append(line);
}
String org_msg=buffer.toString();
OutputStream outputstream = transformationOutput.getOutputPayload().getOutputStream();
getTrace().addInfo("encrypt");
String signedAndEncryptedString =
pgp.signAndEncryptString(org_msg,
privateKeyFile,
privateKeyPassword,
publicEncryptionKeyFile);
getTrace().addInfo("encode");
byte[] bytes = signedAndEncryptedString.getBytes();
String encodedString = Base64.getEncoder().encodeToString(bytes);
// int msg_length = org_msg.length();
getTrace().addInfo("finalstructure");
String target_msg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+"<ns0:MT_bank_Pay_Request xmlns:ns0=\"http://x.com/bank_Payment\">"+"<paymentBase64>"+encodedString+"</paymentBase64>"+"</ns0:MT_bank_Pay_Request>";
outputstream.write(target_msg.getBytes());
//this is to get the final target message that we have converted
getTrace().addInfo("finalstructure"+target_msg);
}
catch (Exception ie) {
}
}
}
This will convert the final message below
<?xml version="1.0" encoding="UTF-8">
<ns0:MT_bank_Pay_Request xmlns:ns0="http://x.com/bank_Payment">
<paymentBase64>"your encoded and encrypted string"</paymentBase64>
</ns0:MT_bank_Pay_Request>
This is the response from the bank side that I was receiving, here in responsebase64 I had the original file content response, which needed to be decoded and decrypted.
<?xml version="1.0" encoding="UTF-8"?>
<ns0:MT_Vendor_Pay_Response xmlns:ns0="http://x.com/bank_Payment">
<referenceId>1</referenceId>
<profileId>2</profileId>
<statusCode>3</statusCode>
<statusDesc>5</statusDesc>
<responseBase64>6</responseBase64>
</ns0:MT_Vendor_Pay_Response>
For decryption, in the below Java code, you can see the original content (which is encrypted and encoded) is within the responsebase64 tag, if blank I am generating a different XML response, but if non-blank I will be consuming the payload within SAP PO. Integration response will be generally provided by the bank side, you can add the dummy payload as same as the response you are having from the bank.
package z001;
import com.sap.aii.mapping.api.*;
import java.io.*;
import java.util.Base64;
import com.didisoft.pgp.PGPLib;
public class decrypt extends AbstractTransformation {
@Override
public void transform(TransformationInput transformationInput, TransformationOutput transformationOutput)
throws StreamTransformationException {
try {
PGPLib pgp = new PGPLib();
String privateKeyFile = "/usr/sap/XXX/X00/<your_custom_folder>/privatekey.skr";
String privateKeyPassword = "<your_key_password>";
InputStream inputStream = transformationInput.getInputPayload().getInputStream();
OutputStream outputstream = transformationOutput.getOutputPayload().getOutputStream();
BufferedReader inpxml = new BufferedReader(new InputStreamReader(inputStream));
getTrace().addInfo("input received");
String originalFileName = "";
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = inpxml.readLine()) != null) {
buffer.append(line);
}
String org_msg = buffer.toString();
String s3 = org_msg;
String isFound = "";
String headerstatus = "";
String headerdesc = "";
String responsebase64 ;
headerstatus = s3;
headerdesc = s3;
responsebase64 = s3;
//I have used index here as my response was having status code and message
//which i have capture in local variable.
headerstatus = headerstatus.substring(headerstatus.indexOf("<statusCode>") + 12);
headerstatus = headerstatus.substring(0, headerstatus.indexOf("</statusCode>"));
getTrace().addInfo(headerstatus);
headerdesc = headerdesc.substring(headerdesc.indexOf("<statusDesc>") + 12);
headerdesc = headerdesc.substring(0, headerdesc.indexOf("</statusDesc>"));
getTrace().addInfo(headerdesc);
//orginal response was coming after <responseBase64> tag which is capture here
responsebase64 = responsebase64.substring(responsebase64.indexOf("<responseBase64>") + 16);
getTrace().addInfo(responsebase64);
//I am checking here if response is there or not, if not i am making a custom xml
if ( responsebase64.indexOf("</responseBase64>") == 0)
{
isFound = "N";
}
else
{
responsebase64 = responsebase64.substring(0, responsebase64.indexOf("</responseBase64>"));
isFound = "Y";
}
getTrace().addInfo("truecheck" + isFound + responsebase64);
if ( isFound == "Y" )
{
getTrace().addInfo("ifcheck");
org_msg = org_msg.substring(org_msg.indexOf("<responseBase64>") + 16);
org_msg = org_msg.substring(0, org_msg.indexOf("</responseBase64>"));
getTrace().addInfo("beforedecoding" + org_msg);
byte[] decodedBytes = Base64.getDecoder().decode(org_msg);
getTrace().addInfo("decoded");
String decodedString = null;
// Get the string of decoded byte array
String s = new String(decodedBytes);
// String encrypted = "";
decodedString = s;
getTrace().addInfo("beforedecryption");
//this is the decryption code, you can use it based on ur use case
originalFileName = pgp.decryptString(decodedString, privateKeyFile, privateKeyPassword);
//end of decryption code
getTrace().addInfo("decrypted" + originalFileName);
}
else
{
getTrace().addInfo("elsecheck");
String so = originalFileName;
if (so == "") {
///if the code is blank
originalFileName = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<ns0:Document xmlns:ns0=\"urn:http://x.com\">\r\n" + "<paymentresponseBase64>"+"FAILED"+"</paymentresponseBase64>"
+ "</ns0:Document>";
}
}
String target_msg = originalFileName;
getTrace().addInfo("finalstructure" + target_msg);
outputstream.write(target_msg.getBytes());
}
catch (Exception ie) {
}
}
}
Note:
I have used the above code based on my use case, you can play around with the Didisoft libraries and choose what fits best. For the adapter level, many modules and blogs are available that can be used to do the encryption and decryption.
Keep track of the expiry of keys, would be helpful for you as a change in year-end activity.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
6 | |
4 | |
4 | |
4 | |
4 | |
3 | |
3 | |
3 | |
3 | |
3 |