Bouncy Castle – Encrypt a stream

I should be forgiven for thinking that encrypting a stream of data instead of a disk file is more difficult than it is supposed to be. Actually when somebody like me who has no experience with writing secure code uses encryption/decryption libraries like Bouncy Castle, it is always hard. So even after the PCI auditor has paid us a visit many times I can still point out many loopholes in our security code like the AES key that is hard-coded. Split key technology is really hard to grok. So I have not attempted it yet. So the AES key is still inside the java class.

This example uses Bouncy Castle to decrypt a file using a GPG key and encrypt it again using another key on the fly. Some parts of the code that are supposed to be obvious are not shown but as I mentioned secure code is hard to write. The missing piece can be reconstructed from the Bouncy Castle examples.

I am planning to fix the code formatting in the blog soon.

Decrypt a file and return a stream

public InputStream decryptToStream( String file ) throws KeyNotFoundException{

PGPEncryptedDataList enc = null;

PGPObjectFactory objectFactory = null;

InputStream in = null;

try {

objectFactory = new PGPObjectFactory( new FileInputStream( file ) );

Object o = objectFactory.nextObject();

// What is a PGP marker packet ?

if ( o instanceof PGPEncryptedDataList ) {

enc = ( PGPEncryptedDataList ) o;

} else {

enc = ( PGPEncryptedDataList ) objectFactory.nextObject();

}

Iterator it = enc.getEncryptedDataObjects();

PGPPublicKeyEncryptedData pbe = null;

while ( it.hasNext()){

pbe = (PGPPublicKeyEncryptedData)it.next();

}

InputStream clear = pbe.getDataStream( getPGPSecretKey( pbe.getKeyID() ), "BC" );

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();
}

if (message instanceof PGPLiteralData) {

PGPLiteralData literal = (PGPLiteralData) message;

in = literal.getInputStream();

}
} catch (FileNotFoundException e) {

} catch (IOException e) {

} catch (NoSuchProviderException e) {

} catch (PGPException e) {

}
return in;
}

Encrypt the stream and write to a file

It should be possible to return a stream from this method instead of writing it to a file.

public void encrypt( PGPPublicKey key,
                               String compressedfile,
                               String encryptedfile,
                               InputStream in ) throws IOException,
PGPException,
NoSuchProviderException {
byte[] buf = new byte[ 1024 ],
literalBuffer = new byte[ 1024 ],
encryption = new byte[ 1024 ];

ByteArrayOutputStream o = null;

OutputStream out = null;

FileOutputStream fos = new FileOutputStream( new File( encryptedfile ));

PGPCompressedDataGenerator compressedData = new PGPCompressedDataGenerator(
PGPCompressedDataGenerator.ZIP);
PGPLiteralDataGenerator lg =
new PGPLiteralDataGenerator();

try {

PGPEncryptedDataGenerator data =
new PGPEncryptedDataGenerator( PGPEncryptedData.CAST5,
true,
new SecureRandom(),
"BC");

data.addMethod( key );
int bytes = 0;

OutputStream writeToEncrypt = data.open( fos,
encryption );

OutputStream lgo = lg.open( compressedData.open( writeToEncrypt ),
PGPLiteralData.BINARY,
compressedfile,
new Date(),
literalBuffer
);

while ((bytes = in.read( buf )) >= 0) {
//As it is written it is encrypted.

lgo.write( buf, 0 , bytes );

}

lg.close();
compressedData.close();
writeToEncrypt.close();
lgo.close();

} catch (IOException e) {

} catch (NoSuchProviderException e) {

} catch (PGPException e) {

}
}

add to del.icio.us : Add to Blinkslist : add to furl : Digg it : add to ma.gnolia : Stumble It! : add to simpy : seed the vine : : : TailRank : post to facebook

Additional Blog

I have started writing about my experience with Ubuntu and my interest in programming languages like Erlang here.

Actually it is difficult to learn distributed architectures and tools like REST, Hadoop etc. and scalability if you don’t have enough exposure. I work for the offshore industry and true innovation is hard here because people are wary of revenue and they play a safe game.

This new blog could be about my experiences with many of these open-source initiatives.