diff options
author | David Hook <dgh@cryptoworkshop.com> | 2013-05-31 11:07:45 +0400 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2013-05-31 11:07:45 +0400 |
commit | 2b976f5364cfdbc37d3086019d93483c983eb80b (patch) | |
tree | cb846af3fd1d43f9c2562a1fb2d06b997ad8f229 /core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java | |
parent | 5f714bd92fbd780d22406f4bc3681be005f6f04a (diff) |
initial reshuffle
Diffstat (limited to 'core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java')
-rw-r--r-- | core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java b/core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java new file mode 100644 index 00000000..16989971 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java @@ -0,0 +1,419 @@ +package org.bouncycastle.crypto.examples; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.security.SecureRandom; + +import org.bouncycastle.crypto.CryptoException; +import org.bouncycastle.crypto.KeyGenerationParameters; +import org.bouncycastle.crypto.engines.DESedeEngine; +import org.bouncycastle.crypto.generators.DESedeKeyGenerator; +import org.bouncycastle.crypto.modes.CBCBlockCipher; +import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; +import org.bouncycastle.crypto.params.DESedeParameters; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.util.encoders.Hex; + +/** + * DESExample is a simple DES based encryptor/decryptor. + * <p> + * The program is command line driven, with the input + * and output files specified on the command line. + * <pre> + * java org.bouncycastle.crypto.examples.DESExample infile outfile [keyfile] + * </pre> + * A new key is generated for each encryption, if key is not specified, + * then the example will assume encryption is required, and as output + * create deskey.dat in the current directory. This key is a hex + * encoded byte-stream that is used for the decryption. The output + * file is Hex encoded, 60 characters wide text file. + * <p> + * When encrypting; + * <ul> + * <li>the infile is expected to be a byte stream (text or binary) + * <li>there is no keyfile specified on the input line + * </ul> + * <p> + * When decrypting; + * <li>the infile is expected to be the 60 character wide base64 + * encoded file + * <li>the keyfile is expected to be a base64 encoded file + * <p> + * This example shows how to use the light-weight API, DES and + * the filesystem for message encryption and decryption. + * + */ +public class DESExample extends Object +{ + // Encrypting or decrypting ? + private boolean encrypt = true; + + // To hold the initialised DESede cipher + private PaddedBufferedBlockCipher cipher = null; + + // The input stream of bytes to be processed for encryption + private BufferedInputStream in = null; + + // The output stream of bytes to be procssed + private BufferedOutputStream out = null; + + // The key + private byte[] key = null; + + /* + * start the application + */ + public static void main(String[] args) + { + boolean encrypt = true; + String infile = null; + String outfile = null; + String keyfile = null; + + if (args.length < 2) + { + DESExample de = new DESExample(); + System.err.println("Usage: java "+de.getClass().getName()+ + " infile outfile [keyfile]"); + System.exit(1); + } + + keyfile = "deskey.dat"; + infile = args[0]; + outfile = args[1]; + + if (args.length > 2) + { + encrypt = false; + keyfile = args[2]; + } + + DESExample de = new DESExample(infile, outfile, keyfile, encrypt); + de.process(); + } + + // Default constructor, used for the usage message + public DESExample() + { + } + + /* + * Constructor, that takes the arguments appropriate for + * processing the command line directives. + */ + public DESExample( + String infile, + String outfile, + String keyfile, + boolean encrypt) + { + /* + * First, determine that infile & keyfile exist as appropriate. + * + * This will also create the BufferedInputStream as required + * for reading the input file. All input files are treated + * as if they are binary, even if they contain text, it's the + * bytes that are encrypted. + */ + this.encrypt = encrypt; + try + { + in = new BufferedInputStream(new FileInputStream(infile)); + } + catch (FileNotFoundException fnf) + { + System.err.println("Input file not found ["+infile+"]"); + System.exit(1); + } + + try + { + out = new BufferedOutputStream(new FileOutputStream(outfile)); + } + catch (IOException fnf) + { + System.err.println("Output file not created ["+outfile+"]"); + System.exit(1); + } + + if (encrypt) + { + try + { + /* + * The process of creating a new key requires a + * number of steps. + * + * First, create the parameters for the key generator + * which are a secure random number generator, and + * the length of the key (in bits). + */ + SecureRandom sr = null; + try + { + sr = new SecureRandom(); + /* + * This following call to setSeed() makes the + * initialisation of the SecureRandom object + * _very_ fast, but not secure AT ALL. + * + * Remove the line, recreate the class file and + * then run DESExample again to see the difference. + * + * The initialisation of a SecureRandom object + * can take 5 or more seconds depending on the + * CPU that the program is running on. That can + * be annoying during unit testing. + * -- jon + */ + sr.setSeed("www.bouncycastle.org".getBytes()); + } + catch (Exception nsa) + { + System.err.println("Hmmm, no SHA1PRNG, you need the "+ + "Sun implementation"); + System.exit(1); + } + KeyGenerationParameters kgp = new KeyGenerationParameters( + sr, + DESedeParameters.DES_EDE_KEY_LENGTH*8); + + /* + * Second, initialise the key generator with the parameters + */ + DESedeKeyGenerator kg = new DESedeKeyGenerator(); + kg.init(kgp); + + /* + * Third, and finally, generate the key + */ + key = kg.generateKey(); + + /* + * We can now output the key to the file, but first + * hex encode the key so that we can have a look + * at it with a text editor if we so desire + */ + BufferedOutputStream keystream = + new BufferedOutputStream(new FileOutputStream(keyfile)); + byte[] keyhex = Hex.encode(key); + keystream.write(keyhex, 0, keyhex.length); + keystream.flush(); + keystream.close(); + } + catch (IOException createKey) + { + System.err.println("Could not decryption create key file "+ + "["+keyfile+"]"); + System.exit(1); + } + } + else + { + try + { + // read the key, and decode from hex encoding + BufferedInputStream keystream = + new BufferedInputStream(new FileInputStream(keyfile)); + int len = keystream.available(); + byte[] keyhex = new byte[len]; + keystream.read(keyhex, 0, len); + key = Hex.decode(keyhex); + } + catch (IOException ioe) + { + System.err.println("Decryption key file not found, "+ + "or not valid ["+keyfile+"]"); + System.exit(1); + } + } + } + + private void process() + { + /* + * Setup the DESede cipher engine, create a PaddedBufferedBlockCipher + * in CBC mode. + */ + cipher = new PaddedBufferedBlockCipher( + new CBCBlockCipher(new DESedeEngine())); + + /* + * The input and output streams are currently set up + * appropriately, and the key bytes are ready to be + * used. + * + */ + + if (encrypt) + { + performEncrypt(key); + } + else + { + performDecrypt(key); + } + + // after processing clean up the files + try + { + in.close(); + out.flush(); + out.close(); + } + catch (IOException closing) + { + + } + } + + /* + * This method performs all the encryption and writes + * the cipher text to the buffered output stream created + * previously. + */ + private void performEncrypt(byte[] key) + { + // initialise the cipher with the key bytes, for encryption + cipher.init(true, new KeyParameter(key)); + + /* + * Create some temporary byte arrays for use in + * encryption, make them a reasonable size so that + * we don't spend forever reading small chunks from + * a file. + * + * There is no particular reason for using getBlockSize() + * to determine the size of the input chunk. It just + * was a convenient number for the example. + */ + // int inBlockSize = cipher.getBlockSize() * 5; + int inBlockSize = 47; + int outBlockSize = cipher.getOutputSize(inBlockSize); + + byte[] inblock = new byte[inBlockSize]; + byte[] outblock = new byte[outBlockSize]; + + /* + * now, read the file, and output the chunks + */ + try + { + int inL; + int outL; + byte[] rv = null; + while ((inL=in.read(inblock, 0, inBlockSize)) > 0) + { + outL = cipher.processBytes(inblock, 0, inL, outblock, 0); + /* + * Before we write anything out, we need to make sure + * that we've got something to write out. + */ + if (outL > 0) + { + rv = Hex.encode(outblock, 0, outL); + out.write(rv, 0, rv.length); + out.write('\n'); + } + } + + try + { + /* + * Now, process the bytes that are still buffered + * within the cipher. + */ + outL = cipher.doFinal(outblock, 0); + if (outL > 0) + { + rv = Hex.encode(outblock, 0, outL); + out.write(rv, 0, rv.length); + out.write('\n'); + } + } + catch (CryptoException ce) + { + + } + } + catch (IOException ioeread) + { + ioeread.printStackTrace(); + } + } + + /* + * This method performs all the decryption and writes + * the plain text to the buffered output stream created + * previously. + */ + private void performDecrypt(byte[] key) + { + // initialise the cipher for decryption + cipher.init(false, new KeyParameter(key)); + + /* + * As the decryption is from our preformatted file, + * and we know that it's a hex encoded format, then + * we wrap the InputStream with a BufferedReader + * so that we can read it easily. + */ + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + + /* + * now, read the file, and output the chunks + */ + try + { + int outL; + byte[] inblock = null; + byte[] outblock = null; + String rv = null; + while ((rv = br.readLine()) != null) + { + inblock = Hex.decode(rv); + outblock = new byte[cipher.getOutputSize(inblock.length)]; + + outL = cipher.processBytes(inblock, 0, inblock.length, + outblock, 0); + /* + * Before we write anything out, we need to make sure + * that we've got something to write out. + */ + if (outL > 0) + { + out.write(outblock, 0, outL); + } + } + + try + { + /* + * Now, process the bytes that are still buffered + * within the cipher. + */ + outL = cipher.doFinal(outblock, 0); + if (outL > 0) + { + out.write(outblock, 0, outL); + } + } + catch (CryptoException ce) + { + + } + } + catch (IOException ioeread) + { + ioeread.printStackTrace(); + } + } + +} + |