Make using Bouncy Castle with OpenPGP great fun again!
This project gives you the following super-powers
Bouncy GPG comes with several examples build in.
Bouncy GPG supports reading gpg
keyrings and parsing keys exported via gpg --export
and gpg --export-secret-key
.
The unit tests have some examples creating/reading keyrings.
The easiest way to manage keyrings is to use the pre-defined KeyringConfigs.
The following snippet encrypts /tmp/plaintext.txt
to recipient@example.com
and signs with sender@example.com
.
The encrypted file is written to /tmp/encrypted.gpg
.
final KeyringConfig keyringConfig = KeyringConfigs
.withKeyRingsFromFiles(
"pubring.gpg",
"secring.gpg",
KeyringConfigCallbacks.withPassword("s3cr3t"));
try (
final FileOutputStream fileOutput = new FileOutputStream("/tmp/encrypted.gpg");
final BufferedOutputStream bufferedOut = new BufferedOutputStream(fileOutput);
final OutputStream outputStream = BouncyGPG
.encryptToStream()
.withConfig(keyringConfig)
.withStrongAlgorithms()
.toRecipient("recipient@example.com")
.andSignWith("sender@example.com")
.binaryOutput()
.andWriteTo(bufferedOut);
final FileInputStream is = new FileInputStream("/tmp/plaintext.txt")
) {
Streams.pipeAll(is, outputStream);
}
The following snippet decrypts the file created in the snippet above.
final KeyringConfig keyringConfig = KeyringConfigs
.withKeyRingsFromFiles(
"pubring.gpg",
"secring.gpg",
KeyringConfigCallbacks.withPassword("s3cr3t"));
try (
final FileInputStream cipherTextStream = new FileInputStream("/tmp/encrypted.gpg");
final FileOutputStream fileOutput = new FileOutputStream(destFile);
final BufferedOutputStream bufferedOut = new BufferedOutputStream(fileOutput);
final InputStream plaintextStream = BouncyGPG
.decryptAndVerifyStream()
.withConfig(keyringConfig)
.andIgnoreSignatures()
.fromEncryptedInputStream(cipherTextStream)
) {
Streams.pipeAll(plaintextStream, bufferedOut);
}
Bouncy castle is often fast enough to not be the bottleneck. That said, here are some metrics to give you an indication of the performance:
Use Case | MBP 2,9 GHz Intel Core i5, Java 1.8.0_111 | (please add more via PR) |
---|---|---|
Encrypt & sign 1GB random | ~64s (16 MB/s) | |
Decrypt 1GB random | ~32s (32 MB/s) |
The directory examples contains several examples that show how easy some common use cases are implemented.
Decrypt a file and verify the signature.
decrypt.sh SOURCEFILE DESTFILE
Uses the testing keys to decrypt a file. Useful for performance measurements and gpg
interoperability.
Encrypt and sign a file.
encrypt.sh SOURCEFILE DESTFILE
Uses the testing keys to encrypt a file. Useful for performance measurements and gpg
interoperability.
A GPG encrypted ZIP file is decrypted on the fly. The structure of the ZIP is then written to disk. All files are re-encrypted before saving them.
demo_reencrypt.sh TARGET
– decrypts an encrypted ZIP file containing three files (total size: 1.2 GB) AND
re-encrypts each of the files in the ZIP to the TARGET
dir.The sample shows how e.g. batch jobs can work with large files without leaving plaintext on disk (together with Transparent GPG decryption).
This scheme has some very appealing benefits:
* Data in transit is always encrypted with public key cryptography. Indispensable when you have to use ftp
,
comforting when you use https
and the next Heartbleed pops up.
* Data at rest is always encrypted with public key cryptography. When (not if) you get hacked, this can make all the
difference between “Move along folks, nothing to see here!” and “I lost confidential customer data to the competition”.
* You still need to protect the private keys, but this is considerable easier than the alternatives.
Consider the following batch job:
pre-processing
needs to split up the data for further processingpre-processing
stream-processes the GPG/ZIP archive
InputStream
processing
job transparently reads the files without writing plaintext to the disk.Have a look at the example classes to see how easy it is to use Bouncy Castle PGP.
Add bouncy castle as a dependency and then install the provider before in your application.
// build.gradle
// in build.gradle add a dependency to bouncy castle and bouncy-gpg
//...
repositories {
mavenCentral()
jcenter()
}
//...
// ...
dependencies {
compile 'org.bouncycastle:bcprov-jdk15on:1.57'
compile 'org.bouncycastle:bcpg-jdk15on:1.57'
// ...
compile 'name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:2.+'
// ...
}
Dropping this in the root level of pom.xml lets you use this lib in a maven project:
<repositories>
<repository>
<id>bintray</id>
<name>bintray</name>
<snapshots>
<enabled>false</enabled>
</snapshots>
<url>http://jcenter.bintray.com</url>
</repository>
</repositories>
and this dependency snippet:
<dependency>
<groupId>name.neuhalfen.projects.crypto.bouncycastle.openpgp</groupId>
<artifactId>bouncy-gpg</artifactId>
<version>2.0.1</version>
</dependency>
// in one of you classed install the BC provider
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
Class | Use when you want to |
---|---|
BouncyGPG |
Starting point for the convenient fluent en- and decryption API. |
KeyringConfigs |
Create default implementations for GPG keyring access. You can also create your own implementations by implementing KeyringConfig . |
KeyringConfigCallbacks |
Used by KeyringConfigs . Create default implementations to provide secret-key passwords. |
DefaultPGPAlgorithmSuites |
Select from predefined algorithms suites or create your won with PGPAlgorithmSuite . |
ReencryptExplodedZipSinglethread |
Work with encrypted ZIPs |
The project is a basic gradle build. All the scripts use ./gradlew installDist
The coverage report (incl. running tests) is generated with ./gradlew check
.
./gradlew bintrayUpload
./gradlew previewWebsite
./gradlew publishWebsite
All Concordion specifications are executed and the result is copied into website/content/specification
.
This code is placed under the Apache License 2.0. Don’t forget to adhere to the BouncyCastle License (http://bouncycastle.org/license.html).