Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.opentdf.platform;

import io.opentdf.platform.sdk.Manifest;
import io.opentdf.platform.sdk.PolicyObject;
import io.opentdf.platform.sdk.SDK;

import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

public class GetManifestInformation {
public static void main(String[] args) throws IOException {
FileChannel tdfStream = FileChannel.open(Path.of(args[0]), StandardOpenOption.READ);

Manifest manifest = SDK.readManifest(tdfStream);
System.out.println("loaded a tdf with key access type: " + manifest.encryptionInformation.keyAccessType);

PolicyObject policyObject = SDK.decodePolicyObject(manifest);
System.out.println("the policy has uuid: " + policyObject.uuid);
}
}

8 changes: 3 additions & 5 deletions sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
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;
Expand Down Expand Up @@ -500,8 +499,8 @@ public AssertionConfig.Statement deserialize(JsonElement json, Type typeOfT, Jso
public EncryptionInformation encryptionInformation;
public Payload payload;
public List<Assertion> assertions = new ArrayList<>();
protected static Manifest readManifest(Reader reader) {
Manifest result = gson.fromJson(reader, Manifest.class);
protected static Manifest readManifest(String manifestJson) {
Manifest result = gson.fromJson(manifestJson, Manifest.class);
if (result.assertions == null) {
result.assertions = new ArrayList<>();
}
Expand Down Expand Up @@ -539,8 +538,7 @@ protected static Manifest readManifest(Reader reader) {
return result;
}

static PolicyObject readPolicyObject(Reader reader) {
var manifest = readManifest(reader);
static PolicyObject decodePolicyObject(Manifest manifest) {
var policyBase64 = manifest.encryptionInformation.policy;
var policyBytes = Base64.getDecoder().decode(policyBase64);
var policyJson = new String(policyBytes, StandardCharsets.UTF_8);
Expand Down
24 changes: 24 additions & 0 deletions sdk/src/main/java/io/opentdf/platform/sdk/SDK.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,30 @@ public static boolean isTDF(SeekableByteChannel channel) {
&& entries.stream().anyMatch(e -> "0.payload".equals(e.getName()));
}

/**
* Reads the manifest without decrypting the TDF
* @param tdfBytes A SeekableByteChannel containing the TDF data
* @return
* @throws SDKException
* @throws IOException
*/
public static Manifest readManifest(SeekableByteChannel tdfBytes) throws SDKException, IOException {
TDFReader reader = new TDFReader(tdfBytes);
String manifestJson = reader.manifest();
return Manifest.readManifest(manifestJson);
}

/**
* Decodes a PolicyObject from the manifest. Use {@link SDK#decodePolicyObject(Manifest)}
* to get the manifest from a TDF.
* @param manifest
* @return
* @throws SDKException
*/
public static PolicyObject decodePolicyObject(Manifest manifest) throws SDKException {
return Manifest.decodePolicyObject(manifest);
}

public String getPlatformUrl() {
return platformUrl;
}
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ Reader loadTDF(SeekableByteChannel tdf, Config.TDFReaderConfig tdfReaderConfig)
TDFReader tdfReader = new TDFReader(tdf);
String manifestJson = tdfReader.manifest();
// use Manifest.readManifest in order to validate the Manifest input
Manifest manifest = Manifest.readManifest(new StringReader(manifestJson));
Manifest manifest = Manifest.readManifest(manifestJson);
byte[] payloadKey = new byte[GCM_KEY_SIZE];
String unencryptedMetadata = null;

Expand Down
8 changes: 3 additions & 5 deletions sdk/src/main/java/io/opentdf/platform/sdk/TDFReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,8 @@ int readPayloadBytes(byte[] buf) {
}

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);
}
String manifestJson = manifest();
Manifest manifest = Manifest.readManifest(manifestJson);
return Manifest.decodePolicyObject(manifest);
}
}
9 changes: 5 additions & 4 deletions sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void testManifestMarshalAndUnMarshal() {
" }\n" +
"}";

Manifest manifest = Manifest.readManifest(new StringReader(kManifestJsonFromTDF));
Manifest manifest = Manifest.readManifest(kManifestJsonFromTDF);

// Test payload
assertEquals(manifest.payload.url, "0.payload");
Expand All @@ -85,7 +85,7 @@ void testManifestMarshalAndUnMarshal() {
assertEquals(manifest.encryptionInformation.integrityInformation.segments.get(0).segmentSize, 1048576);

var serialized = Manifest.toJson(manifest);
var deserializedAgain = Manifest.readManifest(new StringReader(serialized));
var deserializedAgain = Manifest.readManifest(serialized);

assertEquals(manifest, deserializedAgain, "something changed when we deserialized -> serialized -> deserialized");
}
Expand Down Expand Up @@ -140,7 +140,7 @@ void testAssertionNull() {
" \"assertions\": null\n"+
"}";

Manifest manifest = Manifest.readManifest(new StringReader(kManifestJsonFromTDF));
Manifest manifest = Manifest.readManifest(kManifestJsonFromTDF);

// Test payload for sanity check
assertEquals(manifest.payload.url, "0.payload");
Expand All @@ -155,7 +155,8 @@ void testReadingManifestWithObjectStatementValue() throws IOException {
final Manifest manifest;
try (var mStream = getClass().getResourceAsStream("/io.opentdf.platform.sdk.TestData/manifest-with-object-statement-value.json")) {
assert mStream != null;
manifest = Manifest.readManifest(new InputStreamReader(mStream)) ;
var manifestJson = new String(mStream.readAllBytes());
manifest = Manifest.readManifest(manifestJson);
}

assertThat(manifest.assertions).hasSize(2);
Expand Down
15 changes: 15 additions & 0 deletions sdk/src/test/java/io/opentdf/platform/sdk/SDKTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ public SeekableByteChannel truncate(long size) {
assertThat(SDK.isTDF(chan)).isFalse();
}

@Test
void testExaminingManifest() throws IOException {
try (var tdfStream = SDKTest.class.getClassLoader().getResourceAsStream("sample.txt.tdf")) {
assertThat(tdfStream)
.withFailMessage("sample.txt.tdf not found in classpath")
.isNotNull();
var manifest = SDK.readManifest(new SeekableInMemoryByteChannel(tdfStream.readAllBytes()));
assertThat(manifest).isNotNull();
assertThat(manifest.encryptionInformation.integrityInformation.encryptedSegmentSizeDefault)
.isEqualTo(1048604);
var policyObject = SDK.decodePolicyObject(manifest);
assertThat(policyObject.uuid).isEqualTo("98bb8a81-5217-4a31-8852-932d29d71aac");
}
}

@Test
void testReadingRandomBytes() {
var tdf = new byte[2023];
Expand Down