OIC/Integration/9 → PGP Encryption/Decryption with stage activity

integratio
9 min readAug 28, 2023

--

This is a post on Oracle Integration Cloud highlighting PGP encryption and decryption using stage activity.

Integration

(1) Flow: Encrypt => [1.a] Trigger → [1.b] Map to Read FTP file → [1.c] Read FTP file → [1.d] Map to Stage write → [1.e] Stage write with PGP Encrypt → [1.f] Stage read file → [1.g] Map to Reply → [1.h] Reply

Decrypt => [2.a] Trigger → [2.b] Map to Read FTP file → [2.c] Read FTP file to Decrypt → [2.d] Map to Reply → [1.h] Reply

Other Case => [3.a] Trigger → [3.b] Raise Custom Exception → [3.c] Reply

(2) Flow Description: Here we are creating an App Driven Orchestration flow exposing via REST which can be invoked passing Query Parameter. When Query Parameter passed is “ENCRYPT”, it reads csv file from FTP location, PGP encrypts the data and write the encrypted message in a csv file. When Query Parameter passed is “DECRYPT”, it reads encrypted csv file from FTP location, PGP decrypts the data and reply the content as string back to caller of the service. In case, the Query Parameter passed is anything except “ENCRYPT” or “DECRYPT”, it returns a custom exception with error response code 500.

(3) Steps:

Pre-Requisite: Generating PGP Private & Public Key

Either, you can use online portals (e.g. PGP Key Generator) to create a set of PGP Private & Public Key, or you can take the help of below command in Unix system to generate the key set.

* Step 1: Confirm GPG version in UNIX
# gpg --help
e.g. gpg (GnuPG) 2.2.19

*Step 2: Start the key generation process. Enter the following command to start generating your key:
# gpg --gen-key

Real name: xyz
Email address: xyz@gmail.com
You selected this USER-ID:
"xyz <xyz@gmail.com>"
Change (N)ame, (E)mail, or (O)kay/(Q)uit? O

generator a better chance to gain enough entropy.
………

*Step 3: Add a subkey for encryption. Enter the following command to start generating your key:

# gpg --edit-key 'xyz'
gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.
………

gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(14) Existing key from card
Your selection? 6

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 2048

Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes.
………

gpg> q
Save changes? (y/N) y
Subkey generation for encryption purposes is complete. The next step is to verify and export the keys.

*Step 4: List your keys. Enter the following command to list the key on your keyring:
# gpg -k

*Step 5 – Export the public key (including subkey) in ASCII format. Enter the following command to list the keys:
# gpg --armor --output /home/xyz/.gnupg/pgp_keys_out/xyz-pub-sub.asc --export 'xyz'
# cat xyz-pub-sub.asc

-----BEGIN PGP PUBLIC KEY BLOCK-----
[content]
-----END PGP PUBLIC KEY BLOCK-----

*Step 6: Export the private key
$ gpg --list-secret-keys
$ gpg --armor --export-secret-keys xyz@gmail.com > /home/xyz/.gnupg/pgp_keys_out/xyz-pvt-sub.asc

One the public and private PGP keys are handy, please proceed to OIC console to import the keys.

Go to OIC console → Settings → Certificates → Upload.

Go to OIC console → Integrations → Create an App Driven Integration with your project name.

[1.a] Trigger:

Here we are using the template parameter “user”, which we will rename later to “method” and we will use to pass method name e.g. ENCRYPT,DECRYPT, others etc.

Use following XSD for definition, “RestPgpSchema.xsd”:

<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.rest.pgp.com"
targetNamespace="http://www.rest.pgp.com"
elementFormDefault="qualified">
<xsd:element name="pgpReq">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="fileName" type="xsd:string" minOccurs="0"/>
<xsd:element name="fileDir" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="pgpResp">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="result" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

[1.c] Read FTP file: using FTP connection

Using FTP Read file option to read from FTP location. For Directory and File Name we are using logical names. Later we will use map to pass values from input request.

Use the following csv file, “User_Input.csv”:

First_Name,Last_Name,Designation,Qualification,Salary
Naman,Kapoot,Sr. Manager,MA,"67,000"
Disha,Patel,Vice President,MBA,"87,000"
Dev,Ghelot,Sr. Manager,Btech,"97,000"
Priya,Kapoor,SVP,MBA,"77,000"
Dinesh,Bhatt,Consultant,BCOM,"71,000"
Robert,Peter,Sr. Manager,MIS,"81,000"

Flow looks like:

[1.b] Map to Read FTP file: map from Input Request fields

[1.e] Stage write with PGP Encrypt:

File Name: “PgpEncryptFile.csv”

Directory: “/tmpPgpDir”

[1.d] Map to Stage write:

Use XSLT option and drag and drop to create a For-Each and do one to one mapping.

[1.f] Stage read file:

Here we are using File Reference option that we got from Write Stage Response activity.

Use following XSD for definition, “OpaqueSchema.xsd” :

<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:opaque="http://xmlns.oracle.com/pcbpel/adapter/opaque/"
targetNamespace="http://xmlns.oracle.com/pcbpel/adapter/opaque/"
elementFormDefault="qualified">
<xsd:element name="opaqueElement" type="xsd:base64Binary"/>
</xsd:schema>

The Base64Binary encoded data message is stored, which later we will decode.

[1.g] Map to Reply:

Use XSLT function: oraext:decodeBase64 ($ReadPgpDecryFile/nsmpr3:ReadResponse/ns79:opaqueElement ) to decode the Base64encoded string.

Go to flow again:

Edit the “ReceivePgpReq” activity to modify endpoint URI.

Modify as below:

[2.a] Trigger:

Add Switch activity to the flow , so that we can create separate branches for Encrypt and Decrypt operation. Operation selection will be based on the template parameter “method”, the one we just modify above.

Use Reposition to move the existing activities that we have for Encryption to bring inside the branch for Encryption.

Flow will look like:

Incase, user hits service with an invalid method name (anything except Encryption or Decryption), we need to raise an exception with custom message. For this we need to set up the otherwise branch.

[3.a] Trigger: goes to Otherwise for non matching method name.

[3.b] Raise Custom Exception:

Now, we will set up for Decrypt case.

[2.c] Read FTP file to Decrypt:

Use XSLT function: oraext:get-content-as-string ($ReadDecryptPgpFile/nsmpr0:ReadResponse/ns25:empRecordSetOut ) to get the decrypted string in serialized form.

[2.b] Map to Read FTP file:

[2.d] Map to Reply:

Testing:
a. Invalid Query Parameter: passed “method” Query Parameter as not matching value “INVALID”

b. {method} as “ENCRYPT”

Copy the Response text and store in a file “User_Input_Encrypted.csv” that will be used for Decrypt scenario test.

c. {method} as “DECRYPT”

………………………………………………………………………………………………

--

--

integratio

📌 IT Backend enthusiast 📌 Blogging about Oracle FMW, Python, Cloud related technologies 📌 Non monetized, non hustle 📌 Knowledge sharing sole purpose