Skip to content

Commit

Permalink
Add tink functions (#4)
Browse files Browse the repository at this point in the history
* Add dependency to tink 1.7.0

* Add Daead encryption function

* Add simple redact function

* Add Map function
  • Loading branch information
kschulst authored Dec 14, 2022
1 parent 5e6e5dd commit 6429ec0
Show file tree
Hide file tree
Showing 13 changed files with 434 additions and 2 deletions.
27 changes: 25 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

<groupId>no.ssb.dapla.dlp.pseudo.func</groupId>
<artifactId>dapla-dlp-pseudo-func</artifactId>
<version>1.0.3-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>
<name>dapla-dlp-pseudo-func</name>

<properties>
<java.version>8</java.version>
<java.version>11</java.version>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.source>${java.version}</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand All @@ -25,6 +25,7 @@
<logback.version>1.2.10</logback.version>
<lombok.version>1.18.22</lombok.version>
<slf4j.version>1.7.36</slf4j.version>
<tink.version>1.7.0</tink.version>

<!-- Plugin/extension versions -->
<artifactregistry-maven-wagon.version>2.1.4</artifactregistry-maven-wagon.version>
Expand Down Expand Up @@ -52,6 +53,28 @@
<artifactId>format-preserving-encryption</artifactId>
<version>${format-preserving-encryption.version}</version>
</dependency>
<dependency>
<groupId>com.google.crypto.tink</groupId>
<artifactId>tink</artifactId>
<version>${tink.version}</version>
</dependency>

<!--
<dependency>
<groupId>com.google.crypto.tink</groupId>
<artifactId>tink-gcpkms</artifactId>
<version>${tinkVersion}</version>
</dependency>
-->
<!-- to fix CVE-2021-22573 in tink-gcpkms -->
<!--
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client</artifactId>
<version>1.34.1</version>
</dependency>
-->

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/no/ssb/dapla/dlp/pseudo/func/daead/DaeadFunc.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package no.ssb.dapla.dlp.pseudo.func.daead;

import com.google.crypto.tink.DeterministicAead;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import no.ssb.dapla.dlp.pseudo.func.*;
import no.ssb.dapla.dlp.pseudo.func.util.FromString;

import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Base64;

@Slf4j
public class DaeadFunc extends AbstractPseudoFunc {

// FIXME: Replace this with something real
private static final byte[] DAEAD_STAMP_BYTES = "".getBytes(StandardCharsets.UTF_8);
private final DaeadFuncConfigService configService = new DaeadFuncConfigService();
private final DaeadFuncConfig config;

public DaeadFunc(@NonNull PseudoFuncConfig genericConfig) {
super(genericConfig.getFuncDecl());
this.config = configService.resolve(genericConfig);
}

private DeterministicAead daead() {
return config.getDaead();
}

@Override
public PseudoFuncOutput apply(PseudoFuncInput input) {
PseudoFuncOutput output = new PseudoFuncOutput();
input.getValues().forEach(in -> {
String plain = String.valueOf(in);
try {
byte[] ciphertext = daead().encryptDeterministically(plain.getBytes(StandardCharsets.UTF_8), DAEAD_STAMP_BYTES);
output.add(Base64.getEncoder().encodeToString(ciphertext));
}
catch (GeneralSecurityException e) {
throw new DaeadPseudoFuncException("DAEAD apply error. func=" + getFuncDecl() + ", contentType=" + input.getParamMetadata(), e);
}
});

return output;
}

@Override
public PseudoFuncOutput restore(PseudoFuncInput input) {
PseudoFuncOutput output = new PseudoFuncOutput();
input.getValues().forEach(in -> {
byte[] ciphertext = Base64.getDecoder().decode(String.valueOf(in));
try {
byte[] plaintext = daead().decryptDeterministically(ciphertext, DAEAD_STAMP_BYTES);
output.add(FromString.convert(new String(plaintext), in.getClass()));
}
catch (GeneralSecurityException e) {
throw new DaeadPseudoFuncException("DAEAD restore error. func=" + getFuncDecl() + ", contentType=" + input.getParamMetadata(), e);
}
});

return output;
}

public static class DaeadPseudoFuncException extends PseudoFuncException {
public DaeadPseudoFuncException(String message, Throwable cause) {
super(message, cause);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package no.ssb.dapla.dlp.pseudo.func.daead;

import com.google.crypto.tink.DeterministicAead;
import lombok.Builder;
import lombok.Value;
import lombok.experimental.UtilityClass;

@Value
@Builder
public class DaeadFuncConfig {
private final String dataEncryptionKeyId;
private final String base64EncodedWrappedDataEncryptionKey;
private final DeterministicAead daead;

@UtilityClass
public static class Param {
public static final String DEK_ID = "dataEncryptionKeyId";
public static final String WDEK = "wrappedDataEncryptionKey";
public static final String DAEAD = "deterministicAead";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package no.ssb.dapla.dlp.pseudo.func.daead;

import com.google.crypto.tink.DeterministicAead;
import lombok.extern.slf4j.Slf4j;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncConfig;

import static no.ssb.dapla.dlp.pseudo.func.daead.DaeadFuncConfig.Param.DAEAD;

@Slf4j
public class DaeadFuncConfigService {

public DaeadFuncConfig resolve(PseudoFuncConfig cfg) {

return DaeadFuncConfig.builder()
.daead(cfg.getRequired(DAEAD, DeterministicAead.class))
.build();
}

}
54 changes: 54 additions & 0 deletions src/main/java/no/ssb/dapla/dlp/pseudo/func/map/MapFunc.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package no.ssb.dapla.dlp.pseudo.func.map;

import lombok.extern.slf4j.Slf4j;
import no.ssb.dapla.dlp.pseudo.func.AbstractPseudoFunc;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncConfig;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncInput;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncOutput;

import java.util.ServiceLoader;

@Slf4j
public class MapFunc extends AbstractPseudoFunc {
private final MapFuncConfig config;
private final MapFuncConfigService mapFuncConfigService = new MapFuncConfigService();
private final Mapper mapper;

public MapFunc(PseudoFuncConfig genericConfig) {
super(genericConfig.getFuncDecl());
this.config = mapFuncConfigService.resolve(genericConfig);
// TODO: Filter Service Implementation by some annotation (to choose the implementation that is used)
this.mapper = ServiceLoader.load(Mapper.class)
.findFirst()
.orElseThrow(() -> new IllegalStateException(getClass().getSimpleName() + " requires a " + Mapper.class.getName() + " implementation to be present on the classpath"));
}

@Override
public PseudoFuncOutput apply(PseudoFuncInput input) {
PseudoFuncOutput output = new PseudoFuncOutput();

for (Object inputValue : input.getValues()) {
String plain = String.valueOf(inputValue);
final Object pseudonymized = mapper.map(plain);
//output.add(FromString.convert(pseudonymized, inputValue.getClass()));
output.add(pseudonymized);
}

return output;
}

@Override
public PseudoFuncOutput restore(PseudoFuncInput input) {
PseudoFuncOutput output = new PseudoFuncOutput();

for (Object inputValue : input.getValues()) {
String mapped = String.valueOf(inputValue);
final Object clear = mapper.restore(mapped);
//output.add(FromString.convert(clear, inputValue.getClass()));
output.add(clear);
}

return output;
}

}
16 changes: 16 additions & 0 deletions src/main/java/no/ssb/dapla/dlp/pseudo/func/map/MapFuncConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package no.ssb.dapla.dlp.pseudo.func.map;

import lombok.Builder;
import lombok.Value;
import lombok.experimental.UtilityClass;

@Value
@Builder
public class MapFuncConfig {
private final String context;

@UtilityClass
public static class Param {
public static final String CONTEXT = "context";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package no.ssb.dapla.dlp.pseudo.func.map;

import no.ssb.dapla.dlp.pseudo.func.PseudoFuncConfig;

public class MapFuncConfigService {

public MapFuncConfig resolve(PseudoFuncConfig genericConfig) {

String context = genericConfig.getRequired(MapFuncConfig.Param.CONTEXT, String.class);

return MapFuncConfig.builder()
.context(context)
.build();
}

}
9 changes: 9 additions & 0 deletions src/main/java/no/ssb/dapla/dlp/pseudo/func/map/Mapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package no.ssb.dapla.dlp.pseudo.func.map;

public interface Mapper {

Object map(Object data);

Object restore(Object mapped);

}
44 changes: 44 additions & 0 deletions src/main/java/no/ssb/dapla/dlp/pseudo/func/redact/RedactFunc.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package no.ssb.dapla.dlp.pseudo.func.redact;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import no.ssb.dapla.dlp.pseudo.func.AbstractPseudoFunc;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncConfig;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncInput;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncOutput;

@Slf4j
public class RedactFunc extends AbstractPseudoFunc {
private final RedactFuncConfigService configService = new RedactFuncConfigService();
private final RedactFuncConfig config;

public RedactFunc(@NonNull PseudoFuncConfig genericConfig) {
super(genericConfig.getFuncDecl());
this.config = configService.resolve(genericConfig);
}

@Override
public PseudoFuncOutput apply(PseudoFuncInput input) {
PseudoFuncOutput output = new PseudoFuncOutput();
input.getValues().forEach(in -> {
String plain = String.valueOf(in);
if (config.getRegex() != null) {
output.add(plain.replaceAll(config.getRegex(), config.getPlaceholder()));
}
else {
output.add(config.getPlaceholder());
}
});

return output;
}

@Override
public PseudoFuncOutput restore(PseudoFuncInput input) {
PseudoFuncOutput output = new PseudoFuncOutput();
input.getValues().forEach(in -> output.add(in));

return output;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package no.ssb.dapla.dlp.pseudo.func.redact;

import lombok.Builder;
import lombok.Value;
import lombok.experimental.UtilityClass;

@Value
@Builder
public class RedactFuncConfig {
private final String placeholder;
private final String regex;

@UtilityClass
public static class Param {
public static final String PLACEHOLDER = "placeholder";
public static final String REGEX = "regex";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package no.ssb.dapla.dlp.pseudo.func.redact;

import lombok.extern.slf4j.Slf4j;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncConfig;

import static no.ssb.dapla.dlp.pseudo.func.redact.RedactFuncConfig.Param.PLACEHOLDER;
import static no.ssb.dapla.dlp.pseudo.func.redact.RedactFuncConfig.Param.REGEX;

@Slf4j
public class RedactFuncConfigService {

public RedactFuncConfig resolve(PseudoFuncConfig cfg) {
return RedactFuncConfig.builder()
.placeholder(cfg.get(PLACEHOLDER, String.class).orElse("***"))
.regex(cfg.get(REGEX, String.class).orElse(null))
.build();
}

}
Loading

0 comments on commit 6429ec0

Please sign in to comment.