Class Decryptor

  • All Implemented Interfaces:
    java.lang.Cloneable

    public class Decryptor
    extends java.lang.Object
    implements java.lang.Cloneable
    Decrypts and verifies PGP messages using the decryption and verification Keys supplied on this object's Ring.

    To turn off verification, setVerificationRequired(boolean) to false. To decrypt a message encrypted with a passphrase (instead of, or in addition to, a public-key pair), use setSymmetricPassphrase(java.lang.String) to supply the passphrase.

    Here's an example of Bob decrypting and verifying an encrypted file that was signed by Alice:

    
     new Decryptor(
         new Key(new File("path/to/my/keys/alice-pub.gpg")),
         new Key(new File("path/to/my/keys/bob-sec.gpg"), "b0bru1z!")
     ).decrypt(
         new File("path/to/ciphertext.txt.gpg"),
         new File("path/back-to/plaintext.txt")
     );
     
    This is equivalent to the following `gpg` command (where Bob has a `bob` secret key and an `alice` public key on his keyring, and enters "b0bru1z!" when prompted for his passphrase):
    
     gpg --decrypt --output path/back-to/plaintext.txt path/to/ciphertext.txt.gpg
     
    • Field Detail

      • DEFAULT_MAX_FILE_BUFFER_SIZE

        public static final int DEFAULT_MAX_FILE_BUFFER_SIZE
        See Also:
        Constant Field Values
      • DEFAULT_VERIFICATION_REQUIRED

        public static final boolean DEFAULT_VERIFICATION_REQUIRED
        See Also:
        Constant Field Values
      • DEFAULT_COPY_FILE_BUFFER_SIZE

        public static final int DEFAULT_COPY_FILE_BUFFER_SIZE
        See Also:
        Constant Field Values
      • DEFAULT_LOGGING_ENABLED

        public static final boolean DEFAULT_LOGGING_ENABLED
        See Also:
        Constant Field Values
      • verificationRequired

        @Deprecated
        protected boolean verificationRequired
        Deprecated.
        Use verificationType instead.
      • symmetricPassphraseChars

        protected char[] symmetricPassphraseChars
      • symmetricPassphrase

        @Deprecated
        protected java.lang.String symmetricPassphrase
        Deprecated.
        Null unless explicitly set by user.
      • maxFileBufferSize

        protected int maxFileBufferSize
      • copyFileBufferSize

        protected int copyFileBufferSize
      • loggingEnabled

        protected boolean loggingEnabled
      • ring

        protected Ring ring
      • log

        protected final org.slf4j.Logger log
    • Constructor Detail

      • Decryptor

        public Decryptor()
        Constructs a decryptor with an empty key ring.
      • Decryptor

        public Decryptor​(Ring ring)
        Constructs a decryptor with the specified key ring.
      • Decryptor

        public Decryptor​(Key... keys)
        Constructs a decryptor with the specified keys.
    • Method Detail

      • isVerificationRequired

        public boolean isVerificationRequired()
        Returns:
        true to require messages be signed with at least one key from ring. Defaults to true.
      • setVerificationRequired

        public void setVerificationRequired​(boolean x)
        Parameters:
        x - true to require messages be signed with at least one key from ring. Defaults to true.
        See Also:
        DEFAULT_VERIFICATION_REQUIRED
      • getSymmetricPassphraseChars

        public char[] getSymmetricPassphraseChars()
        Returns:
        Passphrase to use to decrypt with a symmetric key; or empty char[]. Note that this char[] itself (and not a copy) will be cached and used until clearSecrets() is called (or setSymmetricPassphraseChars(char[]) is called again with a different passphrase, and then the char[] will be zeroed.
      • setSymmetricPassphraseChars

        public void setSymmetricPassphraseChars​(char[] x)
        Parameters:
        x - Passphrase to use to decrypt with a symmetric key; or empty char[]. Note that this char[] itself (and not a copy) will be cached and used until clearSecrets() is called (or setSymmetricPassphraseChars(char[]) is called again with a different passphrase, and then the char[] will be zeroed.
      • getSymmetricPassphrase

        public java.lang.String getSymmetricPassphrase()
        Returns:
        Passphrase to use to decrypt with a symmetric key; or empty string. Prefer getSymmetricPassphraseChars() to avoid creating extra copies of the passphrase in memory that cannot be cleaned up.
        See Also:
        getSymmetricPassphraseChars()
      • getMaxFileBufferSize

        public int getMaxFileBufferSize()
      • setMaxFileBufferSize

        public void setMaxFileBufferSize​(int maxFileBufferSize)
        Decryptor will choose the most appropriate read/write buffer size for each file. You can set the maximum value here. Defaults to 1MB.
        Parameters:
        maxFileBufferSize - The read/write buffer size
        See Also:
        DEFAULT_MAX_FILE_BUFFER_SIZE
      • getCopyFileBufferSize

        public int getCopyFileBufferSize()
        Returns:
        Internal buffer size used to copy data from input ciphertext stream to output plaintext stream internally
        See Also:
        DEFAULT_COPY_FILE_BUFFER_SIZE, getCopyBuffer()
      • setCopyFileBufferSize

        public void setCopyFileBufferSize​(int copyFileBufferSize)
        Parameters:
        copyFileBufferSize - Internal buffer size used to copy data from input ciphertext stream to output plaintext stream internally
        See Also:
        DEFAULT_COPY_FILE_BUFFER_SIZE, getCopyBuffer()
      • getRing

        public Ring getRing()
        Returns:
        Keys Ring to use for decryption and verification.
      • setRing

        public void setRing​(Ring x)
        Parameters:
        x - Keys Ring to use for decryption and verification.
      • isLoggingEnabled

        public boolean isLoggingEnabled()
        Returns:
        true if logging a brief summary of the execution every time decryption is executed (e.g. file name/path, size, compression type, etc.). Note: errors/warnings logging are not affected by this setting
      • setLoggingEnabled

        public void setLoggingEnabled​(boolean enabled)
        Parameters:
        enabled - true if should log a brief summary of the execution every time decryption is executed (e.g. file name/path, size, compression type, etc.). Note: errors/warnings logging are not affected by this setting
      • clearSecrets

        public void clearSecrets()
        Zeroes-out the cached passphrase for all keys, and releases the extracted private key material for garbage collection.
      • decrypt

        public FileMetadata decrypt​(java.io.File ciphertext,
                                    java.io.File plaintext)
                             throws java.io.IOException,
                                    org.bouncycastle.openpgp.PGPException
        Decrypts the first specified file to the output location specified by the second file, and (if isVerificationRequired()) verifies its signatures. If a file already exists in the output file's location, it will be deleted. If an exception occurs during decryption, the output file will be deleted.
        Parameters:
        ciphertext - File containing a PGP message, in binary or ASCII Armor format.
        plaintext - File into which to decrypt the message.
        Returns:
        Metadata of original file, and the list of keys that signed the message with a verified signature. The original file metadata values are optional, and may be missing or incorrect.
        Throws:
        java.io.IOException - if an IO error occurs reading from or writing to the underlying input or output streams.
        org.bouncycastle.openpgp.PGPException - if the PGP message is not formatted correctly.
        PassphraseException - if an incorrect passphrase was supplied for one of the decryption keys, or as the getSymmetricPassphrase().
        DecryptionException - if the message was not encrypted for any of the keys supplied for decryption.
        VerificationException - if isVerificationRequired() and the message was not signed by any of the keys supplied for verification.
      • decrypt

        public FileMetadata decrypt​(java.nio.file.Path ciphertext,
                                    java.nio.file.Path plaintext)
                             throws java.io.IOException,
                                    org.bouncycastle.openpgp.PGPException
        Decrypts the first specified file to the output location specified by the second file, and (if isVerificationRequired()) verifies its signatures. If a file already exists in the output file's location, it will be deleted. If an exception occurs during decryption, the output file will be deleted.
        Parameters:
        ciphertext - Path to file containing a PGP message, in binary or ASCII Armor format.
        plaintext - Path of the file into which to decrypt the message.
        Returns:
        Metadata of original file, and the list of keys that signed the message with a verified signature. The original file metadata values are optional, and may be missing or incorrect.
        Throws:
        java.io.IOException - if an IO error occurs reading from or writing to the underlying input or output streams.
        org.bouncycastle.openpgp.PGPException - if the PGP message is not formatted correctly.
        PassphraseException - if an incorrect passphrase was supplied for one of the decryption keys, or as the getSymmetricPassphrase().
        DecryptionException - if the message was not encrypted for any of the keys supplied for decryption.
        VerificationException - if isVerificationRequired() and the message was not signed by any of the keys supplied for verification.
      • wrapSourceInputStream

        public java.io.InputStream wrapSourceInputStream​(java.io.InputStream sourceStream,
                                                         long inputSize)
                                                  throws java.io.IOException
        Parameters:
        sourceStream - Original source (ciphertext) InputStream
        inputSize - Expected input (ciphertext) size
        Returns:
        A wrapper buffered stream optimized for the input size according to the current encryptor settings
        Throws:
        java.io.IOException - If failed to generate the wrapper
      • wrapTargetOutputStream

        public java.io.OutputStream wrapTargetOutputStream​(java.io.OutputStream targetStream,
                                                           long inputSize)
                                                    throws java.io.IOException
        Parameters:
        targetStream - Original target (plaintext) OutputStream
        inputSize - Expected input (ciphertext) size
        Returns:
        A wrapper buffered stream optimized for the input size according to the current encryptor settings
        Throws:
        java.io.IOException - If failed to generate the wrapper
      • decrypt

        public FileMetadata decrypt​(java.io.InputStream ciphertext,
                                    java.io.OutputStream plaintext)
                             throws java.io.IOException,
                                    org.bouncycastle.openpgp.PGPException
        Decrypts the specified PGP message into the specified output stream, and (if isVerificationRequired()) verifies the message signatures. Does not close or flush the streams.

        Note that the full decrypted content will be written to the output stream before the message is verified, so you may want to buffer the content and not write it to its final destination until this method returns.

        Parameters:
        ciphertext - PGP message, in binary or ASCII Armor format.
        plaintext - Decrypted content.
        Returns:
        Metadata of original file, and the list of keys that signed the message with a verified signature. The original file metadata values are optional, and may be missing or incorrect.
        Throws:
        java.io.IOException - if an IO error occurs reading from or writing to the underlying input or output streams.
        org.bouncycastle.openpgp.PGPException - if the PGP message is not formatted correctly.
        PassphraseException - if an incorrect passphrase was supplied for one of the decryption keys, or as the getSymmetricPassphrase().
        DecryptionException - if the message was not encrypted for any of the keys supplied for decryption.
        VerificationException - if isVerificationRequired() and the message was not signed by any of the keys supplied for verification.
        See Also:
        decryptWithFullDetails
      • decryptWithFullDetails

        public DecryptionResult decryptWithFullDetails​(java.io.InputStream ciphertext,
                                                       java.io.OutputStream plaintext)
                                                throws java.io.IOException,
                                                       org.bouncycastle.openpgp.PGPException
        Decrypts the specified PGP message into the specified output stream, including the armored headers (if stream was armored and contained any such headers). If isVerificationRequired() also verifies the message signatures. Note: does not close or flush the streams.
        Parameters:
        ciphertext - PGP message, in binary or ASCII Armor format.
        plaintext - Decrypted content target OutputStream
        Returns:
        The DecryptionResult containing all relevant information that could be extracted from the encrypted data - including metadata, armored headers (if any), etc...
        Throws:
        java.io.IOException - if an IO error occurs reading from or writing to the underlying input or output streams.
        org.bouncycastle.openpgp.PGPException - if the PGP message is not formatted correctly.
        PassphraseException - if an incorrect passphrase was supplied for one of the decryption keys, or as the getSymmetricPassphrase().
        DecryptionException - if the message was not encrypted for any of the keys supplied for decryption.
        VerificationException - if isVerificationRequired() and the message was not signed by any of the keys supplied for verification.
      • unpack

        protected java.util.List<FileMetadata> unpack​(java.util.Iterator<?> packets,
                                                      java.io.OutputStream plaintext)
                                               throws java.io.IOException,
                                                      org.bouncycastle.openpgp.PGPException
        Recursively unpacks the pgp message packets, writing the decrypted message content into the output stream.
        Throws:
        java.io.IOException
        org.bouncycastle.openpgp.PGPException
      • buildVerifiers

        protected java.util.List<Decryptor.Verifier> buildVerifiers​(java.util.Iterator<?> signatures)
                                                             throws org.bouncycastle.openpgp.PGPException
        Builds a Decryptor.Verifier for each specified signature for which a verification key is available.
        Throws:
        org.bouncycastle.openpgp.PGPException
      • matchSignatures

        protected void matchSignatures​(java.util.Iterator<org.bouncycastle.openpgp.PGPSignature> signatures,
                                       java.util.List<Decryptor.Verifier> verifiers)
        Matches the specified trailing signatures to the specified verifiers.
      • decrypt

        protected java.io.InputStream decrypt​(java.util.Iterator<?> data)
                                       throws java.io.IOException,
                                              org.bouncycastle.openpgp.PGPException
        Decrypts the encrypted data as the returned input stream.
        Throws:
        java.io.IOException
        org.bouncycastle.openpgp.PGPException
      • decrypt

        protected java.io.InputStream decrypt​(org.bouncycastle.openpgp.PGPPublicKeyEncryptedData data,
                                              Subkey subkey)
                                       throws java.io.IOException,
                                              org.bouncycastle.openpgp.PGPException
        Decrypts the encrypted data as the returned input stream.
        Throws:
        java.io.IOException
        org.bouncycastle.openpgp.PGPException
      • decrypt

        protected java.io.InputStream decrypt​(org.bouncycastle.openpgp.PGPPBEEncryptedData data)
                                       throws java.io.IOException,
                                              org.bouncycastle.openpgp.PGPException
        Decrypts the encrypted data as the returned input stream.
        Throws:
        java.io.IOException
        org.bouncycastle.openpgp.PGPException
      • copy

        protected long copy​(java.io.InputStream i,
                            java.io.OutputStream o,
                            java.util.List<Decryptor.Verifier> verifiers)
                     throws java.io.IOException,
                            org.bouncycastle.openpgp.PGPException
        Copies the content from the specified input stream to the specified output stream, while also checking the content with the specified list of verifiers (if verification required).
        Throws:
        java.io.IOException
        org.bouncycastle.openpgp.PGPException
      • verify

        protected void verify​(java.util.List<Decryptor.Verifier> verifiers,
                              java.util.List<FileMetadata> meta)
                       throws org.bouncycastle.openpgp.PGPException
        Verifies each verifier's signature, and adds keys with verified signatures to the file metadata.
        Throws:
        org.bouncycastle.openpgp.PGPException
      • unarmor

        protected java.io.InputStream unarmor​(java.io.InputStream stream)
                                       throws java.io.IOException,
                                              org.bouncycastle.openpgp.PGPException
        Wraps stream with ArmoredInputStream if necessary (to convert ASCII-armored content back into binary data).
        Throws:
        java.io.IOException
        org.bouncycastle.openpgp.PGPException
      • parse

        protected java.util.Iterator<?> parse​(java.io.InputStream stream)
        Separates stream into PGP packets.
        See Also:
        PGPObjectFactory
      • getVerifierProvider

        protected org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider getVerifierProvider()
        Helper for signature verification.
      • isUsableForDecryption

        protected boolean isUsableForDecryption​(Subkey subkey)
      • buildPublicKeyDecryptor

        protected org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory buildPublicKeyDecryptor​(Subkey subkey)
                                                                                                   throws org.bouncycastle.openpgp.PGPException
        Builds a symmetric-encryption decryptor for the specified subkey.
        Throws:
        org.bouncycastle.openpgp.PGPException
      • buildSymmetricKeyDecryptor

        protected org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory buildSymmetricKeyDecryptor​(char[] passphraseChars)
                                                                                                throws org.bouncycastle.openpgp.PGPException
        Builds a symmetric-key decryptor for the specified passphrase.
        Throws:
        org.bouncycastle.openpgp.PGPException
      • getCopyBuffer

        public byte[] getCopyBuffer()
        Internal buffer for copying decrypted plaintext into the output stream.
      • clone

        public Decryptor clone()
        Overrides:
        clone in class java.lang.Object