package info.junius.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class SymmetricStreamCipher {
// basics:
// text + key ==> cipher text
// cipher text + key ==> plain text
public static void main ( String[] args ) {
byte[] cipherText = null;
byte[] initVector = null;
byte[] rawKey = null;
// generate a key and a cipher and encrypt a document
try {
String plainText = "This is some top secret text!";
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
SecretKey key = keyGenerator.generateKey();
rawKey = key.getEncoded();
SecretKeySpec keySpecification = new SecretKeySpec(rawKey, "DES");
// des cipher with Cipher Feedback mode, 8 bit and pkcs5 padding scheme
Cipher cipher = Cipher.getInstance("DES/CFB8/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpecification, new SecureRandom());
// get input stream for string
InputStream is = new ByteArrayInputStream(plainText.getBytes());
// create output stream for cipher
OutputStream os = new ByteArrayOutputStream();
// create cipher input stream using plain text and cipher as input
CipherInputStream cis = new CipherInputStream(is, cipher);
// read from cipherinputstream and write to outputstream
byte[] cipherBytes = new byte[2];
int i = 0;
while ( (i = cis.read(cipherBytes)) != -1) {
os.write( cipherBytes, 0, i);
System.out.println(Arrays.toString( ((ByteArrayOutputStream)os).toByteArray()));
}
cis.close();
is.close();
os.close();
initVector = cipher.getIV();
cipherText = ((ByteArrayOutputStream)os).toByteArray();
// output
System.out.println("Cipher blocksize: " + cipher.getBlockSize());
System.out.println("Cipher algorithm: " + cipher.getAlgorithm());
System.out.println("Cipher output size: " + cipher.getOutputSize(plainText.length()));
System.out.println("Cipher parameters: " + cipher.getParameters());
System.out.println("Cipher provider: " + cipher.getProvider());
System.out.println("Plain text: " + plainText);
System.out.println("Cipher text: " + Arrays.toString(cipherText));
System.out.println("Initialisation vector: " + Arrays.toString(initVector));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// now decrypt the cipher using data created above, i.e. cipher, rawKey and initialisation vector
// also necessary to know:
// algorithm, mode, padding scheme, e.g. DES/CFB8/PKCS5Padding
try {
// create key specification
SecretKeySpec keySpecification = new SecretKeySpec(rawKey, "DES");
// initialisation vector as a parameter specification
IvParameterSpec iv = new IvParameterSpec(initVector);
// create cipher, same as for encryption
Cipher cipher = Cipher.getInstance("DES/CFB8/PKCS5Padding");
// initialise cipher
cipher.init(Cipher.DECRYPT_MODE, keySpecification, iv);
// get input stream for string
InputStream is = new ByteArrayInputStream(cipherText);
// create output stream for text
OutputStream os = new ByteArrayOutputStream();
// create cipher input stream using cipher text and cipher as input
CipherInputStream cis = new CipherInputStream(is, cipher);
// read from cipherinputstream and write to outputstream
byte[] cipherBytes = new byte[2];
int i = 0;
while ( (i = cis.read(cipherBytes)) != -1) {
os.write( cipherBytes, 0, i);
System.out.println(Arrays.toString( ((ByteArrayOutputStream)os).toByteArray()));
}
cis.close();
is.close();
os.close();
byte[] decrypted = ((ByteArrayOutputStream)os).toByteArray();
String decryptedText = new String(decrypted);
// output
System.out.println("Raw Key: " + Arrays.toString(rawKey));
System.out.println("Cipher blocksize: " + cipher.getBlockSize());
System.out.println("Cipher algorithm: " + cipher.getAlgorithm());
System.out.println("Cipher parameters: " + cipher.getParameters());
System.out.println("Cipher provider: " + cipher.getProvider());
System.out.println("Cipher text: " + Arrays.toString(cipherText));
System.out.println("Initialisation vector: " + Arrays.toString(initVector));
System.out.println("Decrypted text, bytes: " + Arrays.toString(decrypted));
System.out.println("Decrypted text: " + decryptedText);
System.out.println("******************************************************************");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}