diff --git a/jans-core/util/pom.xml b/jans-core/util/pom.xml
index 805c3d2ad61..e3b3d572c09 100644
--- a/jans-core/util/pom.xml
+++ b/jans-core/util/pom.xml
@@ -99,6 +99,12 @@
jakarta.xml.bind
jakarta.xml.bind-api
+
+
+ org.testng
+ testng
+
+
\ No newline at end of file
diff --git a/jans-core/util/src/main/java/io/jans/util/security/AESUtil.java b/jans-core/util/src/main/java/io/jans/util/security/AESUtil.java
new file mode 100644
index 00000000000..bdb6737fe84
--- /dev/null
+++ b/jans-core/util/src/main/java/io/jans/util/security/AESUtil.java
@@ -0,0 +1,68 @@
+package io.jans.util.security;
+
+import javax.crypto.*;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.util.Base64;
+
+public class AESUtil {
+
+ public static final int IV_LENGTH = 16;
+ public static final int GCM_TAG_LENGTH = 16;
+
+ private AESUtil() {
+ }
+
+ public static SecretKey generateKey(int n) throws NoSuchAlgorithmException {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
+ keyGenerator.init(n);
+ return keyGenerator.generateKey();
+ }
+
+ public static SecretKey getKeyFromPassword(String password, String salt)
+ throws NoSuchAlgorithmException, InvalidKeySpecException {
+ SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
+ KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256);
+ return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
+ }
+
+ public static IvParameterSpec generateIv() {
+ return generateIv(IV_LENGTH);
+ }
+
+ public static IvParameterSpec generateIv(int size) {
+ byte[] iv = new byte[size];
+ new SecureRandom().nextBytes(iv);
+ return new IvParameterSpec(iv);
+ }
+
+ public static GCMParameterSpec generateGcmSpec() {
+ return new GCMParameterSpec(GCM_TAG_LENGTH * 8, generateIv().getIV());
+ }
+
+ public static String encrypt(String algorithm, String input, SecretKey key, AlgorithmParameterSpec spec) throws NoSuchPaddingException, NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+
+ Cipher cipher = Cipher.getInstance(algorithm);
+ cipher.init(Cipher.ENCRYPT_MODE, key, spec);
+ byte[] cipherText = cipher.doFinal(input.getBytes());
+ return Base64.getEncoder().encodeToString(cipherText);
+ }
+
+ public static String decrypt(String algorithm, String cipherText, SecretKey key, AlgorithmParameterSpec spec) throws NoSuchPaddingException, NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+ Cipher cipher = Cipher.getInstance(algorithm);
+ cipher.init(Cipher.DECRYPT_MODE, key, spec);
+ byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(cipherText));
+ return new String(plainText);
+ }
+}
diff --git a/jans-core/util/src/test/java/io/jans/util/security/AESUtilTest.java b/jans-core/util/src/test/java/io/jans/util/security/AESUtilTest.java
new file mode 100644
index 00000000000..08d100bae53
--- /dev/null
+++ b/jans-core/util/src/test/java/io/jans/util/security/AESUtilTest.java
@@ -0,0 +1,49 @@
+package io.jans.util.security;
+
+import org.testng.annotations.Test;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import static io.jans.util.security.AESUtil.generateGcmSpec;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * @author Yuriy Z
+ */
+public class AESUtilTest {
+
+ @Test
+ public void cbc_whenEncryptAndDecrypt_shouldProduceCorrectOutput() throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException {
+ String input = "textToEncrypt";
+ SecretKey key = AESUtil.generateKey(128);
+ IvParameterSpec ivParameterSpec = AESUtil.generateIv();
+
+ String algorithm = "AES/CBC/PKCS5Padding";
+ String cipherText = AESUtil.encrypt(algorithm, input, key, ivParameterSpec);
+ String plainText = AESUtil.decrypt(algorithm, cipherText, key, ivParameterSpec);
+
+ assertEquals(input, plainText);
+ }
+
+ @Test
+ public void gcm_whenEncryptAndDecrypt_shouldProduceCorrectOutput() throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException {
+ String input = "textToEncrypt";
+ SecretKey key = AESUtil.generateKey(128);
+
+ String algorithm = "AES/GCM/NoPadding";
+ final GCMParameterSpec gcmSpec = generateGcmSpec();
+
+ String cipherText = AESUtil.encrypt(algorithm, input, key, gcmSpec);
+ String plainText = AESUtil.decrypt(algorithm, cipherText, key, gcmSpec);
+
+ assertEquals(input, plainText);
+ }
+}