SOA suite provides a way to do file
preprocessing. In this particular scenario we will create a valve that uses PGP
private key to decrypt an encrypted file.
If you
required additional information about oracle pipelines please review the
following link
We are going to use bouncy castle as main PGP library
And this code as reference
A.
Java Valve code
1. 1. Create a new project in JDev adding the
following libraries
Bpm-infra should be on your SOA Suite installation ./Oracle_OSB1/soa/modules/oracle.soa.fabric_11.1.1/bpm-infra.jar
Bcpg-jdk15on-19.jar, bcprov-ext-jdk15on-149.jar and bcprov-jdk15on-149.jar
you can download them from bouncy castle website.
2. 2. Create a properties file that will indicate where
your key and passphrase are, add it to Jdev
#properties file for PGP decrypt file
privatekey=/home/oracle/work/aaronkey.gpg
passphrase=welcome1
3. 3. Create the following code
package something;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import oracle.tip.pc.services.pipeline.AbstractValve;
import oracle.tip.pc.services.pipeline.InputStreamContext;
import oracle.tip.pc.services.pipeline.PipelineException;
public class DecryptPGPValve extends AbstractValve {
public
DecryptPGPValve() {
super();
}
public
InputStreamContext execute(InputStreamContext inputStreamContext) throws
PipelineException,
IOException {
Properties
props = new Properties();
try {
props.load(DecryptPGPValve.class.getResourceAsStream("/resource.properties"));
} catch
(Exception ex) {
ex.printStackTrace();
}
PGPFileProcessor pgp = new PGPFileProcessor();
pgp.setSecretKeyFileName(props.getProperty("privatekey")); //
can be either binary or text key
pgp.setPassphrase(props.getProperty("passphrase"));
byte[]
encrypted = null;
try {
encrypted
= pgp.decrypt(inputStreamContext.getInputStream());
} catch
(Exception ex) {
ex.printStackTrace();
}
inputStreamContext.setInputStream(new ByteArrayInputStream(encrypted));
return
inputStreamContext;
}
public void
finalize(InputStreamContext inputStreamContext) {
}
public void
cleanup() throws PipelineException, IOException {
}
}
4. 4. From the code provided by bouncy castle modify
the decrypt method to return bytes
Something like this (check lines in red)
/**
* decrypt the
passed in message stream
*/
@SuppressWarnings("unchecked")
public static
byte[] decryptFileBytes(InputStream in, InputStream keyIn, char[] passwd)
throws
Exception
{
byte[]
encrypted = null;
Security.addProvider(new BouncyCastleProvider());
in =
org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in);
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o =
pgpF.nextObject();
//
// the first
object might be a PGP marker packet.
//
if (o
instanceof PGPEncryptedDataList) {
enc =
(PGPEncryptedDataList) o;
} else {
enc =
(PGPEncryptedDataList) pgpF.nextObject();
}
//
// find the
secret key
//
Iterator<PGPPublicKeyEncryptedData> it =
enc.getEncryptedDataObjects();
PGPPrivateKey
sKey = null;
PGPPublicKeyEncryptedData
pbe = null;
while (sKey ==
null && it.hasNext()) {
pbe =
it.next();
sKey =
findPrivateKey(keyIn, pbe.getKeyID(), passwd);
}
if (sKey ==
null) {
throw new
IllegalArgumentException("Secret key for message not found.");
}
InputStream
clear = pbe.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
Object message
= plainFact.nextObject();
if (message
instanceof PGPCompressedData) {
PGPCompressedData cData = (PGPCompressedData) message;
PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream());
message =
pgpFact.nextObject();
}
final
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final
DataOutputStream dos = new DataOutputStream( baos );
if (message
instanceof PGPLiteralData) {
PGPLiteralData ld = (PGPLiteralData) message;
InputStream unc = ld.getInputStream();
int ch;
while ((ch
= unc.read()) >= 0) {
//out.write(ch);
dos.write(ch);
}
dos.close();
encrypted = baos.toByteArray();
baos.close();
} else if
(message instanceof
PGPOnePassSignatureList) {
throw new
PGPException("Encrypted message contains a signed message - not literal
data.");
} else {
throw new
PGPException("Message is not a simple encrypted file - type
unknown.");
}
if
(pbe.isIntegrityProtected()) {
if
(!pbe.verify()) {
throw
new PGPException("Message failed integrity check");
}
}
System.out.println("decode:" + encrypted);
return
encrypted;
}
5. 5. Compress your files in a JAR file and place them
in
/home/oracle/Oracle/Middleware/Oracle_SOA1/soa/modules/oracle.soa.ext_11.1.1
/home/oracle/Oracle/Middleware/user_projects/domains/base_domain/lib
Directories might change
6. 6. Add bouncy castle libraries as well
Bcpg-jdk15on-19.jar, bcprov-ext-jdk15on-149.jar and bcprov-jdk15on-149.jar
in the following directories
/home/oracle/Oracle/Middleware/Oracle_SOA1/soa/modules/oracle.soa.ext_11.1.1
/home/oracle/Oracle/Middleware/user_projects/domains/base_domain/lib
7. Bounce your server and let’s continue working on the composite
b. Composites
Our idea is to create a composite that will read a file from
file system and will decode it another directory. This can be easily replace
with FTP adapter and work as well.
1. 1. Create a PollFile adapter
a.
Is important to uncheck the Use file streaming
option
b.
Use native format opaque
2. 2. Create a “filePipeline.xml” file in Jdeveloper
as following
<?xml version="1.0"?>
<pipeline
xmlns="http://www.oracle.com/adapter/pipeline">
<valves>
<valve>us.myvalve.com.ebs.encryption.gpg.DecryptPGPValve</valve>
</valves>
</pipeline>
3. 3. Open the poll jca file and add the pipeline property
<adapter-config name="PollFile"
adapter="File Adapter" wsdlLocation="PollFile.wsdl"
xmlns="http://platform.integration.oracle/blocks/adapter/fw/metadata">
<connection-factory location="eis/FileAdapter"
UIincludeWildcard="test*.pgp"/>
<endpoint-activation portType="Read_ptt"
operation="Read">
<activation-spec
className="oracle.tip.adapter.file.inbound.FileActivationSpec">
<property
name="DeleteFile" value="true"/>
<property
name="MinimumAge" value="0"/>
<property
name="PhysicalDirectory"
value="/home/oracle/work/files"/>
<property
name="Recursive" value="false"/>
<property
name="PollingFrequency" value="10"/>
<property
name="PhysicalArchiveDirectory"
value="/home/oracle/work/archive"/>
<property
name="IncludeFiles" value="test.*\.pgp"/>
<property
name="UseHeaders" value="false"/>
<property
name="PipelineFile" value="filePipeline.xml"/>
</activation-spec>
</endpoint-activation>
</adapter-config>
4. 4. Create a write sync operation file
Your decryption should be ready to test
hi
ReplyDeleteHi,
ReplyDeleteThanks in advance for sharing your knowledge.
Can you please tell me what is the purpose of "us.myvalve.com.ebs.encryption.gpg.DecryptPGPValve" this property. What it is doing ?
Hi,
ReplyDeleteDo you the valve code for encryption.
Regards,
Nagaraju
Thank you for your guide to with upgrade information.
ReplyDeleteOracle SOA Online Training Bangalore