tribble.crypto
Class FileEncrypter

java.lang.Object
  extended by tribble.crypto.FileEncrypter

public class FileEncrypter
extends java.lang.Object

Encrypts or decrypts a data file using a stream cipher.

A file can be encrypted or decrypted by supplying a passphrase. The passphrase is hashed (using the SHA-1 algorithm) to generate a 128-bit encryption key, which is then used to encrypt or decrypt the contents of a specified file (using an AES-128 CFB-8 stream cipher algorithm).

Note: The key hashing method has been changed in revision 2.1 (2009-01-27). The '-p1' command line option is provided for backward compatibility, so that data files that were encrypted with earlier versions of this program can still be decrypted.

Source code:
http://david.tribble.com/src/java/tribble/crypto/FileEncrypter.java
Documentation:
http://david.tribble.com/docs/tribble/crypto/FileEncrypter.html

Since:
2005-03-26
Version:
$Revision: 2.4 $ $Date: 2009/04/05 17:00:23 $
Author:
David R. Tribble (david@tribble.com)
Copyright 2005-2009 by David R. Tribble, all rights reserved.
Permission is granted to any person or entity except those designated by the United States Department of State as a terrorist or terrorist government or agency, to use and distribute this source code provided that the original copyright notice remains present and unaltered.
See Also:
AESCipher, StreamCipherSpi

Field Summary
protected static java.lang.String HASH_ALG
          Hashing algorithm to use to convert a passphrase into a key.
protected static int KEY_LEN
          Stream cipher key size (in bytes).
static int MODE_CFB8
           
static int MODE_NONE
           
static int MODE_OFB128
           
static int RC_OKAY
          Exit code: Success.
static int RC_PASSWORD
          Exit code: Bad passphrase.
static int RC_READ
          Exit code: Can't read input.
static int RC_USAGE
          Exit code: Bad command usage.
static int RC_WRITE
          Exit code: Can't write output.
static boolean s_debugs
          Enable verbose debugging output.
 
Constructor Summary
FileEncrypter()
          Default constructor.
 
Method Summary
 long decrypt(java.io.InputStream in, java.io.OutputStream out, byte[] key, boolean hasIV, boolean squeezed, boolean base64, int mode)
          Decrypt an input stream.
static byte[] deriveKey_v1(java.lang.String pwd, int keyLen)
          Derive a cipher encryption key from a passphrase.
static byte[] deriveKey(byte[] pwd, int keyLen)
          Derive an encryption key from a passphrase.
static byte[] deriveKey(java.lang.String pwd, int keyLen)
          Derive a cipher encryption key from a passphrase.
 long encrypt(java.io.InputStream in, java.io.OutputStream out, byte[] key, boolean hasIV, boolean squeezed, boolean base64, int mode)
          Encrypt an input stream.
protected  void finalize()
          Finalization.
static void main(java.lang.String[] args)
          Encrypt or decrypt a data file.
 void reset()
          Wipe all sensitive information from this file encrypter/decrypter.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

MODE_NONE

public static final int MODE_NONE
See Also:
Constant Field Values

MODE_CFB8

public static final int MODE_CFB8
See Also:
Constant Field Values

MODE_OFB128

public static final int MODE_OFB128
See Also:
Constant Field Values

RC_OKAY

public static final int RC_OKAY
Exit code: Success.

See Also:
Constant Field Values

RC_READ

public static final int RC_READ
Exit code: Can't read input.

See Also:
Constant Field Values

RC_WRITE

public static final int RC_WRITE
Exit code: Can't write output.

See Also:
Constant Field Values

RC_PASSWORD

public static final int RC_PASSWORD
Exit code: Bad passphrase.

See Also:
Constant Field Values

RC_USAGE

public static final int RC_USAGE
Exit code: Bad command usage.

See Also:
Constant Field Values

HASH_ALG

protected static final java.lang.String HASH_ALG
Hashing algorithm to use to convert a passphrase into a key.

See Also:
Constant Field Values

KEY_LEN

protected static final int KEY_LEN
Stream cipher key size (in bytes).

See Also:
Constant Field Values

s_debugs

public static boolean s_debugs
Enable verbose debugging output.

Constructor Detail

FileEncrypter

public FileEncrypter()
Default constructor.

Since:
1.1, 2005-06-26
Method Detail

main

public static void main(java.lang.String[] args)
                 throws java.lang.Exception
Encrypt or decrypt a data file.

Usage

java tribble.crypto.FileEncrypter [-p passphrase] [-options...] file

Options:

-a
Encode/decode the data as base-64 ASCII text. By default, the encrypted data is binary. This option causes encrypted data to be written as ASCII text, using in a base-64 (radix-64) character encoding. For decryption, this option specifies that the input is in base-64 ASCII form.
-c
Compress the data (default). By default, the data is compressed (using the GZIP/PKZIP "deflate" compression algorithm) prior to being encrypted, and uncompressed after being decrypted. In addition to making the encrypted output smaller, this also makes it harder to crack the encryption.
-cfb8
Use a CFB-8 (Cipher FeedBack, 8-bit) ciphering mode. (This is the default.)
-ofb128
Use an OFB-128 (Output FeedBack, 128-bit) ciphering mode.
-D
Display verbose messages. These messages are written to the standard error output.
-d
Decrypt the file.
-e
Encrypt the file (the default).
-nc
Do not compress the data. This disables compression/decompression of the data (-c).
-o output-file
Specifies the file to write the encrypted output data to. If this option is not specified, the output is written to the standard output stream by default.
-p passphrase
Specifies the encryption passphrase. This is hashed into the symmetric cipher key used for encryption/decryption.
-pe var
Specifies an environment variable containing the encryption passphrase.
-pp name
Specifies a Java property name containing the encryption passphrase.
-p1
Specifies that the encryption passphrase is to be hashed into the symmetric cipher key using an algorithm that is backward compatible with revisions prior to 2.1.

If a passphrase is not specified, it will be read from the standard input.

Parameters:
args - Command line arguments.
Throws:
java.lang.Exception - Thrown if an I/O or encryption error occurs.
Since:
1.1, 2005-06-26

deriveKey

public static byte[] deriveKey(java.lang.String pwd,
                               int keyLen)
Derive a cipher encryption key from a passphrase. (Version 2.x.)

An encryption key is derived by hashing (using SHA-1) the text passphrase and extracting the upper bits of the hash.

Parameters:
pwd - A user-supplied passphrase.
keyLen - Length of the key to generate (in bytes).
Returns:
An encryption key derived from the passphrase.
Throws:
java.lang.RuntimeException - (unchecked) Thrown if the hashing (message digest) class could not be loaded.
Since:
1.2, 2005-06-28

deriveKey_v1

public static byte[] deriveKey_v1(java.lang.String pwd,
                                  int keyLen)
Derive a cipher encryption key from a passphrase. (Version 1.x.)

Note: This method has been renamed as of revision 2.1, being replaced with a new algorithm used in method deriveKey().

An encryption key is derived by hashing (using SHA-1) the text passphrase and extracting the upper bits of the hash.

Parameters:
pwd - A user-supplied passphrase.
keyLen - Length of the key to generate (in bytes).
Returns:
An encryption key derived from the passphrase.
Throws:
java.lang.RuntimeException - (unchecked) Thrown if the hashing (message digest) class could not be loaded.
Since:
2.4, 2009-04-05

deriveKey

public static byte[] deriveKey(byte[] pwd,
                               int keyLen)
Derive an encryption key from a passphrase.

An encryption key is derived by hashing (using SHA-1) the text passphrase and extracting the upper bits of the hash.

Parameters:
pwd - A user-supplied text passphrase.
keyLen - Length of the key to generate (in bytes).
Returns:
An encryption key derived from the passphrase.
Throws:
java.lang.RuntimeException - (unchecked) Thrown if the hashing (message digest) class could not be loaded.
Since:
1.2, 2005-06-28

reset

public void reset()
Wipe all sensitive information from this file encrypter/decrypter.

Since:
1.1, 2005-06-26

encrypt

public long encrypt(java.io.InputStream in,
                    java.io.OutputStream out,
                    byte[] key,
                    boolean hasIV,
                    boolean squeezed,
                    boolean base64,
                    int mode)
             throws java.io.IOException,
                    java.security.InvalidKeyException
Encrypt an input stream.

Random IV bytes are prepended to the output stream to make it harder to crack the encryption. Note: Not using a random prepended IV severly compromises the security of the stream cipher. Likewise, no two messages (files) should ever be encrypted using the same passphrase+IV combination.

Stream Cipher - CFB-8 Encryption Mode

         Random +---------------+
         IV     | | | | | | | | |  (128 bits, 16 bytes)
                +---------------+
                        :
                        v
         State  +-------------+-+
         Block  | | | | | | | |C| <------+
                +-------------+-+        :
                 Si     :                :
                        :                :
     +---------------+  :                :
 Key | | | | | | | | |  :                :
     +---------------+  :                :
           :            v                :
           :    +===============+        :
           +--> [               ]        :
                [    Cipher     ]        :
                [               ]        :
                +===============+        :
                        :                :
                        v                :
      Encrypted +-------------+-+        :
        Block   |E| | | | | | | |        :
                +-------------+-+        :
                 :             Ei        :
                 v                      +-+     Encrypted
              [ XOR ] ----------------> |C| --> Output
                 ^                      +-+     Stream
                 :                       Ci
 Plaintext      +-+
 Input -------> |P|
 Stream         +-+
                 Pi 

The state block is initially filled with the IV. As each plaintext byte Pi is read from the input stream, the state block is encrypted using the encryption key to produce the next encryption keystream block Ei. The last byte of the keystream block is XORed with the plaintext input byte Pi to produce the output ciphertext byte Ci, which is written to the output stream. The encrypted byte Ci is then shifted into the state block, which prepares the state block for the next input byte Pi+1.

Stream Cipher - OFB-128 Encryption Mode

         Random +---------------+
         IV     | | | | | | | | |  (128 bits, 16 bytes)
                +---------------+
                        :
                        v
         State  +---------------+
         Block  | | | | | | | | | <---+
                +---------------+     :
                  Si    :             :
                        :             :
     +---------------+  :             :
 Key | | | | | | | | |  :             :
     +---------------+  :             :
           :            v             :
           :    +===============+     :
           +--> [               ]     :
                [    Cipher     ]     :
                [               ]     :
                +===============+     :
                        :             :
                        v             :
      Encrypted +---------------+     :
        Block   | | | | | | | | | ----+
                +---------------+
                  Ei    :
                        v        +-+-+-+-+-+-+-+-+
                     [ XOR ] --> | | | | | | |X|X| --> Output
                        ^        +-+-+-+-+-+-+-+-+     Stream
                        :          Ci
 Input          +-+-+-+-+-+-+-+-+
 Stream ------> | | | | | | |X|X|
                +-+-+-+-+-+-+-+-+
                  Pi 

The state block is initially filled with the IV. As each block of plaintext bytes Pi is read from the input stream, the state block is encrypted using the encryption key to produce the next encryption keystream block Ei. The bytes of the keystream block are XORed with the plaintext input bytes Pi to produce the output ciphertext bytes Ci, which are written to the output stream. The encrypted bytes Ei are then shifted into the state block, which prepares the state block for the next input block Pi+1.

Parameters:
in - A binary input stream to encrypt.
out - A binary output stream to write the encrypted data to.
key - Encryption key, which must be either 128, 192, or 256 bits (16, 24, or 32 bytes) long.
hasIV - If true, the encrypted output stream will have random IV bytes prepended to it, otherwise not.
squeezed - If true, the plaintext data from the input stream is compressed (using the ZIP "deflate" compression method) prior to being encrypted. This not only makes the resulting encrypted output stream smaller than the original input stream, it also makes it harder to crack the encrypted data using chosen plaintext attacks.
base64 - If true, the encrypted output data is written as base-64 (a.k.a. radix-64) ASCII text instead of as binary data. This character text data is suitable for inclusion in normal text and email documents.
mode - Ciphering mode to use, which is one of the MODE_XXX constants.
Returns:
Number of bytes encrypted.
Throws:
java.io.IOException - Thrown if either in or out is null.
java.security.InvalidKeyException - If key is not the correct length or otherwise invalid.
Since:
1.1, 2005-05-26

decrypt

public long decrypt(java.io.InputStream in,
                    java.io.OutputStream out,
                    byte[] key,
                    boolean hasIV,
                    boolean squeezed,
                    boolean base64,
                    int mode)
             throws java.io.IOException,
                    java.security.InvalidKeyException
Decrypt an input stream.

Random IV bytes may have been prepended to the output stream to make it harder to crack the encryption. Note: Not using a random prepended IV severly compromises the security of the stream cipher. Likewise, no two messages (files) should ever be encrypted using the same passphrase+IV combination.

Stream Cipher - CFB-8 Decryption Mode

The decryption algorithm is identical to the encryption algorithm.

         Random +---------------+
         IV     | | | | | | | | |  (128 bits, 16 bytes)
                +---------------+
                        :
                        v
         State  +-------------+-+
         Block  | | | | | | | |P| <------+
                +-------------+-+        :
                  Si    :                :
                        :                :
     +---------------+  :                :
 Key | | | | | | | | |  :                :
     +---------------+  :                :
           :            v                :
           :    +===============+        :
           +--> [               ]        :
                [    Cipher     ]        :
                [               ]        :
                +===============+        :
                        :                :
                        v                :
      Encrypted +-------------+-+        :
        Block   | | | | | | | |E|        :
                +-------------+-+        :
                 :             Ei        :
                 v                  +-+  :      Decrypted
              [ XOR ] ------------> |P| ------> Output
                 ^                  +-+  :      Stream
                 :                   Pi  :
 Encrypted      +-+                      :
 Input -------> |C| ---------------------+
 Stream         +-+
                 Ci 

The state block is initially filled with the IV. As each ciphertext byte Ci is read from the input stream, the state block is encrypted using the encryption key to produce the next encryption keystream block Ei. The last byte of the keystream block is XORed with the ciphertext input byte Ci to produce the output plaintext byte Pi, which is written to the output stream. The encrypted byte Ci is then shifted into the state block, which prepares the state block for the next input byte Ci+1.

Stream Cipher - OFB-128 Decryption Mode

The decryption algorithm is identical to the encryption algorithm.

         Random +---------------+
         IV     | | | | | | | | |  (128 bits, 16 bytes)
                +---------------+
                        :
                        v
         State  +---------------+
         Block  | | | | | | | | | <---+
                +---------------+     :
                  Si    :             :
                        :             :
     +---------------+  :             :
 Key | | | | | | | | |  :             :
     +---------------+  :             :
           :            v             :
           :    +===============+     :
           +--> [               ]     :
                [    Cipher     ]     :
                [               ]     :
                +===============+     :
                        :             :
                        v             :
      Encrypted +---------------+     :
        Block   | | | | | | | | | ----+
                +---------------+
                  Ei    :
                        v        +-+-+-+-+-+-+-+-+
                     [ XOR ] --> | | | | | | |X|X| --> Output
                        ^        +-+-+-+-+-+-+-+-+     Stream
                        :          Pi
 Input          +-+-+-+-+-+-+-+-+
 Stream ------> | | | | | | |X|X|
                +-+-+-+-+-+-+-+-+
                  Ci 

The state block is initially filled with the IV. As each block of ciphertext bytes Ci is read from the input stream, the state block is encrypted using the encryption key to produce the next encryption keystream block Ei. The bytes of the keystream block are XORed with the ciphertext input bytes Ci to produce the output plaintext bytes Pi, which are written to the output stream. The encrypted bytes Ei are then shifted into the state block, which prepares the state block for the next input block Ci+1.

Parameters:
in - A binary input stream to decrypt.
out - A binary output stream to write the decrypted data to.
key - Encryption key, which must be either 128, 192, or 256 bits (16, 24, or 32 bytes) long.
hasIV - If true, the encrypted input stream has random IV bytes prepended to it, otherwise not.
squeezed - If true, the decrypted data from the input stream is decompressed (using the ZIP "inflate" compression method) after being decrypted.
base64 - If true, the encrypted input data is read as base-64 (a.k.a. radix-64) ASCII text instead of as binary data.
mode - Ciphering mode to use, which is one of the MODE_XXX constants.
Returns:
Number of bytes encrypted.
Throws:
java.io.IOException - Thrown if either in or out is null.
java.security.InvalidKeyException - If key is not the correct length or otherwise invalid.
Since:
1.1, 2005-05-26

finalize

protected void finalize()
                 throws java.lang.Throwable
Finalization. Wipes all sensitive information from this file encrypter/decrypter.

Overrides:
finalize in class java.lang.Object
Throws:
java.lang.Throwable
Since:
1.1, 2005-03-30
See Also:
reset()