package util;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.security.AlgorithmParameters;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletException;
public class Encryption {
/**
* Encrypt an array of integers to a String.
*
* @param integers
* @param context
* @return
* @throws ServletException
*/
public static String encryptIntegers(int integers[], String password) throws ServletException {
/* Generate salt. */
SecureRandom rand = new SecureRandom();
byte salt[] = new byte[8];
rand.nextBytes(salt);
byte[] iv;
byte[] ciphertext;
try {
/* Derive the key, given password and salt. */
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
/* Encrypt the SampleSetID. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
iv = params.getParameterSpec(IvParameterSpec.class).getIV();
ByteBuffer buff = ByteBuffer.allocate(integers.length * 4);
for (int i = 0; i < integers.length; ++i) {
buff.putInt(integers[i]);
}
ciphertext = cipher.doFinal(buff.array());
} catch (Exception ex) {
throw new ServletException(ex);
}
/* Store the encrypted SampleSetID in a cookie */
Encoder encoder = Base64.getEncoder();
String encryptedStr = encoder.encodeToString(ciphertext) + "|" + encoder.encodeToString(iv) + "|" + encoder.encodeToString(salt);
return encryptedStr;
}
/**
* Decrypt an array of integers from a String.
*
* @param encrypted
* @param context
* @return
* @throws ServletException
*/
public static int[] decryptIntegers(String encrypted, String password) throws ServletException {
String encryptedParts[] = encrypted.split("\\|");
if (encryptedParts.length != 3) {
throw new ServletException("Invalid encrypted string.");
}
/* Extract the encrypted data, initialisation vector, and salt from the cookie. */
Decoder decoder = Base64.getDecoder();
byte ciphertext[] = decoder.decode(encryptedParts[0]);
byte iv[] = decoder.decode(encryptedParts[1]);
byte salt[] = decoder.decode(encryptedParts[2]);
byte plainbytes[];
try {
/* Derive the key, given password and salt. */
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
/* Decrypt the message, given derived key and initialization vector. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
plainbytes = cipher.doFinal(ciphertext);
} catch (Exception ex) {
throw new ServletException(ex);
}
IntBuffer buff = ByteBuffer.wrap(plainbytes).asIntBuffer();
int integers[] = new int[buff.remaining()];
for (int i = 0; i < integers.length; ++i) {
integers[i] = buff.get();
}
return integers;
}
}