cancel
Showing results for 
Search instead for 
Did you mean: 

Decryption of XML fields using Private Key file in KeyStore

vishal1889
Active Participant
0 Kudos

Hi All,

We have recently came across a requirement where we need to perform decryption of a single XML field in the payload. Basically, we need to generate a X.509 Certificate and send it to a third party to encrypt the Employee Bank details and pass on the file to us. No in PI we need to decrypt that XML field using corresponding Private key stored in NWA Key Store.

This can be done either in EJB module or in mapping (java mapping / UDF). Preferably in Mapping.

I have gone through many bogs and discussions and I could find the Java code for Digital Signature and its verification but nothing for Decryption..

It would be really helpful if someone can advise with the Code Snippet.

I am on PI 7.31 Single Stack.

Regards

Vj

Accepted Solutions (1)

Accepted Solutions (1)

nitindeshpande
Active Contributor
0 Kudos

Hello Vishal,

You can go through the below blog for implementing both Verification and Decryption. This uses the Keys from the Key store.

http://people/rajendra.badi/blog/2011/08/24/configuring-wsse-digital-signing-and-encryption-using-sa...

Regards,

Nitin

vishal1889
Active Participant
0 Kudos

Hi Nitin,

Thanks for your response.

But the blog you are referring to is for SOAP adapter and it encrypt complete Payload. In My case I have to use SFTP Adapter in Sender channel and need to decrypt only one field of the payload.

I have also refereed to your blog, which is to sign the data. I tried modifying it for encryption and decryption, but couldn't succeeded.

http://scn.sap.com/community/pi-and-soa-middleware/blog/2015/09/07/signing-the-request-message-using...

Regards

Vj

nitindeshpande
Active Contributor
0 Kudos

Hello Vishal,

My blog is only for signing. I have not extended it for encryption or decryption. What are the keys used for your encryption by your 3rd party? I mean what type of keys they are, keys with .asc extension or PKCS etc?

Regards,

Nitin

vishal1889
Active Participant
0 Kudos

Hi Nitin,

We'll be generating PKCS12 file and send the X.509 certificate to the 3rd Party. Mostly it will be .cer file.

Regards

Vj

nitindeshpande
Active Contributor
0 Kudos

Hello Vishal,

I don't think so, you can use .cer files for encryption. As encryption requires key pairs. And certificates do not work in pairs.

Regards,

Nitin

vishal1889
Active Participant
0 Kudos

Hi Nitin,

I am certainly not a master in the java space for encryption and decryption.

However I referred few post on stack overflow and was able to do the encryption using .cer file and decryption with .pem (extracted from .pfx file).

Below is the sample UDF for encryption, (same works from Adapter module as well)

****************************************************************************************************************

public String encrypt(String input, String keyName, Container container) throws StreamTransformationException{

String message = "";

        byte[] messageBytes;   

        byte[] ciphertextBytes = null;

        try {  

            // The source of randomness

            SecureRandom secureRandom = new SecureRandom();

            // Obtain a RSA Cipher Object

            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

            // Loading certificate file 

            InputStream inStream = new FileInputStream(keyName);

            CertificateFactory cf = CertificateFactory.getInstance("X.509");

            X509Certificate cert =(X509Certificate)cf.generateCertificate(inStream);

            inStream.close();

            // Read the public key from certificate file

            RSAPublicKey pubkey = (RSAPublicKey) cert.getPublicKey();

            messageBytes = input.getBytes();

            // Initialize the cipher for encryption

            cipher.init(Cipher.ENCRYPT_MODE, pubkey, secureRandom);

            // Encrypt the message

            ciphertextBytes = cipher.doFinal(messageBytes);

  byte[] encodedstr = Base64.encodeBase64(ciphertextBytes);

            return new String(encodedstr);

        }catch( IOException e ){

return e.toString();

        }catch( CertificateException e ){

return e.toString();

        }catch( NoSuchAlgorithmException e ){

return e.toString();

        } catch (Exception e) {

return e.toString();

        }

}

******************************************************************************************************************

Here "input" is the field to be encrypted and "keyName" is the .cer file name along with its complete path on filesystem.

Now the problem is I have to access the .cer file from keystore and not file system, which I am unable to do.

Can you please help on that part?

Regards

Vj

engswee
Active Contributor
0 Kudos

Hi Vishal

You can access the keystore using KeyStoreManager per my comment on Nitin's blog

Signing the request message using Certificates and Encoding the message using Base64 - Bouncy Castle...

Rgds

Eng Swe

vishal1889
Active Participant
0 Kudos

Hi Eng,

I tried with that, but its returning a null object exception.

I am still trying to debug the code.

Regards

Vj

vishal1889
Active Participant
0 Kudos

Hi Eng,

Thanks to your valuable feedback, I am able to access the KeyStore now.

But there is still small issue which I am unable to resolve.

If I upload my public and private keys in existing KeyStore view my code works fine and I am able to read the keys with the respective alias.

But when when I tried to create a new KeyStore view and import the same public and private keys in it, I am not able to fetch the keys by their alias.

Is there some kind of permissions which we need to set after KeyStore view creation ?

Regards

Vj

engswee
Active Contributor
0 Kudos

Hi Vishal

Are you getting any errors for this? Can you share a screenshot of the error?

If you search on SCN, it looks like this is a common issue accessing the keystore from mapping. It is recommended to access the keystore using an adapter module instead of mapping as mentioned by Stefan in the thread below.

Otherwise, I think from mapping you can only access the DEFAULT keystore.

Regards

Eng Swee

vishal1889
Active Participant
0 Kudos

Hi Eng,

Thanks for your response.

Below is the screenshot of the error.

I even tried to add some debug statements to see till where my code executes and found that, I am able to find the Keystore view  in the Keystore Manager but unable to retrieve its contents i.e. certificates and private key via their aliases.

Just to make it more clear:

1) Now I am accessing the Keystore via Adapter module only.

2) The Keystore view which I am able to access now is "WebServiceSecurity", which is SAP standard view.


I am not sure on the fact, if we need to grant some addition access to retrieve the contents of the Keystore.

Regards

Vj

engswee
Active Contributor
0 Kudos

Hi Vishal

I tried this with a custom module on my system and faced similar issues as yours. It seems to be only able to access the certificates on some views but not others. If I upload the same certificate into different views, it can only be accessed by the module in some of the views (i.e. DEFAULT, TrustedCAs, WebServiceSecurity).

To be honest, I'm not sure where the permissions for the keystore views are. I can't find anything in NWA regarding that

Regards

Eng Swee

vishal1889
Active Participant
0 Kudos

Hi Eng,

Appreciate your efforts on this.

I was exploring more on the java docs for class SAPSecurityResources and for method "getKeyStoreManager" it says we can define the Permission to our java code using MANIFEST.MF file in the project.

I tried with the example, but since I don't have any experience with MANIFEST.MF file, I wasn't able to explore enough.

Can you suggest in this direction ?

Regards

Vj

engswee
Active Contributor
0 Kudos

Hi Vishal

I noticed there is an extra Security section in the key storage page - didn't notice it before as the color is blue which is same as the background!

In that section, it looks as though it is possible to grant code-based permissions for domains.

Unfortunately, I've tried granting all access to my adapter module but still unable to get access to the certificates in the custom view.

Maybe you can try this out and see how it works on your end. Also, you mentioned that you can access the certs in an existing custom view. Can you check if there were any permissions granted for that view?

Regards

Eng Swee

vishal1889
Active Participant
0 Kudos

Hi Eng,

There was some confusion when I said I was able to access the certificate from existing custom view.

It was always SAP standard view

I'll check more on this setting and advise.

Regards

Vj

engswee
Active Contributor
0 Kudos

Can you let me know which standard view you could access?

vishal1889
Active Participant
0 Kudos

It is WebServiceSecurity only.

Regards

Vj

engswee
Active Contributor
0 Kudos

Hi Vishal

I am able to access that standard view as well. At this point, I'll suggest that you just proceed to storing the certs in that view for access from the module. I don't think there should be an issue with using that view since the description says "Web Services Security: Keys and trusted certificates for message security (sign, verify signatures, decrypt)" which matches what you are trying to achieve.

Regards

Eng Swee

vishal1889
Active Participant
0 Kudos

Hi Eng,

Yes, I am also proceeding with the standard keystore only.

There is one more observation, which I would like to share.

I am able to read the private key from keystore even with the wrong password. Below is the piece of code which I am using to fetch private key.


public Key getPrivateKey(String view, String alias, String password, Location location, AuditAccess audit)

  throws ResourceException, UnrecoverableEntryException {

  final String SIGNATURE = "getPrivateKey()";

  location.entering(SIGNATURE);

  KeyStore keystore = getKeystore(view, location, audit);

  PrivateKey privateKey = null;

  try {

  privateKey = (RSAPrivateKey) keystore.getKey(alias, password.toCharArray());

  if (privateKey == null) {

  location.errorT(SIGNATURE, "Private Key with Alias:\"" + alias +"\" not found in KeyStore View:\"" + view +"\"");

  throw new ResourceException("Private Key with Alias:\"" + alias +"\" not found in KeyStore View:\"" + view +"\"");

  }

  } catch (KeyStoreException e) {

  location.catching(SIGNATURE, e);

  throw new ResourceException(e);

  } catch (NoSuchAlgorithmException e) {

  NoSuchAlgorithmException ne = new NoSuchAlgorithmException(e.toString()+".Private Key with Alias:\"" + alias +"\" not found in KeyStore View:\"" + view +"\"");

  location.catching(SIGNATURE, ne);

  throw new ResourceException(ne);

  } catch (UnrecoverableKeyException e) {

  UnrecoverableKeyException ue = new UnrecoverableKeyException(e.toString()+"Unable to read the Priavte Key with Alias:\"" + alias +"\". Could be due to incorrect password.");

  location.catching(SIGNATURE, ue);

  throw new ResourceException(ue);

  }

  location.exiting(SIGNATURE);

  return privateKey;

  }

Is it possible for you to validate this?

Regards

Vj

engswee
Active Contributor
0 Kudos

Hi Vishal

Coincidentally, Praveen just happened to answer this in the following thread.

Password is not required as access is via code-based. This makes sense because during import to NWA, the password is already required. Therefore once it's in NWA, it'll be accessible. This is unlike direct access to the private key in a filesystem where password is required.

You should try and use the code provided in the sample module ConvertCRLFfromToLF.

Regards

Eng Swee

vishal1889
Active Participant
0 Kudos

Hi Eng,

Thanks for your efforts on this, my adapter module is now working as expected.

Closing this discussion.

Regards

Vj

Answers (0)