/* * Copyright (C) 2011-2012 Intel Corporation * All rights reserved. */ package com.intel.mtwilson.crypto; import com.intel.dcsg.cpg.crypto.CryptographyException; import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; /** * This utility class includes methods for encrypting/decrypting fields in our * database tables using AES-128. This class assumes the use of CBC mode and * PKCS#5 padding. * * If you need to generate a new secret key from a password, try something like this: * SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); * KeySpec spec = new PBEKeySpec("password".toCharArray(), salt_byteArray, ITERATIONS(65536), KEYLEN_BITS(128)); * SecretKey tmp = factory.generateSecret (spec); * SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); * * Or if you want to generate a new random key, call the generateKey() method. * SecretKey skey = Aes128.generateKey(); * * To simplify usage, this class wraps all cryptographic exceptions with a single CryptographyException class. * The original exceptions are available via the getCause() method of CryptographyException. * * The encryptString and decryptString methods use the UTF-8 character set and Base64 encoding. * * @author jbuhacoff */ public class Aes128 { private SecretKey secretKey; private static int KEY_LENGTH = 128; private static int BLOCK_SIZE = 16; // KEY_LENGTH / 8 private Cipher cipher; public Aes128(byte[] secretKeyAes128) throws CryptographyException { try { cipher = Cipher.getInstance ("AES/CBC/PKCS5Padding"); secretKey = new SecretKeySpec(secretKeyAes128, "AES"); } catch(NoSuchAlgorithmException e) { throw new CryptographyException(e); } catch(NoSuchPaddingException e) { throw new CryptographyException(e); } } public Aes128(SecretKey secretKeyAes128) throws CryptographyException { try { cipher = Cipher.getInstance ("AES/CBC/PKCS5Padding"); secretKey = secretKeyAes128; } catch(NoSuchAlgorithmException e) { throw new CryptographyException(e); } catch(NoSuchPaddingException e) { throw new CryptographyException(e); } } public synchronized byte[] encrypt(byte[] plaintext) throws CryptographyException { try { cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] iv = cipher.getIV(); byte[] ciphertext = cipher.doFinal(plaintext); return concat(iv, ciphertext); } catch(InvalidKeyException e) { throw new CryptographyException(e); } catch(IllegalBlockSizeException e) { throw new CryptographyException(e); } catch(BadPaddingException e) { throw new CryptographyException(e); } } public String encryptString(String plaintext) throws CryptographyException { try { return Base64.encodeBase64String(encrypt(plaintext.getBytes("UTF-8"))); } catch (UnsupportedEncodingException e) { throw new CryptographyException(e); } } public synchronized byte[] decrypt(byte[] ciphertext) throws CryptographyException { try { cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(ciphertext, 0, BLOCK_SIZE)); return cipher.doFinal(ciphertext, BLOCK_SIZE, ciphertext.length - BLOCK_SIZE); // skip the first 16 bytes (IV) } catch(InvalidKeyException e) { throw new CryptographyException(e); } catch(IllegalBlockSizeException e) { throw new CryptographyException(e); } catch(BadPaddingException e) { throw new CryptographyException(e); } catch(InvalidAlgorithmParameterException e) { throw new CryptographyException(e); } } public String decryptString(String ciphertext) throws CryptographyException { try { return new String(decrypt(Base64.decodeBase64(ciphertext)), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new CryptographyException(e); } } private byte[] concat(byte[] a, byte[] b) { byte[] result = new byte[a.length + b.length]; System.arraycopy(a, 0, result, 0, a.length); System.arraycopy(b, 0, result, a.length, b.length); return result; } public static SecretKey generateKey() throws CryptographyException { try { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(KEY_LENGTH); SecretKey skey = kgen.generateKey(); return skey; } catch(NoSuchAlgorithmException e) { throw new CryptographyException(e); } } }