Return to Snippet

Revision: 15380
at July 2, 2009 20:22 by geekiuscaesar


Initial Code
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Cryptor {
	private static byte[] r = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6,
			0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF };
	private static byte[] header = new byte[] { 0x1, 0x2, 0x2 };
	private static int headerlen = 3;
	private static byte[] iv = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6,
			0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF };
	private static int shalen = 32;

	private SecretKeySpec secretKeySpec = new SecretKeySpec(r, "AES");
	private IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

	public byte[] encrypt(String plaintext) throws IOException,
			NoSuchAlgorithmException, NoSuchPaddingException,
			InvalidKeyException, InvalidAlgorithmParameterException,
			IllegalBlockSizeException, BadPaddingException {
		byte[] text = plaintext.getBytes();

		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		stream.write(header);

		// Encrypt text
		Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
		cipher.init(Cipher.ENCRYPT_MODE, this.secretKeySpec,
				this.ivParameterSpec);
		stream.write(cipher.doFinal(text));

		// Hash text
		MessageDigest digest = MessageDigest.getInstance("SHA-256");
		digest.update(text);
		stream.write(digest.digest());

		byte[] bytes = stream.toByteArray();
		stream.close();
		return bytes;
	}

	public String decrypt(byte[] bytes) throws NoSuchAlgorithmException,
			NoSuchPaddingException, InvalidKeyException,
			InvalidAlgorithmParameterException, IllegalBlockSizeException,
			BadPaddingException, InvalidHashException, InvalidHeaderException {
		ByteBuffer buf = ByteBuffer.wrap(bytes);

		byte[] header = new byte[headerlen];
		buf.get(header);
		if (!Arrays.equals(header, Cryptor.header))
			throw new InvalidHeaderException(
					"Header is not valid. Decryption aborted.");

		int aeslen = bytes.length - shalen - headerlen;
		byte[] aes = new byte[aeslen];
		buf.get(aes);

		// Decrypt text
		Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
		cipher.init(Cipher.DECRYPT_MODE, this.secretKeySpec,
				this.ivParameterSpec);
		byte[] text = cipher.doFinal(aes);

		// Compute hash
		MessageDigest digest = MessageDigest.getInstance("SHA-256");
		digest.update(text);
		byte[] hash = digest.digest();

		byte[] hash2 = new byte[shalen];
		buf.get(hash2);

		if (!Arrays.equals(hash, hash2))
			throw new InvalidHashException(
					"Verification failed. Decryption aborted.");

		return new String(text);
	}

	class InvalidHeaderException extends Exception {
		private static final long serialVersionUID = 1L;

		public InvalidHeaderException(String string) {
			super(string);
		}
	}

	class InvalidHashException extends Exception {
		private static final long serialVersionUID = 1L;

		public InvalidHashException(String string) {
			super(string);
		}
	}

	public static void main(String[] args) throws Exception {
		Cryptor c = new Cryptor();

		System.out
				.println(c
						.decrypt(c
								.encrypt("String encryption/decryption with integrity check. In a real world example, the key should be kept secret and the IV should be unique.")));

	}

}

Initial URL


Initial Description


Initial Title
AES encrypter/decrypter with check in CFB mode in Java using JCE

Initial Tags


Initial Language
Java