1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
| * Copyright (c) 2000 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 2nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book (recommended),
* visit http://www.davidflanagan.com/javaexamples2.
*/
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
/**
* This class defines methods for encrypting and decrypting using the Triple DES
* algorithm and for generating, reading and writing Triple DES keys. It also
* defines a main() method that allows these methods to be used from the command
* line.
*/
public class TripleDES {
/**
* The program. The first argument must be -e, -d, or -g to encrypt,
* decrypt, or generate a key. The second argument is the name of a file
* from which the key is read or to which it is written for -g. The -e and
* -d arguments cause the program to read from standard input and encrypt or
* decrypt to standard output.
*/
public static void main(String[] args) {
try {
// Check to see whether there is a provider that can do TripleDES
// encryption. If not, explicitly install the SunJCE provider.
try {
Cipher c = Cipher.getInstance("DESede");
} catch (Exception e) {
// An exception here probably means the JCE provider hasn't
// been permanently installed on this system by listing it
// in the $JAVA_HOME/jre/lib/security/java.security file.
// Therefore, we have to install the JCE provider explicitly.
System.err.println("Installing SunJCE provider.");
Provider sunjce = new com.sun.crypto.provider.SunJCE();
Security.addProvider(sunjce);
}
// This is where we'll read the key from or write it to
File keyfile = new File(args[1]);
// Now check the first arg to see what we're going to do
if (args[0].equals("-g")) { // Generate a key
System.out.print("Generating key. This may take some time...");
System.out.flush();
SecretKey key = generateKey();
writeKey(key, keyfile);
System.out.println("done.");
System.out.println("Secret key written to " + args[1]
+ ". Protect that file carefully!");
} else if (args[0].equals("-e")) { // Encrypt stdin to stdout
SecretKey key = readKey(keyfile);
encrypt(key, System.in, System.out);
} else if (args[0].equals("-d")) { // Decrypt stdin to stdout
SecretKey key = readKey(keyfile);
decrypt(key, System.in, System.out);
}
} catch (Exception e) {
System.err.println(e);
System.err.println("Usage: java " + TripleDES.class.getName()
+ " -d|-e|-g <keyfile>");
}
}
/** Generate a secret TripleDES encryption/decryption key */
public static SecretKey generateKey() throws NoSuchAlgorithmException {
// Get a key generator for Triple DES (a.k.a DESede)
KeyGenerator keygen = KeyGenerator.getInstance("DESede");
keygen.init(168);
// Use it to generate a key
return keygen.generateKey();
}
/** Save the specified TripleDES SecretKey to the specified file */
public static void writeKey(SecretKey key, File f) throws IOException,
NoSuchAlgorithmException, InvalidKeySpecException {
// Convert the secret key to an array of bytes like this
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");
DESedeKeySpec keyspec = (DESedeKeySpec) keyfactory.getKeySpec(key,
DESedeKeySpec.class);
byte[] rawkey = keyspec.getKey();
// Write the raw key to the file
FileOutputStream out = new FileOutputStream(f);
out.write(rawkey);
out.close();
}
/** Read a TripleDES secret key from the specified file */
public static SecretKey readKey(File f) throws IOException,
NoSuchAlgorithmException, InvalidKeyException,
InvalidKeySpecException {
// Read the raw bytes from the keyfile
DataInputStream in = new DataInputStream(new FileInputStream(f));
byte[] rawkey = new byte[(int) f.length()];
in.readFully(rawkey);
in.close();
// Convert the raw bytes to a secret key like this
DESedeKeySpec keyspec = new DESedeKeySpec(rawkey);
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");
SecretKey key = keyfactory.generateSecret(keyspec);
return key;
}
/**
* Use the specified TripleDES key to encrypt bytes from the input stream
* and write them to the output stream. This method uses CipherOutputStream
* to perform the encryption and write bytes at the same time.
*/
public static void encrypt(SecretKey key, InputStream in, OutputStream out)
throws NoSuchAlgorithmException, InvalidKeyException,
NoSuchPaddingException, IOException {
// Create and initialize the encryption engine
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, key);
// Create a special output stream to do the work for us
CipherOutputStream cos = new CipherOutputStream(out, cipher);
ici
// Read from the input and write to the encrypting output stream
byte[] buffer = new byte[2048];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
cos.write(buffer, 0, bytesRead);
}
cos.close();
// For extra security, don't leave any plaintext hanging around memory.
java.util.Arrays.fill(buffer, (byte) 0);
}
/**
* Use the specified TripleDES key to decrypt bytes ready from the input
* stream and write them to the output stream. This method uses uses Cipher
* directly to show how it can be done without CipherInputStream and
* CipherOutputStream.
*/
public static void decrypt(SecretKey key, InputStream in, OutputStream out)
throws NoSuchAlgorithmException, InvalidKeyException, IOException,
IllegalBlockSizeException, NoSuchPaddingException,
BadPaddingException {
// Create and initialize the decryption engine
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.DECRYPT_MODE, key);
// Read bytes, decrypt, and write them out.
byte[] buffer = new byte[2048];
int bytesRead;
ici
while ((bytesRead = in.read(buffer)) != -1) {
out.write(cipher.update(buffer, 0, bytesRead));
}
// Write out the final bunch of decrypted bytes
out.write(cipher.doFinal());
out.flush();
}
} |