Class Ghostryde
Whenever we stage sensitive data to cloud storage (like XML RDE deposit data), we GHOST RYDE IT first to keep it safe from the prying eyes of anyone with access to the Google Cloud Console.
The encryption is similar to the "regular" RyDE RDE deposit file encryption. The main difference (and the reason we had to create a custom encryption) is that the RDE deposit has a tar file in the encoding. A tar file needs to know its final size in the header, which means we have to create the entire deposit before we can start encoding it.
Deposits are big, and there's no reason to hold it all in memory. Instead, save a "staging" version encrypted with Ghostryde instead of "RyDE" (the RDE encryption/encoding), using the "rde-staging" keys. We also remember the actual data size during the staging creation.
Then when we want to create the actual deposits, we decrypt the staging version, and using the saved value for the data size we can encrypt with "RyDE" using the receiver key.
Here's how you write a file:
File in = new File("lol.txt");
File out = new File("lol.txt.ghostryde");
File lengthOut = new File("lol.length.ghostryde");
try (OutputStream output = new FileOutputStream(out);
OutputStream lengthOutput = new FileOutputStream(lengthOut);
OutputStream ghostrydeEncoder = Ghostryde.encoder(output, publicKey, lengthOut);
InputStream input = new FileInputStream(in)) {
ByteStreams.copy(input, ghostrydeEncoder);
}
Here's how you read a file:
File in = new File("lol.txt.ghostryde");
File out = new File("lol.txt");
Ghostryde ghost = new Ghostryde(1024);
try (InputStream fileInput = new FileInputStream(in);
InputStream ghostrydeDecoder = new Ghostryde.decoder(fileInput, privateKey);
OutputStream fileOutput = new FileOutputStream(out)) {
ByteStreams.copy(ghostryderDecoder, fileOutput);
}
Simple API
If you're writing test code or are certain your data can fit in memory, you might find these static methods more convenient:
byte[] data = "hello kitty".getBytes(UTF_8);
byte[] blob = Ghostryde.encode(data, publicKey);
byte[] result = Ghostryde.decode(blob, privateKey);
GhostRYDE Format
A .ghostryde
file is the exact same thing as a .gpg
file, except the OpenPGP
message layers will always be present and in a specific order. You can analyse the layers on the
command-line using the gpg --list-packets blah.ghostryde
command.
Ghostryde is different from RyDE in the sense that ghostryde is only used for internal storage; whereas RyDE is meant to protect data being stored by a third-party.
-
Method Summary
Modifier and TypeMethodDescriptionstatic byte[]
decode
(byte[] data, org.bouncycastle.openpgp.PGPPrivateKey key) Deciphers a ghostryde file from an in-memory byte array.static ImprovedInputStream
decoder
(InputStream input, org.bouncycastle.openpgp.PGPPrivateKey decryptionKey) Creates a Ghostryde decoder.static byte[]
encode
(byte[] data, org.bouncycastle.openpgp.PGPPublicKey key) Creates a ghostryde file from an in-memory byte array.static ImprovedOutputStream
encoder
(OutputStream output, org.bouncycastle.openpgp.PGPPublicKey encryptionKey) Creates a Ghostryde Encoder.static ImprovedOutputStream
encoder
(OutputStream output, org.bouncycastle.openpgp.PGPPublicKey encryptionKey, OutputStream lengthOutput) Creates a Ghostryde Encoder.static long
readLength
(InputStream lengthStream) Reads the value of a length stream - seeencoder(java.io.OutputStream, org.bouncycastle.openpgp.PGPPublicKey, java.io.OutputStream)
.
-
Method Details
-
encode
public static byte[] encode(byte[] data, org.bouncycastle.openpgp.PGPPublicKey key) throws IOException Creates a ghostryde file from an in-memory byte array.- Throws:
IOException
-
decode
public static byte[] decode(byte[] data, org.bouncycastle.openpgp.PGPPrivateKey key) throws IOException Deciphers a ghostryde file from an in-memory byte array.- Throws:
IOException
-
readLength
Reads the value of a length stream - seeencoder(java.io.OutputStream, org.bouncycastle.openpgp.PGPPublicKey, java.io.OutputStream)
.- Throws:
IOException
-
encoder
public static ImprovedOutputStream encoder(OutputStream output, org.bouncycastle.openpgp.PGPPublicKey encryptionKey, @Nullable OutputStream lengthOutput) Creates a Ghostryde Encoder.Optionally can also save the total length of the data written to an OutputStream.
This is necessary because the RyDE format uses a tar file which requires the total length in the header. We don't want to have to decrypt the entire ghostryde file to determine the length, so we just save it separately.
- Parameters:
output
- where to write the encrypted dataencryptionKey
- the encryption key to uselengthOutput
- if not null - will save the total length of the data written to this output. SeereadLength(java.io.InputStream)
.
-
encoder
public static ImprovedOutputStream encoder(OutputStream output, org.bouncycastle.openpgp.PGPPublicKey encryptionKey) Creates a Ghostryde Encoder.- Parameters:
output
- where to write the encrypted dataencryptionKey
- the encryption key to use
-
decoder
public static ImprovedInputStream decoder(InputStream input, org.bouncycastle.openpgp.PGPPrivateKey decryptionKey) Creates a Ghostryde decoder.- Parameters:
input
- from where to read the encrypted datadecryptionKey
- the decryption key to use
-