analytics

Saturday, April 9, 2011

Advanced Encryption Standard (AES)

Advanced Encryption Standard

In cryptography, the Advanced Encryption Standard (AES) is a symmetric-key encryption standard adopted by the U.S. government. The standard comprises three block ciphers, AES-128, AES-192 and AES-256, adopted from a larger collection originally published as Rijndael. Each of these ciphers has a 128-bit block size, with key sizes of 128, 192 and 256 bits, respectively. The AES ciphers have been analyzed extensively and are now used worldwide, as was the case with its predecessor, the Data Encryption Standard (DES).

AES was announced by National Institute of Standards and Technology (NIST) as U.S. FIPS PUB 197 (FIPS 197) on November 26, 2001 after a 5-year standardization process in which fifteen competing designs were presented and evaluated before Rijndael was selected as the most suitable (see Advanced Encryption Standard process for more details). It became effective as a Federal government standard on May 26, 2002 after approval by the Secretary of Commerce. It is available in many different encryption packages. AES is the first publicly accessible and open cipher approved by the NSA for top secretinformation.

The Rijndael cipher was developed by two Belgian cryptographers, Joan Daemen and Vincent Rijmen, and submitted by them to the AES selection process. Rijndael is a wordplay based upon the names of the two inventors.

AES is based on a design principle known as a Substitution permutation network. It is fast in both software and hardware. Unlike its predecessor, DES, AES does not use a Feistel network.

AES has a fixed block size of 128 bits and a key size of 128, 192, or 256 bits, whereas Rijndael can be specified with block and key sizes in any multiple of 32 bits, with a minimum of 128 bits. The blocksize has a maximum of 256 bits, but the keysize has no theoretical maximum.

AES operates on a 4×4 matrix of bytes, termed the state (versions of Rijndael with a larger block size have additional columns in the state). Most AES calculations are done in a special finite field.

The AES cipher is specified as a number of repetitions of transformation rounds that convert the input plaintext into the final output of ciphertext. Each round consists of several processing steps, including one that depends on the encryption key. A set of reverse rounds are applied to transform ciphertext back into the original plaintext using the same encryption key.


Simple Data Encryption/Decryption Example with AES

For encryption we must use a secret key along with an algorithm. In the following example we use an algorithm called AES 128 and the bytes of the word "ThisIsASecretKey" as the secret key (the best secret key we found in this world).

AES algorithm can use a key of 128 bits (16 bytes * 8); so we selected that key.

package org.roy.crypto;


import java.security.*;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;

public class SimpleProtector {

private static final String ALGORITHM = "AES";

private static final byte[] keyValue =
new byte[] { 'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };

public static String encrypt(String valueToEnc) throws Exception {

Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
String encryptedValue = new BASE64Encoder().encode(encValue);
return encryptedValue;
}


public static String decrypt(String encryptedValue) throws Exception {

Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedValue);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}


private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
// SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
// key = keyFactory.generateSecret(new DESKeySpec(keyValue));
return key;
}
}

We use "generateKey()" method to generate a secret key for AES algorithm with a given key. You can change the used algorithm by changing this Key generation; the commented out code shows the use of DES algorithm (Data Encryption Standard). Following is a simple class to test the above implementation.

package org.roy.crypto;

public class TestSimpleProtector {

public static void main(String[] args) throws Exception {
String password = "mypassword";
String passwordEnc = SimpleProtector.encrypt(password);
String passwordDec = SimpleProtector.decrypt(passwordEnc);

System.out.println("Plain Text : " + password);
System.out.println("Encrypted : " + passwordEnc);
System.out.println("Decrypted : " + passwordDec);
}
}


Following is the output we got from above test; so you clearly see that the original text is reproduced after the decryption operation.

Plain Text : mypassword
Encrypted : sBhCap4urE50a/dGuhNgrw==
Decrypted : mypassword


Another Simple Example:

import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;

public class AES {

public static String asHex (byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}

return strbuf.toString();
}


public static void main(String[] args) throws Exception {

String message="AES still rocks!!";
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available

// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();

SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

// Instantiate the cipher
Cipher cipher = Cipher.getInstance("AES");

cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal((args.length == 0 ? message : args[0]).getBytes());
System.out.println("encrypted string: " + asHex(encrypted));


cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original = cipher.doFinal(encrypted);
String originalString = new String(original);
System.out.println("Original string: " + originalString + " " + asHex(original));
}
}


OUTPUT:

encrypted string: 91369a3b74c6feede0eff48fcf004f67d26cdd0b4907b44fd2147a4077ded0d1
Original string: AES still rocks!! 414553207374696c6c20726f636b732121

5 comments:

  1. Nice example, Thanks! BTW i like your fish.. :o)

    ReplyDelete
  2. I see that you have used BASE64Encoder()/BASE64Decoder() in the first example and in the second one you used asHex(). What is the difference between asHex and BASE64Encoder()/BASE64Decoder()?

    ReplyDelete
    Replies
    1. The difference between Base64 and hex is really just how bytes are represented. Hex will take two characters for each byte but Base64 takes 4 characters for every 3 bytes, so it's more efficient than hex.

      Delete
  3. thanks, it was very useful :-) :-)

    ReplyDelete