I’ve recently had the opportunity to build a PI interface where the receiving system provided a web service where part of the message needed to be encrytped using PGP.
First thoughts are – sure – no worries. We have the PGP module from SAP to do this. But no… The PGP module will only operate on an entire message and is really designed just for file processing. So how else can we do this?
There are probably a number of ways but the easiest way I could come up with was a java mapping program.
On the sender side we have SAP sending out HR details as an example. On the receiver side we have a web service: the wsdl simply described two required fields.
Note field arg1 is of type base64Binary. This is where our PGP encrypted message needs to go. The message to be encrypted has its own xsd as provided by the vendor.
Here’s the Operation mapping to give you an overview of the mapping steps involved:
- This mapping program takes the source data from SAP and maps to the XSD provided by the receiving system vendor
- This mapping takes the result and strips out “most” namespaces (due to a bug in the vendor system). This can be ignored for the purposes of this blog
- This mapping program is our java mapping where we PGP encrypt the message
- Finally the fourth mapping program simply maps the encrypted data into the Base64Binary field of the receiving systems wsdl.
We could of course have done ALL this inside a java mapping but I think that breaking it up into individual programs like this makes it easier to understand and support and more importantly, makes the PGP program completely re-usable (assuming there are other crazy systems out there int he world that like parts of the message encrypted with PGP).
ps. My friend Dieter Bauer actually pushed me along this way as I was about to hack it all in Java 😉
So how do we do PGP in Java. Should be easy? What I found was that there are a number of convoluted libraries out there with little or no documentation to support them. The ‘best of the worst’ seemed to be Bouncy Castle. So off I went reading their sample programs and “google-programming”, but when I attempted to write any code, eclipse kept saying that the main methods I wanted to use were deprecated.
As it turns out, Bouncy Castle have shipped newer versions of their famework but forgotten to update any of their sample programs. I found any documentation next to useless as well.
A couple more hours and more googling for code snippets and I had come up with a re-usable module that will PGP encrypt, sign, decrypt any platintext from a java stream. Source code gist.
There are two classes:
- The mapping library program that can be re-used anywhere you need to apply a PGP encryption, decryption or message signing. BcPGP.java
- The PI java mapping program – a reusable java mapping program which will encrypt the source message using PGP: MapPGP.java
The BcPGP method for encrypting relies on a tmp file being used. The encryptString routine in MapPGP is slighlty better as the tmp file is not requied.
BcPGP includes the decryptFile method – it actually works on a stream so doesn’t need to use a file.
BcPGP includes a method signEncryptFile – this one does need a file to work with but can probably be refactored to remove the file. Note that this method hard-codes the encryptiopn type and other parameters as it was just used for testing and no more.
MapPGP only relies on BcPGP for the readPublicKey method – it would be easy to re-factor this and not use BcPGP for encryption.
Hopefully this will help anyone else out there requiring some PGP encryption in their integrations where you can’t use the standard adapter module provided by SAP.
Usual caveats apply about anyone using this in a production system.
ps. As per comment below – here is a pic of PI operation mapping parameters: