Encrypting/decrypting using Rijndael (AES)

Rijndael has been selected as the proposed AES algorithm (check out http://csrc.nist.gov/encryption/aes/aesfact.html. You can find more information of Rijdael on the homepage of the designer(s).

Main.java:

import javax.crypto.spec.*;
import java.security.*;
import javax.crypto.*;
import org.bouncycastle.util.encoders.Hex;
 
public class Main
{
   public static void main(String []args) throws Exception {
      String toEncrypt = "The shorter you live, the longer you're dead!";
 
      System.out.println("Encrypting...");
      byte[] encrypted = encrypt(toEncrypt, "password");
 
      System.out.println("Decrypting...");
      String decrypted = decrypt(encrypted, "password");
    
      System.out.println("Decrypted text: " + decrypted);
   } 
 
   public static byte[] encrypt(String toEncrypt, String key) throws Exception {
      // create a binary key from the argument key (seed)
      SecureRandom sr = new SecureRandom(key.getBytes());
      KeyGenerator kg = KeyGenerator.getInstance("Rijndael");
      kg.init(sr);
      SecretKey sk = kg.generateKey();
 
      // create an instance of cipher
      Cipher cipher = Cipher.getInstance("Rijndael");
 
      // initialize the cipher with the key
      cipher.init(Cipher.ENCRYPT_MODE, sk);
 
      // enctypt!
      byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
 
      return encrypted;
   }
 
   public static String decrypt(byte[] toDecrypt, String key) throws Exception {
      // create a binary key from the argument key (seed)
      SecureRandom sr = new SecureRandom(key.getBytes());
      KeyGenerator kg = KeyGenerator.getInstance("Rijndael");
      kg.init(sr);
      SecretKey sk = kg.generateKey();
 
      // do the decryption with that key
      Cipher cipher = Cipher.getInstance("Rijndael");
      cipher.init(Cipher.DECRYPT_MODE, sk);
      byte[] decrypted = cipher.doFinal(toDecrypt);
 
      return new String(decrypted);
   }
}

(tested with the BouncyCastle JCE provider, http://www.bouncycastle.org)

What is a message digest?

A messagedigest is a sortof a fingerprint for a chunk of data. If only one bit of that data has changed, the message digest algorithm would generate a different fingerprint. This allows you to determine if, for example during network transmission of data, that data has changed. You cannot deduce the original contents of a message from a message digest.

A common example is the use of a password system, where passwords are stored as messagedigests. When you logon to the system, it will compute a messagedigest of the password you’ve typed in and compare it with the messagedigest that is stored in the username/password file.

There are two popular types of message digest algorithms: MD5 and SHA.

For example, the MD5 message digest for the plaintext The sun is green and the grass shines is (in hex) 470DB3B23F9D445446DFCE291C9F17AB.

For information on how to generate a messagedigest in Java, look at this answer.

Encrypting/decrypting using Skipjack

Check out the following pages for more infomration on Skipjack encryption:
http://www.tropsoft.com/strongenc/skipjack.htm
http://www.cs.technion.ac.il/~biham/Reports/SkipJack/note1.html

Main.java:

import javax.crypto.spec.*;
import java.security.*;
import javax.crypto.*;
import org.bouncycastle.util.encoders.Hex;
 
public class Main
{
   public static void main(String []args) throws Exception {
      String toEncrypt = "The shorter you live, the longer you're dead!";
 
      System.out.println("Encrypting...");
      byte[] encrypted = encrypt(toEncrypt, "password");
 
      System.out.println("Decrypting...");
      String decrypted = decrypt(encrypted, "password");
    
      System.out.println("Decrypted text: " + decrypted);
   } 
 
   public static byte[] encrypt(String toEncrypt, String key) throws Exception {
      // create a binary key from the argument key (seed)
      SecureRandom sr = new SecureRandom(key.getBytes());
      KeyGenerator kg = KeyGenerator.getInstance("Skipjack");
      kg.init(sr);
      SecretKey sk = kg.generateKey();
 
      // create an instance of cipher
      Cipher cipher = Cipher.getInstance("Skipjack");
 
      // initialize the cipher with the key
      cipher.init(Cipher.ENCRYPT_MODE, sk);
 
      // enctypt!
      byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
 
      return encrypted;
   }
 
   public static String decrypt(byte[] toDecrypt, String key) throws Exception {
      // create a binary key from the argument key (seed)
      SecureRandom sr = new SecureRandom(key.getBytes());
      KeyGenerator kg = KeyGenerator.getInstance("Skipjack");
      kg.init(sr);
      SecretKey sk = kg.generateKey();
 
      // do the decryption with that key
      Cipher cipher = Cipher.getInstance("Skipjack");
      cipher.init(Cipher.DECRYPT_MODE, sk);
      byte[] decrypted = cipher.doFinal(toDecrypt);
 
      return new String(decrypted);
   }
}

(tested with the BouncyCastle JCE provider, http://www.bouncycastle.org)

Generating a MD5 message digest

What MD5 is and why it it important is explained well on the following page:

http://www.enteract.com/~lspitz/md5.html

A digest has two properties:
- it is computationally infeasible to find another input string that generates the same digest
- the digest does not reveal anything about the input that was used to generate it.

The engine class MessageDigest provides the functionality of several
types of cryptographic algorithms. What algorithms are available depends
on the provider you are using. For example, Sun (the default provider) supplies
implementations of the MD5 and SHA-1 message digest algorithms. Other providers
may have their own implementation of these algorithms or other algorithms.

As an implementation is supplied by Sun in the JDK, you don’t even have to
install another provider. Here’s is an example using the implementation by Cryptix:

 
import cryptix.util.core.Hex;
import cryptix.util.test.BaseTest;
import java.security.MessageDigest;
 
class TestMD5 
{
   public static void main(String[] args) {
      String plaintext = "The sun is green and the grass shines";

      MessageDigest md = null;
      try {
         // first create an instance, given the provider
         md = MessageDigest.getInstance("MD5", "Cryptix");
      }
      catch(java.security.NoSuchProviderException e) {
         System.out.println(e);
         System.exit(1);
      }
      catch(java.security.NoSuchAlgorithmException e) {
         System.out.println(e);
         System.exit(1);
      }

      md.reset();

      // call the update method one or more times 
      // (useful when you don't know the size of your data, eg. stream)
      md.update(plaintext.getBytes());

      // now calculate the hash
      byte[] hash = md.digest();

      System.out.println("Plaintext:nt" + plaintext + "n");
      // Hex is a function provided by Cryptix to produce a nice output
      System.out.println("Message Digest:nt" + Hex.toString(hash));
   }
}

generates the output:

 
Plaintext:
	The sun is green and the grass shines

Message Digest:
	470DB3B23F9D445446DFCE291C9F17AB

What is asymmetric cryptography?

The problem with symmetric cryptography is how to distribute the secret key to the involved parties. In assymetric cryptography (also: public key cryptography), algorithms use two different keys: a private and a public one. A message encrypted with a private key can be decrypted with its public key (and in some cases vice versa). The owner of the key pair holds the private key, and may distribute the public key to anyone. Someone who wants to send a secret message uses the public key of the intended receiver to encrypt it. Only the receiver holds the private key and can decrypt it.

Compared to secret key encryption, public key encryption is slow.

A popular assymetric cryptographic algorithm is RSA, used in PGP.

What is a message authentication code (MAC)?

A MAC is a type of a message digest but that requires a key. It uses that key to encrypt the hash. Only the receiver, who has access to that key, can decrypt the hash and verify whether the message has not been tampered with.

This is to solve the problem that a man-in-the-middle, one that spies the communication line, intercepts a message with a conventional message digest and then sends out another message with another message digest. The receiver is unable to know whether the whole thing comes from the original sender. If the sender and receiver would use a MAC utilizing a (secret) key, there would be no way for the man-in-the-middle to intercept and send out a new message as he doesn’t know the key.

The problem with MACs is that secret keys need to be shared between both parties.

A MAC works with available hashing methods (MD5 or SHA).

Programmatically generating a public and private key

Programmatically:

Main.java:

import javax.crypto.spec.*;
import java.security.*;
import javax.crypto.*;
import java.io.*;
 
public class Main
{
   public static void main(String []args) throws Exception {
      KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
      kpg.initialize(1024);
      KeyPair kp = kpg.genKeyPair();
 
      byte[] publicKey = kp.getPublic().getEncoded();
      byte[] privateKey = kp.getPrivate().getEncoded();
 
      FileOutputStream fos = new FileOutputStream("public.key");
      fos.write(publicKey);
      fos.close();
      fos = new FileOutputStream("private.key");
      fos.write(privateKey);
      fos.close();
   }
}

using keytool:

keytool -genkey -alias mykey -keysize 1024 -keyalg RSA