package fr.mch.mdo.restaurant.services.util;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import fr.mch.mdo.logs.ILogger;
import fr.mch.mdo.restaurant.exception.MdoTechnicalException;
import fr.mch.mdo.restaurant.services.logs.LoggerServiceImpl;
public class RestaurantReferenceFactory implements IRestaurantReferenceFactory
{
private static ILogger logger = LoggerServiceImpl.getInstance().getLogger(RestaurantReferenceFactory.class.getName());
/**
* This class is only used for Singleton lazy initialization
*
* @author Mathieu
*
*/
private static class InitializeOnDemandHolder
{
/** Singleton */
private static IRestaurantReferenceFactory instance;
static {
logger.info("Instantiating the class " + RestaurantReferenceFactory.class.getName());
instance = new RestaurantReferenceFactory();
logger.info(RestaurantReferenceFactory.class.getName() + " class instantiated");
}
}
public static IRestaurantReferenceFactory getInstance() {
return InitializeOnDemandHolder.instance;
}
private byte[] encrypt(String mdKey, String message) throws Exception {
final MessageDigest md = MessageDigest.getInstance("md5");
final byte[] digestOfPassword = md.digest(mdKey.getBytes("UTF-8"));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
final byte[] plainTextBytes = message.getBytes("UTF-8");
final byte[] cipherText = cipher.doFinal(plainTextBytes);
return cipherText;
}
private String decrypt(String mdKey, byte[] message) throws Exception {
final MessageDigest md = MessageDigest.getInstance("md5");
final byte[] digestOfPassword = md.digest(mdKey.getBytes("UTF-8"));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
decipher.init(Cipher.DECRYPT_MODE, key, iv);
final byte[] plainText = decipher.doFinal(message);
return new String(plainText, "UTF-8");
}
private static final String HEXES = "0123456789ABCDEF";
public static String byteArrayToHexaString(byte[] raw) {
if (raw == null) {
return null;
}
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
public static byte[] hexaStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
@Override
public String getReferenceFromValue(String key, String value) throws MdoTechnicalException {
String result = null;
if (key == null) {
key = "";
}
if (value == null) {
value = "";
}
try {
byte[] data = this.encrypt(key, value);
result = byteArrayToHexaString(data);
} catch (Exception e) {
logger.error("Could not generate reference from value " + value + " with key " + key, e);
throw new MdoTechnicalException("Could not generate reference from value " + value + " with key " + key, e);
}
return result;
}
@Override
public String getValueFromReference(String key, String reference) throws MdoTechnicalException {
String result = null;
if (key == null) {
key = "";
}
if (reference == null) {
reference = "";
}
try {
result = this.decrypt(key, hexaStringToByteArray(reference));
} catch (Exception e) {
logger.error("Could not generate value from reference " + reference + " with key " + key, e);
throw new MdoTechnicalException("Could not generate value from reference " + reference + " with key " + key, e);
}
return result;
}
}