package dev.dinauer.oidcproxy.session; import jakarta.enterprise.context.ApplicationScoped; import org.eclipse.microprofile.config.inject.ConfigProperty; import javax.crypto.*; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.util.Base64; @ApplicationScoped public class EncryptUtils { private static final String CIPHER_TRANSFORMATION = "AES/GCM/NoPadding"; private static final int IV_LENGTH = 8; private static final int AUTH_TAG_LENGTH = 128; private final SecretKey key; public EncryptUtils(@ConfigProperty(name = "oidc.proxy.crypto.secret") String secret) { try { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec(secret.toCharArray(), secret.getBytes(), 256_000, 256); this.key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { throw new RuntimeException(e); } } public String encrypt(String input) throws Exception { byte[] iv = new byte[IV_LENGTH]; new SecureRandom().nextBytes(iv); Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION); cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(AUTH_TAG_LENGTH, iv)); byte[] encrypted = cipher.doFinal(input.getBytes((StandardCharsets.UTF_8))); byte[] combined = new byte[iv.length + encrypted.length]; System.arraycopy(iv, 0, combined, 0, iv.length); System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length); return Base64.getEncoder().encodeToString(combined); } public String decrypt(String ciphertext) throws Exception { byte[] combined = Base64.getDecoder().decode(ciphertext); byte[] iv = new byte[IV_LENGTH]; byte[] encrypted = new byte[combined.length - IV_LENGTH]; System.arraycopy(combined, 0, iv, 0, iv.length); System.arraycopy(combined, iv.length, encrypted, 0, encrypted.length); Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION); cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(AUTH_TAG_LENGTH, iv)); return new String(cipher.doFinal(encrypted), StandardCharsets.UTF_8); } }