Class Ghostryde


  • public final class Ghostryde
    extends java.lang.Object
    Utility class for reading and writing data in the ghostryde container format.

    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

      All Methods Static Methods Concrete Methods 
      Modifier and Type Method Description
      static byte[] decode​(byte[] data, org.bouncycastle.openpgp.PGPPrivateKey key)
      Deciphers a ghostryde file from an in-memory byte array.
      static ImprovedInputStream decoder​(java.io.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​(java.io.OutputStream output, org.bouncycastle.openpgp.PGPPublicKey encryptionKey)
      Creates a Ghostryde Encoder.
      static ImprovedOutputStream encoder​(java.io.OutputStream output, org.bouncycastle.openpgp.PGPPublicKey encryptionKey, java.io.OutputStream lengthOutput)
      Creates a Ghostryde Encoder.
      static long readLength​(java.io.InputStream lengthStream)
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • encode

        public static byte[] encode​(byte[] data,
                                    org.bouncycastle.openpgp.PGPPublicKey key)
                             throws java.io.IOException
        Creates a ghostryde file from an in-memory byte array.
        Throws:
        java.io.IOException
      • decode

        public static byte[] decode​(byte[] data,
                                    org.bouncycastle.openpgp.PGPPrivateKey key)
                             throws java.io.IOException
        Deciphers a ghostryde file from an in-memory byte array.
        Throws:
        java.io.IOException
      • encoder

        public static ImprovedOutputStream encoder​(java.io.OutputStream output,
                                                   org.bouncycastle.openpgp.PGPPublicKey encryptionKey,
                                                   @Nullable
                                                   java.io.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 data
        encryptionKey - the encryption key to use
        lengthOutput - if not null - will save the total length of the data written to this output. See readLength(java.io.InputStream).
      • encoder

        public static ImprovedOutputStream encoder​(java.io.OutputStream output,
                                                   org.bouncycastle.openpgp.PGPPublicKey encryptionKey)
        Creates a Ghostryde Encoder.
        Parameters:
        output - where to write the encrypted data
        encryptionKey - the encryption key to use
      • decoder

        public static ImprovedInputStream decoder​(java.io.InputStream input,
                                                  org.bouncycastle.openpgp.PGPPrivateKey decryptionKey)
        Creates a Ghostryde decoder.
        Parameters:
        input - from where to read the encrypted data
        decryptionKey - the decryption key to use