Encrypt on the server (never in the browser with a key the browser can see) and store only the ciphertext in the process; decrypt in the service that needs the clear value. A small Java integration with the JDK's AES-GCM and a key kept outside the process app:
// Java (managed jar): AES-256-GCM with a key from an environment/JVM property or a file - never from a script constant
public class Crypto {
private static SecretKey key() throws Exception {
String b64 = System.getProperty("bpm.crypto.key", System.getenv("BPM_CRYPTO_KEY")); // 32 bytes, Base64; on CP4BA from a mounted secret
return new SecretKeySpec(Base64.getDecoder().decode(b64), "AES");
}
public static String encrypt(String clear) throws Exception {
byte[] iv = new byte[12]; new SecureRandom().nextBytes(iv);
Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); c.init(Cipher.ENCRYPT_MODE, key(), new GCMParameterSpec(128, iv));
byte[] enc = c.doFinal(clear.getBytes("UTF-8"));
byte[] out = new byte[iv.length + enc.length]; System.arraycopy(iv, 0, out, 0, 12); System.arraycopy(enc, 0, out, 12, enc.length);
return Base64.getEncoder().encodeToString(out);
}
public static String decrypt(String b64) throws Exception {
byte[] all = Base64.getDecoder().decode(b64);
Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); c.init(Cipher.DECRYPT_MODE, key(), new GCMParameterSpec(128, Arrays.copyOfRange(all, 0, 12)));
return new String(c.doFinal(all, 12, all.length - 12), "UTF-8");
}
}// service flow "Encrypt value": Java Integration Crypto.encrypt(tw.local.clear) -> tw.local.cipherText
// usage: the coach submits the value, the first service flow after the coach encrypts it and clears the clear-text variable
tw.local.customer.ssnEncrypted = tw.local.cipherText; tw.local.ssnClear = null;
// decrypt only in the service that calls the back end; never map the clear value back into a coach unless masked
Rules: keys come from the platform (JVM custom property, a file readable only by the server user, a Kubernetes secret on CP4BA), rotated with a key id stored next to the ciphertext; do not expose encrypted fields as searchable business data (the search would be on ciphertext anyway); mask on display (***-**-1234); log nothing; and prefer not storing the value at all when a token / reference from the source system suffices. The coach-side "Encrypted Input" controls of some toolkits only obfuscate (Base64 / XOR in the browser) - fine against shoulder surfing, useless as security.
References