package org.openstack.atlas.util.b64aes;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.IllegalBlockSizeException;
import java.security.InvalidKeyException;
import javax.crypto.BadPaddingException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.util.Random;
public class Aes {
private static final int rivSize = 4;
private static final int PAGESIZE = 4096;
private static Random rnd = new Random();
private static final byte[] iv = new byte[]{111, -120, 13, -78,
123, 21, 81, -13,
12, -49, 124, 63,
13, 96, -54, 32};
public static SecretKey getAesKey(String key_str) throws
NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException {
SecretKey secret = new SecretKeySpec(md5sum(key_str), "AES");
return secret;
}
public static String b64encrypt(byte[] ptext, String key_str)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException, IOException {
byte[] ctext = encrypt(ptext, sha256(key_str));
return new String(Base64.encode(ctext, ctext.length));
}
public static byte[] encrypt(byte[] ptextBytes, byte[] keyBytes)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException,
IOException, IllegalBlockSizeException, BadPaddingException {
SecretKey key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
AlgorithmParameterSpec algoParamSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, algoParamSpec);
byte[] ptextWithRandomVector = injectVector(ptextBytes, rivSize);
return cipher.doFinal(ptextWithRandomVector);
}
public static byte[] b64decrypt(String b64ctext, String key_str)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeySpecException, BadPaddingException,
InvalidKeyException, IllegalBlockSizeException,
InvalidAlgorithmParameterException,
UnsupportedEncodingException,
PaddingException, IOException {
byte[] ctextBytes = b64ctext.getBytes("UTF-8");
byte[] ctext = Base64.decode(ctextBytes, ctextBytes.length);
return decrypt(ctext, sha256(key_str));
}
public static byte[] decrypt(byte[] ctextBytes, byte[] keyBytes)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeySpecException, BadPaddingException,
InvalidKeyException, IllegalBlockSizeException,
InvalidAlgorithmParameterException,
UnsupportedEncodingException,
PaddingException, IOException {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
AlgorithmParameterSpec algoPramSpec = new IvParameterSpec(iv);
SecretKey key = new SecretKeySpec(keyBytes,"AES");
cipher.init(Cipher.DECRYPT_MODE, key, algoPramSpec);
byte[] ptextBytes = cipher.doFinal(ctextBytes);
ptextBytes = removeVector(ptextBytes, rivSize);
return ptextBytes;
}
public static String b64decrypt_str(String b64ctext, String key_str)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeySpecException, BadPaddingException,
InvalidKeyException, IllegalBlockSizeException,
InvalidAlgorithmParameterException,
UnsupportedEncodingException,
PaddingException, IOException {
return new String(b64decrypt(b64ctext, key_str),"utf-8");
}
public static byte[] sha256(String str_in) throws NoSuchAlgorithmException,
UnsupportedEncodingException {
return sha256(str_in.getBytes("UTF-8"));
}
public static byte[] sha256(byte[] bytesIn) throws NoSuchAlgorithmException {
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
sha256.reset();
sha256.update(bytesIn);
return sha256.digest();
}
private static byte[] md5sum(String str_in) throws NoSuchAlgorithmException, UnsupportedEncodingException {
return md5sum(str_in.getBytes("UTF-8"));
}
private static byte[] md5sum(byte[] bytesIn) throws NoSuchAlgorithmException {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.reset();
md5.update(bytesIn);
return md5.digest();
}
private static byte[] injectVector(byte[] bytes, int vLength) throws IOException {
ByteArrayOutputStream bas = new ByteArrayOutputStream(PAGESIZE);
byte[] vector = new byte[vLength];
rnd.nextBytes(vector);
bas.write(vector);
bas.write(bytes);
return bas.toByteArray();
}
private static byte[] removeVector(byte[] bytes, int vLength) throws IOException {
byte[] out;
int olen = bytes.length - vLength;
if (olen <= 0) {
return new byte[0];
}
out = new byte[olen];
int ilen = bytes.length;
for (int i = vLength; i < ilen; i++) {
out[i - vLength] = bytes[i];
}
return out;
}
}