11package no .ssb .dlp .pseudo .core .func ;
22
3- import com .google .crypto .tink .DeterministicAead ;
4- import com .google .crypto .tink .JsonKeysetReader ;
5- import com .google .crypto .tink .KeysetHandle ;
6- import com .google .crypto .tink .KmsClients ;
3+ import com .github .benmanes .caffeine .cache .Cache ;
4+ import com .github .benmanes .caffeine .cache .LoadingCache ;
5+ import com .google .crypto .tink .*;
76import no .ssb .crypto .tink .fpe .Fpe ;
87import no .ssb .dapla .dlp .pseudo .func .PseudoFunc ;
98import no .ssb .dapla .dlp .pseudo .func .PseudoFuncConfig ;
9+ import no .ssb .dapla .dlp .pseudo .func .PseudoFuncException ;
1010import no .ssb .dapla .dlp .pseudo .func .PseudoFuncFactory ;
1111import no .ssb .dapla .dlp .pseudo .func .composite .MapAndEncryptFunc ;
1212import no .ssb .dapla .dlp .pseudo .func .composite .MapAndEncryptFuncConfig ;
2424import no .ssb .dlp .pseudo .core .tink .model .EncryptedKeysetWrapper ;
2525import no .ssb .dlp .pseudo .core .util .Json ;
2626
27+ import java .security .GeneralSecurityException ;
28+ import java .time .Duration ;
2729import java .util .*;
2830import java .util .function .Function ;
2931import java .util .stream .Collectors ;
3032
3133public class PseudoFuncs {
3234
3335 private final Map <PseudoFuncRule , PseudoFunc > ruleToFuncMap = new LinkedHashMap <>();
36+ private final LoadingCache <String , Aead > aeadCache ;
3437
3538
3639 //TODO: Validate that all required secrets are available
3740 public PseudoFuncs (Collection <PseudoFuncRule > rules , Collection <PseudoSecret > pseudoSecrets ,
38- Collection <PseudoKeyset > keysets ) {
41+ Collection <PseudoKeyset > keysets , LoadingCache <String , Aead > aeadCache ) {
42+ this .aeadCache = aeadCache ;
3943 Map <PseudoFuncRule , PseudoFuncConfig > ruleToPseudoFuncConfigs = initPseudoFuncConfigs (rules , pseudoSecrets , keysets );
4044 rules .forEach (rule -> ruleToFuncMap .put (rule , PseudoFuncFactory .create (ruleToPseudoFuncConfigs .get (rule ))));
4145 }
4246
4347 // TODO: Move these init functions elsewhere?
44- static Map <PseudoFuncRule , PseudoFuncConfig > initPseudoFuncConfigs (Collection <PseudoFuncRule > pseudoRules ,
48+ Map <PseudoFuncRule , PseudoFuncConfig > initPseudoFuncConfigs (Collection <PseudoFuncRule > pseudoRules ,
4549 Collection <PseudoSecret > pseudoSecrets ,
4650 Collection <PseudoKeyset > pseudoKeysets ) {
4751
@@ -70,7 +74,7 @@ static Map<PseudoFuncRule, PseudoFuncConfig> initPseudoFuncConfigs(Collection<Ps
7074 }));
7175 }
7276
73- private static void enrichMapAndEncryptFunc (PseudoFuncConfig funcConfig ,
77+ private void enrichMapAndEncryptFunc (PseudoFuncConfig funcConfig ,
7478 Map <String , PseudoKeyset > pseudoKeysetMap ,
7579 Map <String , PseudoSecret > pseudoSecretsMap ,
7680 Collection <PseudoSecret > pseudoSecrets ) {
@@ -86,15 +90,15 @@ private static void enrichMapAndEncryptFunc(PseudoFuncConfig funcConfig,
8690 }
8791 }
8892
89- private static void enrichLegacyFpeFuncConfig (PseudoFuncConfig funcConfig , Map <String , PseudoSecret > pseudoSecretsMap ) {
93+ private void enrichLegacyFpeFuncConfig (PseudoFuncConfig funcConfig , Map <String , PseudoSecret > pseudoSecretsMap ) {
9094 String secretId = funcConfig .getRequired (FpeFuncConfig .Param .KEY_ID , String .class );
9195 if (! pseudoSecretsMap .containsKey (secretId )) {
9296 throw new PseudoException ("No secret found for FPE pseudo func with " + FpeFuncConfig .Param .KEY_ID + "=" + secretId );
9397 }
9498 funcConfig .add (FpeFuncConfig .Param .KEY_DATA , pseudoSecretsMap .get (secretId ).getBase64EncodedContent ());
9599 }
96100
97- private static void enrichTinkDaeadFuncConfig (PseudoFuncConfig funcConfig , Map <String , PseudoKeyset > keysetMap , Collection <PseudoSecret > pseudoSecrets ) {
101+ private void enrichTinkDaeadFuncConfig (PseudoFuncConfig funcConfig , Map <String , PseudoKeyset > keysetMap , Collection <PseudoSecret > pseudoSecrets ) {
98102 String dekId = funcConfig .getRequired (TinkDaeadFuncConfig .Param .KEY_ID , String .class );
99103
100104 // TODO: Support creating new key material instead of failing if none found?
@@ -116,9 +120,13 @@ private static void enrichTinkDaeadFuncConfig(PseudoFuncConfig funcConfig, Map<S
116120
117121 try {
118122 String keyUri = keyset .getKekUri ().toString ();
123+
124+ Aead masterKey = Optional .ofNullable (this .aeadCache .get (keyUri ))
125+ .orElseThrow (() -> new PseudoFuncException ("Key material with URI " + keyUri + " not found in cache" ));
126+
119127 KeysetHandle keysetHandle = KeysetHandle .read (
120128 JsonKeysetReader .withString (keyset .toJson ()),
121- KmsClients . get ( keyUri ). getAead ( keyUri )
129+ masterKey
122130 );
123131
124132 DeterministicAead daead = keysetHandle .getPrimitive (DeterministicAead .class );
@@ -129,7 +137,7 @@ private static void enrichTinkDaeadFuncConfig(PseudoFuncConfig funcConfig, Map<S
129137 }
130138 }
131139
132- private static void enrichTinkFpeFuncConfig (PseudoFuncConfig funcConfig , Map <String , PseudoKeyset > keysetMap , Collection <PseudoSecret > pseudoSecrets ) {
140+ private void enrichTinkFpeFuncConfig (PseudoFuncConfig funcConfig , Map <String , PseudoKeyset > keysetMap , Collection <PseudoSecret > pseudoSecrets ) {
133141 String dekId = funcConfig .getRequired (TinkFpeFuncConfig .Param .KEY_ID , String .class );
134142
135143 // TODO: Support creating new key material instead of failing if none found?
@@ -151,9 +159,13 @@ private static void enrichTinkFpeFuncConfig(PseudoFuncConfig funcConfig, Map<Str
151159
152160 try {
153161 String keyUri = keyset .getKekUri ().toString ();
162+
163+ Aead masterKey = Optional .ofNullable (this .aeadCache .get (keyUri ))
164+ .orElseThrow (() -> new PseudoFuncException ("Key material with URI " + keyUri + " not found in cache" ));
165+
154166 KeysetHandle keysetHandle = KeysetHandle .read (
155167 JsonKeysetReader .withString (keyset .toJson ()),
156- KmsClients . get ( keyUri ). getAead ( keyUri )
168+ masterKey
157169 );
158170
159171 Fpe fpe = keysetHandle .getPrimitive (Fpe .class );
0 commit comments