Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@
import org.erdtman.jcs.JsonCanonicalizer;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Objects;

Expand All @@ -29,6 +32,8 @@ public class Manifest {
private static final String kAssertionHash = "assertionHash";
private static final String kAssertionSignature = "assertionSig";

private static final Gson gson = new Gson();

@Override
public boolean equals(Object o) {
if (this == o)
Expand Down Expand Up @@ -327,7 +332,6 @@ public int hashCode() {
}

public String hash() throws IOException {
Gson gson = new Gson();
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-256");
Expand Down Expand Up @@ -443,4 +447,17 @@ private JWSVerifier createVerifier(AssertionConfig.AssertionKey assertionKey) th
public EncryptionInformation encryptionInformation;
public Payload payload;
public List<Assertion> assertions = new ArrayList<>();

private static Manifest readManifest(Reader reader) {
return gson.fromJson(reader, Manifest.class);
}

static PolicyObject readPolicyObject(Reader reader) {
var manifest = readManifest(reader);
var policyBase64 = manifest.encryptionInformation.policy;
var policyBytes = Base64.getDecoder().decode(policyBase64);
var policyJson = new String(policyBytes, StandardCharsets.UTF_8);

return gson.fromJson(policyJson, PolicyObject.class);
}
}
31 changes: 9 additions & 22 deletions sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -355,6 +357,10 @@ public void readPayload(OutputStream outputStream) throws TDFReadFailed,
}
}
}

public PolicyObject readPolicyObject() {
return tdfReader.readPolicyObject();
}
}

private static String calculateSignature(byte[] data, byte[] secret, Config.IntegrityAlgorithm algorithm) {
Expand Down Expand Up @@ -411,13 +417,6 @@ public TDFObject createTDF(InputStream payload,
StringBuilder aggregateHash = new StringBuilder();
byte[] readBuf = new byte[tdfConfig.defaultSegmentSize];

MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new SDKException("error creating SHA-256 message digest", e);
}

tdfObject.manifest.encryptionInformation.integrityInformation.segments = new ArrayList<>();
long totalSize = 0;
boolean finished;
Expand Down Expand Up @@ -487,7 +486,7 @@ public TDFObject createTDF(InputStream payload,
tdfObject.manifest.payload.isEncrypted = true;

List<Manifest.Assertion> signedAssertions = new ArrayList<>();
;

for (var assertionConfig : tdfConfig.assertionConfigList) {
var assertion = new Manifest.Assertion();
assertion.id = assertionConfig.id;
Expand Down Expand Up @@ -538,18 +537,6 @@ public List<String> defaultKases(TDFConfig config) {
return defk;
}

private void fillInPublicKeyInfo(List<Config.KASInfo> kasInfoList, SDK.KAS kas) {
for (var kasInfo : kasInfoList) {
if (kasInfo.PublicKey != null && !kasInfo.PublicKey.isBlank()) {
continue;
}
logger.info("no public key provided for KAS at {}, retrieving", kasInfo.URL);
Config.KASInfo getKasInfo = kas.getPublicKey(kasInfo);
kasInfo.PublicKey = getKasInfo.PublicKey;
kasInfo.KID = getKasInfo.KID;
}
}

public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas,
Config.AssertionVerificationKeys... assertionVerificationKeys)
throws NotValidateRootSignature, SegmentSizeMismatch,
Expand All @@ -562,8 +549,8 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas,
String unencryptedMetadata = null;

Set<String> knownSplits = new HashSet<String>();
Set<String> foundSplits = new HashSet<String>();
;
Set<String> foundSplits = new HashSet<>();

Map<Autoconfigure.KeySplitStep, Exception> skippedSplits = new HashMap<>();
boolean mixedSplits = manifest.encryptionInformation.keyAccessObj.size() > 1 &&
(manifest.encryptionInformation.keyAccessObj.get(0).sid != null) &&
Expand Down
16 changes: 13 additions & 3 deletions sdk/src/main/java/io/opentdf/platform/sdk/TDFReader.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package io.opentdf.platform.sdk;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
Expand All @@ -12,7 +14,7 @@

public class TDFReader {

private final ZipReader.Entry manifest;
private final ZipReader.Entry manifestEntry;
private final InputStream payload;

public TDFReader(SeekableByteChannel tdf) throws IOException {
Expand All @@ -27,14 +29,14 @@ public TDFReader(SeekableByteChannel tdf) throws IOException {
throw new IllegalArgumentException("tdf doesn't contain a payload");
}

manifest = entries.get(TDF_MANIFEST_FILE_NAME);
manifestEntry = entries.get(TDF_MANIFEST_FILE_NAME);
payload = entries.get(TDF_PAYLOAD_FILE_NAME).getData();
}

public String manifest() {
var out = new ByteArrayOutputStream();
try {
manifest.getData().transferTo(out);
manifestEntry.getData().transferTo(out);
} catch (IOException e) {
throw new SDKException("error retrieving manifest from zip file", e);
}
Expand All @@ -54,4 +56,12 @@ int readPayloadBytes(byte[] buf) {
}
return totalRead;
}

public PolicyObject readPolicyObject() {
try (var reader = new BufferedReader(new InputStreamReader(manifestEntry.getData()))){
return Manifest.readPolicyObject(reader);
} catch (IOException e) {
throw new SDKException("error reading policy object", e);
}
}
}
7 changes: 7 additions & 0 deletions sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Base64;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.lenient;
Expand Down Expand Up @@ -120,6 +121,7 @@ void testSimpleTDFEncryptAndDecrypt() throws Exception {
Config.withAutoconfigure(false),
Config.withKasInformation(getKASInfos()),
Config.withMetaData("here is some metadata"),
Config.withDataAttributes("https://example.org/attr/a/value/b", "https://example.org/attr/c/value/d"),
Config.withAssertionConfig(assertion1));

String plainText = "this is extremely sensitive stuff!!!";
Expand All @@ -144,6 +146,11 @@ void testSimpleTDFEncryptAndDecrypt() throws Exception {
.withFailMessage("extracted data does not match")
.isEqualTo(plainText);
assertThat(reader.getMetadata()).isEqualTo("here is some metadata");

var policyObject = reader.readPolicyObject();
assertThat(policyObject).isNotNull();
assertThat(policyObject.body.dataAttributes.stream().map(a -> a.attribute).collect(Collectors.toList())).asList()
.containsExactlyInAnyOrder("https://example.org/attr/a/value/b", "https://example.org/attr/c/value/d");
}

@Test
Expand Down
Loading