| 1 | public class EncryptedAttribute { |
| 2 | public static final String AES_ECB_PKCS_5_PADDING = "AES/ECB/PKCS5Padding"; |
| 3 | private static volatile SecureRandom numberGenerator = new SecureRandom(); |
| 4 | public static byte[] salt(byte[] data) { |
| 5 | byte[] salt = new byte[4]; |
| 6 | numberGenerator.nextBytes(salt); |
| 7 | byte[] salted = new byte[data.length + salt.length]; |
| 8 | System.arraycopy(salt, 0, salted, 0, salt.length); |
| 9 | System.arraycopy(data, 0, salted, salt.length, data.length); |
| 10 | return salted; |
| 11 | } |
| 12 | public static byte[] unsalt(byte[] data) { |
| 13 | byte[] unsalted = new byte[data.length - 4]; |
| 14 | System.arraycopy(data, 4, unsalted, 0, unsalted.length); |
| 15 | return unsalted; |
| 16 | } |
| 17 | public static String encodeBase64(byte[] binary) { |
| 18 | return Base64.getEncoder().encodeToString(binary); |
| 19 | } |
| 20 | public static byte[] decodeBase64(String str) { |
| 21 | try { |
| 22 | return Base64.getDecoder().decode(str); |
| 23 | } catch (Exception e) { |
| 24 | return new byte[0]; |
| 25 | } |
| 26 | } |
| 27 | public static String encryptAttribute(String attribute, String accessKey) throws Exception { |
| 28 | if (attribute == null || attribute.length() == 0) { |
| 29 | return attribute; |
| 30 | } |
| 31 | Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING); |
| 32 | cipher.init(Cipher.ENCRYPT_MODE, buildKey(accessKey)); |
| 33 | return "crypt:" + encodeBase64(cipher.doFinal(salt(attribute.getBytes("UTF-8")))); |
| 34 | } |
| 35 | public static String decryptAttribute(String attribute, String accessKey) { |
| 36 | if (attribute == null || accessKey == null || !attribute.startsWith("crypt2:")) { //If attribute is not |
| 37 | encrypted |
| 38 | return it |
| 39 | return attribute; |
| 40 | } |
| 41 | try { |
| 42 | Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING); |
| 43 | cipher.init(Cipher.DECRYPT_MODE, buildKey(accessKey)); |
| 44 | return new String(unsalt(cipher.doFinal(decodeBase64(attribute.substring("crypt2:".length())))), "UTF- |
| 45 | 8 "); |
| 46 | } |
| 47 | catch (Exception e) { |
| 48 | return attribute; |
| 49 | } |
| 50 | } |
| 51 | private static SecretKeySpec buildKey(String accessKey) throws Exception { |
| 52 | MessageDigest digester = MessageDigest.getInstance("SHA-256"); |
| 53 | digester.update(accessKey.getBytes("UTF-8")); |
| 54 | byte[] key = Arrays.copyOf(digester.digest(), 32); |
| 55 | SecretKeySpec spec = new SecretKeySpec(key, "AES"); |
| 56 | return spec; |
| 57 | } |
| 58 | } |