public class EncryptedAttribute {
public static final String AES_ECB_PKCS_5_PADDING = "AES/ECB/PKCS5Padding";
private static volatile SecureRandom numberGenerator = new SecureRandom();
public static byte[] salt(byte[] data) {
byte[] salt = new byte[4];
numberGenerator.nextBytes(salt);
byte[] salted = new byte[data.length + salt.length];
System.arraycopy(salt, 0, salted, 0, salt.length);
System.arraycopy(data, 0, salted, salt.length, data.length);
return salted;
}
public static byte[] unsalt(byte[] data) {
byte[] unsalted = new byte[data.length - 4];
System.arraycopy(data, 4, unsalted, 0, unsalted.length);
return unsalted;
}
public static String encodeBase64(byte[] binary) {
return Base64.getEncoder().encodeToString(binary);
}
public static byte[] decodeBase64(String str) {
try {
return Base64.getDecoder().decode(str);
} catch (Exception e) {
return new byte[0];
}
}
public static String encryptAttribute(String attribute, String accessKey) throws Exception {
if (attribute == null || attribute.length() == 0) {
return attribute;
}
Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, buildKey(accessKey));
return "crypt:" + encodeBase64(cipher.doFinal(salt(attribute.getBytes("UTF-8"))));
}
public static String decryptAttribute(String attribute, String accessKey) {
if (attribute == null || accessKey == null || !attribute.startsWith("crypt2:")) { //If attribute is not
encrypted
return it
return attribute;
}
try {
Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING);
cipher.init(Cipher.DECRYPT_MODE, buildKey(accessKey));
return new String(unsalt(cipher.doFinal(decodeBase64(attribute.substring("crypt2:".length())))), "UTF-
8 ");
}
catch (Exception e) {
return attribute;
}
}
private static SecretKeySpec buildKey(String accessKey) throws Exception {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(accessKey.getBytes("UTF-8"));
byte[] key = Arrays.copyOf(digester.digest(), 32);
SecretKeySpec spec = new SecretKeySpec(key, "AES");
return spec;
}
}