Skip to content

Commit

Permalink
Changed PseudoFuncInput and PseudoFuncOutput to only carry a single v…
Browse files Browse the repository at this point in the history
…alue. (#18)
  • Loading branch information
bjornandre authored Mar 11, 2024
1 parent 478439e commit d987381
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 329 deletions.
46 changes: 3 additions & 43 deletions src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFuncInput.java
Original file line number Diff line number Diff line change
@@ -1,47 +1,7 @@
package no.ssb.dapla.dlp.pseudo.func;

import lombok.Value;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Value
public class PseudoFuncInput {
private final List<Object> values = new ArrayList<>();

public PseudoFuncInput(Object v) {
if (v instanceof Collection) {
values.addAll((Collection) v);
}
else if (v.getClass().isArray()) {
values.addAll(Arrays.asList((Object[]) v));
}
else {
values.add(v);
}
}

public static PseudoFuncInput of(Object v) {
return new PseudoFuncInput(v);
}

public List<String> getStringValues() {
return values.stream()
.map(String::valueOf)
.collect(Collectors.toList());
}

public List<ParamMetadata> getParamMetadata() {
return getStringValues().stream()
.map(ParamMetadata::parse)
.collect(Collectors.toList());
}

@Override
public String toString() {
return String.valueOf(values);
public record PseudoFuncInput(String value) {
public static PseudoFuncInput of(String value) {
return new PseudoFuncInput(value);
}
}
41 changes: 6 additions & 35 deletions src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFuncOutput.java
Original file line number Diff line number Diff line change
@@ -1,42 +1,24 @@
package no.ssb.dapla.dlp.pseudo.func;

import lombok.NoArgsConstructor;
import lombok.Value;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Value
@NoArgsConstructor
public class PseudoFuncOutput {
List<Object> values = new ArrayList<>();
String value;
List<String> warnings = new ArrayList<>();
Map<String, String> metadata = new HashMap<>();


public PseudoFuncOutput(Object v) {
if (v instanceof Collection) {
values.addAll((Collection) v);
}
else if (v.getClass().isArray()) {
values.addAll(Arrays.asList((Object[]) v));
}
else {
values.add(v);
}
}

public static PseudoFuncOutput of(Object v) {
return new PseudoFuncOutput(v);
public PseudoFuncOutput(String value) {
this.value = value;
}

public void add(Object object) {
values.add(object);
public static PseudoFuncOutput of(String value) {
return new PseudoFuncOutput(value);
}

public void addWarning(String warning) {
Expand All @@ -46,20 +28,9 @@ public void addWarning(String warning) {
public void addMetadata(String key, String value) {
metadata.put(key, value);
}

public List<String> getStringValues() {
return values.stream()
.map(String::valueOf)
.collect(Collectors.toList());
}

public Object getFirstValue() {
return getValues().getFirst();
}

@Override
public String toString() {
return String.valueOf(values);
return String.valueOf(value);
}

public boolean hasWarnings() {
Expand Down
69 changes: 28 additions & 41 deletions src/main/java/no/ssb/dapla/dlp/pseudo/func/fpe/FpeFunc.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import com.idealista.fpe.builder.FormatPreservingEncryptionBuilder;
import lombok.extern.slf4j.Slf4j;
import no.ssb.dapla.dlp.pseudo.func.*;
import no.ssb.dapla.dlp.pseudo.func.util.FromString;

import java.util.ArrayList;
import java.util.List;

import static no.ssb.dapla.dlp.pseudo.func.fpe.Domains.domainOf;

Expand All @@ -30,58 +32,43 @@ public FpeFunc(PseudoFuncConfig genericConfig) {
config = fpeConfigService.resolve(genericConfig);

fpe = FormatPreservingEncryptionBuilder
.ff1Implementation()
.withDomain(domainOf(config.getAlphabet()))
.withDefaultPseudoRandomFunction(config.getKey())
.withDefaultLengthRange()
.build();
.ff1Implementation()
.withDomain(domainOf(config.getAlphabet()))
.withDefaultPseudoRandomFunction(config.getKey())
.withDefaultLengthRange()
.build();
}

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

for (Object inputValue : input.getValues()) {
String plain = String.valueOf(inputValue);

if (config.isReplaceIllegalChars()) {
CharReplacer.ReplacementResult res = CharReplacer.replace(plain, config.getReplaceIllegalCharsWith(), config.getAlphabet().availableCharacters());
if (res.hasReplacedChars()) {
plain = res.getResult();
output.addWarning(String.format("%s --> %s replaced by '%s' before pseudo",
getFuncDecl(), res.getReplacedChars(), res.getReplacementString()));
}
}
final String pseudonymized;

try {
pseudonymized = isFpeTransformCompliant(plain)
? fpe.encrypt(plain, STATIC_TWEAK)
: plain;
}
catch (Exception e) {
throw new FpePseudoFuncException("FPE pseudo apply error. func=" + getFuncDecl() + ", contentType=" + input.getParamMetadata(), e);
String plain = input.value();
List<String> warnings = new ArrayList<>();
if (config.isReplaceIllegalChars()) {
CharReplacer.ReplacementResult res = CharReplacer.replace(plain, config.getReplaceIllegalCharsWith(), config.getAlphabet().availableCharacters());
if (res.hasReplacedChars()) {
plain = res.getResult();
warnings.add(String.format("%s --> %s replaced by '%s' before pseudo",
getFuncDecl(), res.getReplacedChars(), res.getReplacementString()));
}

output.add(FromString.convert(pseudonymized, inputValue.getClass()));
}

return output;
try {
final String pseudonymized = isFpeTransformCompliant(plain) ? fpe.encrypt(plain, STATIC_TWEAK) : plain;
PseudoFuncOutput output = PseudoFuncOutput.of(pseudonymized);
warnings.forEach(output::addWarning);
return output;
} catch (Exception e) {
throw new FpePseudoFuncException("FPE pseudo apply error. func=" + getFuncDecl(), e);
}
}

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

for (Object inputValue : input.getValues()) {
String pseudonymized = String.valueOf(inputValue);
String pseudonymized = input.value();
String plain = isFpeTransformCompliant(pseudonymized)
? fpe.decrypt(pseudonymized, STATIC_TWEAK)
: pseudonymized;
output.add(FromString.convert(plain, inputValue.getClass()));
}

return output;
? fpe.decrypt(pseudonymized, STATIC_TWEAK)
: pseudonymized;
return PseudoFuncOutput.of(plain);
}

/**
Expand Down
32 changes: 9 additions & 23 deletions src/main/java/no/ssb/dapla/dlp/pseudo/func/redact/RedactFunc.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package no.ssb.dapla.dlp.pseudo.func.redact;

import com.google.common.base.Strings;
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;

import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.nullToEmpty;

@Slf4j
public class RedactFunc extends AbstractPseudoFunc {
private final RedactFuncConfigService configService = new RedactFuncConfigService();
Expand All @@ -31,29 +27,19 @@ public RedactFunc(@NonNull PseudoFuncConfig genericConfig) {

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

return output;
String plain = input.value();
if (plain.trim().isEmpty()) {
return PseudoFuncOutput.of(plain);
} else if (config.getRegex() != null) {
return PseudoFuncOutput.of(plain.replaceAll(config.getRegex(), config.getPlaceholder()));
} else {
return PseudoFuncOutput.of(config.getPlaceholder());
}
}

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

return output;
return PseudoFuncOutput.of(input.value());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
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 no.ssb.dapla.dlp.pseudo.func.AbstractPseudoFunc;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncConfig;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncException;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncInput;
import no.ssb.dapla.dlp.pseudo.func.PseudoFuncOutput;

import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
Expand Down Expand Up @@ -35,36 +38,24 @@ private DeterministicAead daead() {

@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;
String plain = input.value();
try {
byte[] ciphertext = daead().encryptDeterministically(plain.getBytes(StandardCharsets.UTF_8), DAEAD_STAMP_BYTES);
return PseudoFuncOutput.of(Base64.getEncoder().encodeToString(ciphertext));
} catch (GeneralSecurityException e) {
throw new DaeadPseudoFuncException("DAEAD apply error. func=" + getFuncDecl(), e);
}
}

@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;
byte[] ciphertext = Base64.getDecoder().decode(input.value());
try {
byte[] plaintext = daead().decryptDeterministically(ciphertext, DAEAD_STAMP_BYTES);
return PseudoFuncOutput.of(new String(plaintext));
} catch (GeneralSecurityException e) {
throw new DaeadPseudoFuncException("DAEAD restore error. func=" + getFuncDecl(), e);
}
}

public static class DaeadPseudoFuncException extends PseudoFuncException {
Expand Down
Loading

0 comments on commit d987381

Please sign in to comment.