-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new function that combines both mapping and encryption. (#19)
Add MapAndEncryptFunc which combines both mapping and encryption
- Loading branch information
1 parent
d987381
commit e8883e8
Showing
12 changed files
with
271 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
src/main/java/no/ssb/dapla/dlp/pseudo/func/TransformDirection.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package no.ssb.dapla.dlp.pseudo.func; | ||
|
||
public enum TransformDirection { | ||
APPLY, RESTORE | ||
} |
96 changes: 96 additions & 0 deletions
96
src/main/java/no/ssb/dapla/dlp/pseudo/func/composite/MapAndEncryptFunc.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package no.ssb.dapla.dlp.pseudo.func.composite; | ||
|
||
import no.ssb.dapla.dlp.pseudo.func.AbstractPseudoFunc; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFunc; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncConfig; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncFactory; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncInput; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncOutput; | ||
import no.ssb.dapla.dlp.pseudo.func.TransformDirection; | ||
|
||
import java.util.function.Function; | ||
|
||
import static no.ssb.dapla.dlp.pseudo.func.composite.MapAndEncryptFuncConfig.Param.*; | ||
|
||
/** | ||
* This is a composite {@code PseudoFunc} that combines two {@code PseudoFunc}s into a single operation. | ||
* <p> | ||
* It assumes that one is a mapping function (e.g. MapFunc) and the other is an encryption function | ||
* (e.g FpeFunc, TinkFpeFunc, TinkDaeadFunc). | ||
* | ||
* The {@code MapAndEncryptFunc} must be configured with a | ||
* {@link no.ssb.dapla.dlp.pseudo.func.composite.MapAndEncryptFuncConfig.Param#ENCRYPTION_FUNC_IMPL} and a | ||
* {@link no.ssb.dapla.dlp.pseudo.func.composite.MapAndEncryptFuncConfig.Param#MAP_FUNC_IMPL}. | ||
* | ||
* The {@code PseudoFuncConfig} must also contain all the necessary configs for each of the underlying | ||
* {@code PseudoFunc}s. For example MapFuncConfig and TinkFpeFuncConfig. | ||
*/ | ||
public class MapAndEncryptFunc extends AbstractPseudoFunc { | ||
|
||
final PseudoFunc encryptionFunc; | ||
final PseudoFunc mapFunc; | ||
|
||
public MapAndEncryptFunc(PseudoFuncConfig genericConfig) { | ||
super(genericConfig.getFuncDecl()); | ||
genericConfig.add(PseudoFuncConfig.Param.FUNC_IMPL, | ||
genericConfig.getRequired(ENCRYPTION_FUNC_IMPL, String.class)); | ||
var encryptionFuncConfig = genericConfig.asMap(); | ||
genericConfig.add(PseudoFuncConfig.Param.FUNC_IMPL, | ||
genericConfig.getRequired(MAP_FUNC_IMPL, String.class)); | ||
var mapFuncConfig = genericConfig.asMap(); | ||
|
||
this.encryptionFunc = PseudoFuncFactory.create(new PseudoFuncConfig(encryptionFuncConfig)); | ||
this.mapFunc = PseudoFuncFactory.create(new PseudoFuncConfig(mapFuncConfig)); | ||
} | ||
|
||
@Override | ||
public String getAlgorithm() { | ||
return encryptionFunc.getAlgorithm(); | ||
} | ||
|
||
@Override | ||
public void init(PseudoFuncInput input, TransformDirection direction) { | ||
if (direction == TransformDirection.APPLY) { | ||
// Prepare map from original value to mapped value | ||
mapFunc.init(input, direction); | ||
} else { | ||
// Decrypt and then prepare to map back to original value | ||
mapFunc.init(PseudoFuncInput.of( | ||
encryptionFunc.restore(input).getValue()), | ||
direction | ||
); | ||
} | ||
} | ||
|
||
@Override | ||
public PseudoFuncOutput apply(PseudoFuncInput input) { | ||
// Map original value to mapped value and then encrypt | ||
return transform(input, mapFunc::apply, encryptionFunc::apply); | ||
} | ||
@Override | ||
public PseudoFuncOutput restore(PseudoFuncInput input) { | ||
// Decrypt and then map back to original value | ||
return transform(input, encryptionFunc::restore, mapFunc::restore); | ||
} | ||
|
||
/** | ||
* Apply both functions {@code inner} and {@code outer} and merge both | ||
* outputs. | ||
* | ||
* @param input the original value | ||
* @param inner the inner function to apply | ||
* @param outer the outer function to apply | ||
* @return the result object | ||
*/ | ||
private PseudoFuncOutput transform(PseudoFuncInput input, | ||
Function<PseudoFuncInput, PseudoFuncOutput> inner, | ||
Function<PseudoFuncInput, PseudoFuncOutput> outer) { | ||
final PseudoFuncOutput innerOutput = inner.apply(input); | ||
final PseudoFuncOutput outerOutput = outer.apply( | ||
PseudoFuncInput.of(innerOutput.getValue())); | ||
innerOutput.getWarnings().forEach(outerOutput::addWarning); | ||
innerOutput.getMetadata().forEach(outerOutput::addMetadata); | ||
return outerOutput; | ||
|
||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/no/ssb/dapla/dlp/pseudo/func/composite/MapAndEncryptFuncConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package no.ssb.dapla.dlp.pseudo.func.composite; | ||
|
||
import lombok.Builder; | ||
import lombok.Value; | ||
import lombok.experimental.UtilityClass; | ||
|
||
@Value | ||
@Builder | ||
public class MapAndEncryptFuncConfig { | ||
String encryptionFunc; | ||
String mapFunc; | ||
|
||
@UtilityClass | ||
public static class Param { | ||
public static final String ENCRYPTION_FUNC_IMPL = "encryptionFunc"; | ||
public static final String MAP_FUNC_IMPL = "mapFunc"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/main/java/no/ssb/dapla/dlp/pseudo/func/map/MappingNotFoundException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package no.ssb.dapla.dlp.pseudo.func.map; | ||
|
||
public class MappingNotFoundException extends RuntimeException { | ||
public MappingNotFoundException(String message) { | ||
super(message); | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
src/test/java/no/ssb/dapla/dlp/pseudo/func/composite/MapAndEncryptFuncTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package no.ssb.dapla.dlp.pseudo.func.composite; | ||
|
||
import com.google.common.collect.ImmutableMap; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFunc; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncConfig; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncFactory; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncInput; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncOutput; | ||
import no.ssb.dapla.dlp.pseudo.func.fpe.FpeFunc; | ||
import no.ssb.dapla.dlp.pseudo.func.fpe.FpeFuncConfig; | ||
import no.ssb.dapla.dlp.pseudo.func.map.MapFunc; | ||
import no.ssb.dapla.dlp.pseudo.func.map.MappingNotFoundException; | ||
import no.ssb.dapla.dlp.pseudo.func.map.TestMapper; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.assertj.core.api.Assertions.*; | ||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
public class MapAndEncryptFuncTest { | ||
private static final String BASE64_ENCODED_KEY = "w0/G6A5e/KHtTo31FD6mhhS1Tkga43l79IBK24gM4F8="; | ||
|
||
final PseudoFuncConfig config = new PseudoFuncConfig(ImmutableMap.of( | ||
PseudoFuncConfig.Param.FUNC_DECL, "map-fpe-test", | ||
PseudoFuncConfig.Param.FUNC_IMPL, MapAndEncryptFunc.class.getName(), | ||
MapAndEncryptFuncConfig.Param.MAP_FUNC_IMPL, MapFunc.class.getName(), | ||
MapAndEncryptFuncConfig.Param.ENCRYPTION_FUNC_IMPL, FpeFunc.class.getName(), | ||
FpeFuncConfig.Param.ALPHABET, "alphanumeric+whitespace", | ||
FpeFuncConfig.Param.KEY_ID, "keyId1", | ||
FpeFuncConfig.Param.KEY_DATA, BASE64_ENCODED_KEY | ||
|
||
)); | ||
/* | ||
* This test should transform OriginalValue -> MappedValue -> FPE encrypted MappedValue | ||
* (and back) | ||
*/ | ||
@Test | ||
public void transformAndRestore() { | ||
String expectedVal = "ygd1M9at1nK"; // FPE encrypted MappedValue | ||
PseudoFunc func = PseudoFuncFactory.create(config); | ||
|
||
PseudoFuncOutput pseudonymized = func.apply(PseudoFuncInput.of(TestMapper.ORIGINAL)); | ||
assertThat(pseudonymized.getValue()).isEqualTo(expectedVal); | ||
|
||
PseudoFuncOutput depseudonymized = func.restore(PseudoFuncInput.of(pseudonymized.getValue())); | ||
assertThat(depseudonymized.getValue()).isEqualTo(TestMapper.ORIGINAL); | ||
} | ||
|
||
@Test | ||
public void call_apply_with_mapping_failure() { | ||
PseudoFunc func = PseudoFuncFactory.create(config); | ||
|
||
assertThrows(MappingNotFoundException.class,() -> | ||
func.apply(PseudoFuncInput.of("unknown")) | ||
); | ||
} | ||
|
||
@Test | ||
public void call_restore_with_mapping_failure() { | ||
PseudoFunc func = PseudoFuncFactory.create(config); | ||
|
||
assertThrows(MappingNotFoundException.class,() -> | ||
func.restore(PseudoFuncInput.of("unknown")) | ||
); | ||
} | ||
|
||
} |
29 changes: 29 additions & 0 deletions
29
src/test/java/no/ssb/dapla/dlp/pseudo/func/map/MapFuncTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package no.ssb.dapla.dlp.pseudo.func.map; | ||
|
||
import com.google.common.collect.ImmutableMap; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFunc; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncConfig; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncFactory; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncInput; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncOutput; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.assertj.core.api.Assertions.*; | ||
|
||
public class MapFuncTest { | ||
@Test | ||
public void transformAndRestore() { | ||
final PseudoFuncConfig config = new PseudoFuncConfig(ImmutableMap.of( | ||
PseudoFuncConfig.Param.FUNC_DECL, "map-test", | ||
PseudoFuncConfig.Param.FUNC_IMPL, MapFunc.class.getName() | ||
)); | ||
PseudoFunc func = PseudoFuncFactory.create(config); | ||
|
||
PseudoFuncOutput mapOutput = func.apply(PseudoFuncInput.of(TestMapper.ORIGINAL)); | ||
assertThat(mapOutput.getValue()).isEqualTo(TestMapper.MAPPED); | ||
|
||
PseudoFuncOutput depseudonymized = func.restore(PseudoFuncInput.of(mapOutput.getValue())); | ||
assertThat(depseudonymized.getValue()).isEqualTo(TestMapper.ORIGINAL); | ||
} | ||
|
||
} |
41 changes: 41 additions & 0 deletions
41
src/test/java/no/ssb/dapla/dlp/pseudo/func/map/TestMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package no.ssb.dapla.dlp.pseudo.func.map; | ||
|
||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncInput; | ||
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncOutput; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* This class is loaded using the Java Service Provider API. | ||
*/ | ||
public class TestMapper implements Mapper { | ||
|
||
public static String ORIGINAL = "OriginalValue"; | ||
public static String MAPPED = "MappedValue"; | ||
|
||
@Override | ||
public void init(PseudoFuncInput data) { | ||
} | ||
|
||
@Override | ||
public void setConfig(Map<String, Object> config) { | ||
} | ||
|
||
@Override | ||
public PseudoFuncOutput map(PseudoFuncInput input) throws MappingNotFoundException { | ||
if (ORIGINAL.equals(input.value())) { | ||
return PseudoFuncOutput.of(MAPPED); | ||
} else { | ||
throw new MappingNotFoundException(String.format("Could not map value %s", input.value())); | ||
} | ||
} | ||
|
||
@Override | ||
public PseudoFuncOutput restore(PseudoFuncInput mapped) throws MappingNotFoundException { | ||
if (MAPPED.equals(mapped.value())) { | ||
return PseudoFuncOutput.of(ORIGINAL); | ||
} else { | ||
throw new MappingNotFoundException(String.format("Could not map value %s", mapped.value())); | ||
} | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
src/test/resources/META-INF/services/no.ssb.dapla.dlp.pseudo.func.map.Mapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
no.ssb.dapla.dlp.pseudo.func.map.TestMapper |