Skip to content

Commit

Permalink
fix: Correct null assertions when deserializing (#211)
Browse files Browse the repository at this point in the history
previously this would throw null pointer exception if `"assertions":
null` was in the manifest, this should stop that error and assign
assertions and empty arraylist if it is null on deserialization
  • Loading branch information
elizabethhealy authored Nov 21, 2024
1 parent 1ee1367 commit b075194
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 4 deletions.
17 changes: 16 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 @@ -41,7 +41,9 @@ public class Manifest {
private static final String kAssertionHash = "assertionHash";
private static final String kAssertionSignature = "assertionSig";

private static final Gson gson = new Gson();
private static final Gson gson = new GsonBuilder()
.registerTypeAdapter(Manifest.class, new ManifestDeserializer())
.create();

@Override
public boolean equals(Object o) {
Expand Down Expand Up @@ -458,6 +460,19 @@ private JWSVerifier createVerifier(AssertionConfig.AssertionKey assertionKey) th
public Payload payload;
public List<Assertion> assertions = new ArrayList<>();

public static class ManifestDeserializer implements JsonDeserializer<Object> {
@Override
public Manifest deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
// Let Gson handle the default deserialization of the object first
Manifest manifest = new Gson().fromJson(json, typeOfT);
// Now check if the `assertions` field is null and replace it with an empty list if necessary
if (manifest.assertions == null) {
manifest.assertions = new ArrayList<>(); // Replace null with empty list
}
return manifest;
}
}

private static Manifest readManifest(Reader reader) {
return gson.fromJson(reader, Manifest.class);
}
Expand Down
6 changes: 5 additions & 1 deletion sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package io.opentdf.platform.sdk;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.nimbusds.jose.*;

import io.opentdf.platform.policy.Value;
import io.opentdf.platform.policy.attributes.AttributesServiceGrpc.AttributesServiceFutureStub;
import io.opentdf.platform.sdk.Config.TDFConfig;
import io.opentdf.platform.sdk.Manifest.ManifestDeserializer;
import io.opentdf.platform.sdk.Autoconfigure.AttributeValueFQN;
import io.opentdf.platform.sdk.Config.KASInfo;

Expand Down Expand Up @@ -75,7 +77,9 @@ public TDF() {

private static final SecureRandom sRandom = new SecureRandom();

private static final Gson gson = new Gson();
private static final Gson gson = new GsonBuilder()
.registerTypeAdapter(Manifest.class, new ManifestDeserializer())
.create();

public class SplitKeyException extends IOException {
public SplitKeyException(String errorMessage) {
Expand Down
72 changes: 71 additions & 1 deletion sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import io.opentdf.platform.sdk.Manifest.ManifestDeserializer;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class ManifestTest {
Expand Down Expand Up @@ -62,7 +65,9 @@ void testManifestMarshalAndUnMarshal() {
"}";

GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.setPrettyPrinting().create();
Gson gson = gsonBuilder.setPrettyPrinting()
.registerTypeAdapter(Manifest.class, new ManifestDeserializer())
.create();
Manifest manifest = gson.fromJson(kManifestJsonFromTDF, Manifest.class);

// Test payload
Expand Down Expand Up @@ -90,4 +95,69 @@ void testManifestMarshalAndUnMarshal() {

assertEquals(manifest, deserializedAgain, "something changed when we deserialized -> serialized -> deserialized");
}

@Test
void testAssertionNull() {
String kManifestJsonFromTDF = "{\n" +
" \"encryptionInformation\": {\n" +
" \"integrityInformation\": {\n" +
" \"encryptedSegmentSizeDefault\": 1048604,\n" +
" \"rootSignature\": {\n" +
" \"alg\": \"HS256\",\n" +
" \"sig\": \"N2Y1ZjJlYWE4N2EzNjc2Nzc3NzgxNGU2ZGE1NmI4NDNhZTI5ZWY5NDc2OGI1ZTMzYTIyMTU4MDBlZTY3NzQzNA==\"\n" +
" },\n" +
" \"segmentHashAlg\": \"GMAC\",\n" +
" \"segmentSizeDefault\": 1048576,\n" +
" \"segments\": [\n" +
" {\n" +
" \"encryptedSegmentSize\": 41,\n" +
" \"hash\": \"ZWEyZTkwYjZiZThmYWZhNzg5ZmNjOWIyZTA2Njg5OTQ=\",\n" +
" \"segmentSize\": 1048576\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"keyAccess\": [\n" +
" {\n" +
" \"policyBinding\": {\n" +
" \"alg\": \"HS256\",\n" +
" \"hash\": \"YTgzNThhNzc5NWRhMjdjYThlYjk4ZmNmODliNzc2Y2E5ZmZiZDExZDQ3OTM5ODFjZTRjNmE3MmVjOTUzZTFlMA==\"\n" +
" },\n" +
" \"protocol\": \"kas\",\n" +
" \"type\": \"wrapped\",\n" +
" \"url\": \"http://localhost:65432/kas\",\n" +
" \"wrappedKey\": \"dJ3PdscXWvLv/juSkL7EMhl4lgLSBfI9EeoG2ct6NeSwPkPm/ieMF6ryDQjGeqZttoLlx2qBCVpik/BooGd/FtpYMIF/7a5RFTJ3G+o4Lww/zG6zIgV2APEPO+Gp7ORlFyMNJfn6Tj8ChTweKBqfXEXLihTV6sTZFtsWjdV96Z4KXbLe8tGpkXBpUAsSlmjcDJ920vrqnp3dvt2GwfmAiRWYCMXxnqUECqN5kVXMJywcvHatv2ZJSA/ixjDOrix+MocDJ69K/yFA17DXgfjf5X4SLyS0XgaZcXsdACBb+ogBlPw6vAbBrAyqI0Vi1msMRYNDS+FTl1yWEXl1HpyyCw==\"\n" +
" }\n" +
" ],\n" +
" \"method\": {\n" +
" \"algorithm\": \"AES-256-GCM\",\n" +
" \"isStreamable\": true,\n" +
" \"iv\": \"tozen81HLtZktNOP\"\n" +
" },\n" +
" \"policy\": \"eyJib2R5Ijp7ImRhdGFBdHRyaWJ1dGVzIjpbXSwiZGlzc2VtIjpbXX0sInV1aWQiOiJiNTM3MDllMy03NmE3LTRmYzctOGEwZi1mZDBhNjcyNmVhM2YifQ==\",\n" +
" \"type\": \"split\"\n" +
" },\n" +
" \"payload\": {\n" +
" \"isEncrypted\": true,\n" +
" \"mimeType\": \"application/octet-stream\",\n" +
" \"protocol\": \"zip\",\n" +
" \"type\": \"reference\",\n" +
" \"url\": \"0.payload\"\n" +
" },\n" +
" \"assertions\": null\n"+
"}";

GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.setPrettyPrinting()
.registerTypeAdapter(Manifest.class, new ManifestDeserializer())
.create();
Manifest manifest = gson.fromJson(kManifestJsonFromTDF, Manifest.class);

// Test payload for sanity check
assertEquals(manifest.payload.url, "0.payload");
assertEquals(manifest.payload.isEncrypted, true);
// Test assertion deserialization
assertNotNull(manifest.assertions);
assertEquals(manifest.assertions.size(), 0);

}
}
10 changes: 9 additions & 1 deletion sdk/src/test/java/io/opentdf/platform/sdk/ZipReaderTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package io.opentdf.platform.sdk;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import io.opentdf.platform.sdk.Manifest.ManifestDeserializer;

import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
Expand Down Expand Up @@ -36,7 +40,11 @@ public void testReadingExistingZip() throws Exception {
if (entry.getName().endsWith(".json")) {
entry.getData().transferTo(stream);
var data = stream.toString(StandardCharsets.UTF_8);
var map = new Gson().fromJson(data, Map.class);
var gson = new GsonBuilder()
.registerTypeAdapter(Manifest.class, new ManifestDeserializer())
.create();
var map = gson.fromJson(data, Map.class);

assertThat(map.get("encryptionInformation")).isNotNull();
}
}
Expand Down

0 comments on commit b075194

Please sign in to comment.