From 4541fbbb5cc0faba018312e287178ea20469ca51 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Tue, 19 Nov 2024 11:59:42 -0500 Subject: [PATCH 1/9] add check for null manifest assertions --- .../io/opentdf/platform/sdk/Manifest.java | 3 +- .../java/io/opentdf/platform/sdk/TDF.java | 50 ++++++++++--------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java index 03075664..01502bba 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -51,7 +51,8 @@ public boolean equals(Object o) { return false; Manifest manifest = (Manifest) o; return Objects.equals(encryptionInformation, manifest.encryptionInformation) - && Objects.equals(payload, manifest.payload) && Objects.equals(assertions, manifest.assertions); + && Objects.equals(payload, manifest.payload) + && (manifest.assertions != null && Objects.equals(assertions, manifest.assertions)); } @Override diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java index 4c6eb6da..363d3583 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -695,35 +695,37 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } // Validate assertions - for (var assertion : manifest.assertions) { - // Skip assertion verification if disabled - if (tdfReaderConfig.disableAssertionVerification) { - break; - } + if (manifest.assertions != null) { + for (var assertion : manifest.assertions) { + // Skip assertion verification if disabled + if (tdfReaderConfig.disableAssertionVerification) { + break; + } - // Set default to HS256 - var assertionKey = new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.HS256, payloadKey); - Config.AssertionVerificationKeys assertionVerificationKeys = tdfReaderConfig.assertionVerificationKeys; - if (!assertionVerificationKeys.isEmpty()) { - var keyForAssertion = assertionVerificationKeys.getKey(assertion.id); - if (keyForAssertion != null) { - assertionKey = keyForAssertion; + // Set default to HS256 + var assertionKey = new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.HS256, payloadKey); + Config.AssertionVerificationKeys assertionVerificationKeys = tdfReaderConfig.assertionVerificationKeys; + if (!assertionVerificationKeys.isEmpty()) { + var keyForAssertion = assertionVerificationKeys.getKey(assertion.id); + if (keyForAssertion != null) { + assertionKey = keyForAssertion; + } } - } - var hashValues = assertion.verify(assertionKey); - var assertionAsJson = gson.toJson(assertion); - JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); - var hashOfAssertion = Hex.encodeHexString(digest.digest(jc.getEncodedUTF8())); - var signature = aggregateHash + hashOfAssertion; - var encodeSignature = Base64.getEncoder().encodeToString(signature.getBytes()); + var hashValues = assertion.verify(assertionKey); + var assertionAsJson = gson.toJson(assertion); + JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); + var hashOfAssertion = Hex.encodeHexString(digest.digest(jc.getEncodedUTF8())); + var signature = aggregateHash + hashOfAssertion; + var encodeSignature = Base64.getEncoder().encodeToString(signature.getBytes()); - if (!Objects.equals(hashOfAssertion, hashValues.getAssertionHash())) { - throw new AssertionException("assertion hash mismatch", assertion.id); - } + if (!Objects.equals(hashOfAssertion, hashValues.getAssertionHash())) { + throw new AssertionException("assertion hash mismatch", assertion.id); + } - if (!Objects.equals(encodeSignature, hashValues.getSignature())) { - throw new AssertionException("failed integrity check on assertion signature", assertion.id); + if (!Objects.equals(encodeSignature, hashValues.getSignature())) { + throw new AssertionException("failed integrity check on assertion signature", assertion.id); + } } } From 2342df36c386e087d9d2b7d798077b67f8f53cd4 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Tue, 19 Nov 2024 12:00:25 -0500 Subject: [PATCH 2/9] dont need equals null check --- sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java index 01502bba..03075664 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -51,8 +51,7 @@ public boolean equals(Object o) { return false; Manifest manifest = (Manifest) o; return Objects.equals(encryptionInformation, manifest.encryptionInformation) - && Objects.equals(payload, manifest.payload) - && (manifest.assertions != null && Objects.equals(assertions, manifest.assertions)); + && Objects.equals(payload, manifest.payload) && Objects.equals(assertions, manifest.assertions); } @Override From b1dec756a8bf614f1c24b26909b2f2ff95e5c0cc Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 20 Nov 2024 10:50:07 -0500 Subject: [PATCH 3/9] use a readresolve --- .../io/opentdf/platform/sdk/Manifest.java | 52 +++++++++++++++ .../java/io/opentdf/platform/sdk/TDF.java | 52 +++++++-------- .../io/opentdf/platform/sdk/ManifestTest.java | 64 +++++++++++++++++++ 3 files changed, 142 insertions(+), 26 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java index 03075664..aff25c7c 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -15,6 +15,10 @@ import org.apache.commons.codec.binary.Hex; import org.erdtman.jcs.JsonCanonicalizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.Reader; @@ -454,10 +458,58 @@ private JWSVerifier createVerifier(AssertionConfig.AssertionKey assertionKey) th } } + // // Cpublic static Logger logger = LoggerFactory.getLogger(TDF.class);ustom deserializer for the assertions field + // private static class AssertionSerializer implements JsonDeserializer, JsonSerializer { + // public static Logger logger = LoggerFactory.getLogger(AssertionSerializer.class); + // @Override + // public List deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + // logger.info("deserializing json assertions"); + // logger.info(json.toString()); + // if (json == null || json.isJsonNull()) { + // logger.info("found null"); + // return new ArrayList<>(); // Replace null with an empty list + // } + // // Deserialize the list normally if it exists + // return new Gson().fromJson(json, typeOfT); + // } + // @Override + // public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) { + // return context.serialize(src, typeOfSrc); + // } + // } + + // private static class PolicyBindingSerializer implements JsonDeserializer, JsonSerializer { + // @Override + // public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + // throws JsonParseException { + // if (json.isJsonObject()) { + // return context.deserialize(json, Manifest.PolicyBinding.class); + // } else if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isString()) { + // return json.getAsString(); + // } else { + // throw new JsonParseException("Unexpected type for policyBinding"); + // } + // } + + // @Override + // public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) { + // return context.serialize(src, typeOfSrc); + // } + // } + public EncryptionInformation encryptionInformation; public Payload payload; + // @JsonAdapter(AssertionSerializer.class) public List assertions = new ArrayList<>(); + // Ensure assertions is never null after deserialization + private Object readResolve() { + if (assertions == null) { + assertions = new ArrayList<>(); + } + return this; + } + private static Manifest readManifest(Reader reader) { return gson.fromJson(reader, Manifest.class); } diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java index 363d3583..f5ea5cfc 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -695,37 +695,37 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } // Validate assertions - if (manifest.assertions != null) { - for (var assertion : manifest.assertions) { - // Skip assertion verification if disabled - if (tdfReaderConfig.disableAssertionVerification) { - break; - } + logger.info("ASS:"); + logger.info(manifest.assertions.toString()); + for (var assertion : manifest.assertions) { + // Skip assertion verification if disabled + if (tdfReaderConfig.disableAssertionVerification) { + break; + } - // Set default to HS256 - var assertionKey = new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.HS256, payloadKey); - Config.AssertionVerificationKeys assertionVerificationKeys = tdfReaderConfig.assertionVerificationKeys; - if (!assertionVerificationKeys.isEmpty()) { - var keyForAssertion = assertionVerificationKeys.getKey(assertion.id); - if (keyForAssertion != null) { - assertionKey = keyForAssertion; - } + // Set default to HS256 + var assertionKey = new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.HS256, payloadKey); + Config.AssertionVerificationKeys assertionVerificationKeys = tdfReaderConfig.assertionVerificationKeys; + if (!assertionVerificationKeys.isEmpty()) { + var keyForAssertion = assertionVerificationKeys.getKey(assertion.id); + if (keyForAssertion != null) { + assertionKey = keyForAssertion; } + } - var hashValues = assertion.verify(assertionKey); - var assertionAsJson = gson.toJson(assertion); - JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); - var hashOfAssertion = Hex.encodeHexString(digest.digest(jc.getEncodedUTF8())); - var signature = aggregateHash + hashOfAssertion; - var encodeSignature = Base64.getEncoder().encodeToString(signature.getBytes()); + var hashValues = assertion.verify(assertionKey); + var assertionAsJson = gson.toJson(assertion); + JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); + var hashOfAssertion = Hex.encodeHexString(digest.digest(jc.getEncodedUTF8())); + var signature = aggregateHash + hashOfAssertion; + var encodeSignature = Base64.getEncoder().encodeToString(signature.getBytes()); - if (!Objects.equals(hashOfAssertion, hashValues.getAssertionHash())) { - throw new AssertionException("assertion hash mismatch", assertion.id); - } + if (!Objects.equals(hashOfAssertion, hashValues.getAssertionHash())) { + throw new AssertionException("assertion hash mismatch", assertion.id); + } - if (!Objects.equals(encodeSignature, hashValues.getSignature())) { - throw new AssertionException("failed integrity check on assertion signature", assertion.id); - } + if (!Objects.equals(encodeSignature, hashValues.getSignature())) { + throw new AssertionException("failed integrity check on assertion signature", assertion.id); } } diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java index cc169d2f..ae95f021 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java @@ -9,6 +9,7 @@ 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 { @@ -90,4 +91,67 @@ 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().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); + + } } From fc062c9ccd4aba15a313dde36ea8b48ade69f2d9 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 20 Nov 2024 11:14:09 -0500 Subject: [PATCH 4/9] use manifest deserializer --- .../io/opentdf/platform/sdk/Manifest.java | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java index aff25c7c..74dc1f10 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -1,6 +1,7 @@ package io.opentdf.platform.sdk; import com.google.gson.*; +// import com.google.gson.reflect.TypeToken; import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; import com.nimbusds.jose.*; @@ -11,14 +12,15 @@ import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; +// import io.opentdf.platform.sdk.Manifest.ManifestDeserializer; import io.opentdf.platform.sdk.TDF.AssertionException; import org.apache.commons.codec.binary.Hex; import org.erdtman.jcs.JsonCanonicalizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +// import org.slf4j.Logger; +// import org.slf4j.LoggerFactory; +// import org.slf4j.Logger; +// import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.Reader; @@ -502,12 +504,47 @@ private JWSVerifier createVerifier(AssertionConfig.AssertionKey assertionKey) th // @JsonAdapter(AssertionSerializer.class) public List assertions = new ArrayList<>(); - // Ensure assertions is never null after deserialization - private Object readResolve() { - if (assertions == null) { - assertions = new ArrayList<>(); + // // Ensure assertions is never null after deserialization + // private Object readResolve() { + // if (assertions == null) { + // assertions = new ArrayList<>(); + // } + // return this; + // } + + // @JsonAdapter(ManifestDeserializer.class) + // class ManifestDeserializer implements JsonDeserializer { + // @Override + // public Manifest deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + // JsonObject jsonObject = json.getAsJsonObject(); + // Manifest manifest = new Manifest(); + + // // Handle the `assertions` field, replacing null with an empty list + // JsonElement assertionsElement = jsonObject.get("assertions"); + // if (assertionsElement == null || assertionsElement.isJsonNull()) { + // manifest.assertions = new ArrayList<>(); + // } else { + // // Deserialize the list normally + // manifest.assertions = new Gson().fromJson(assertionsElement, new TypeToken>() {}.getType()); } + + // return manifest; + // } + // } + + @JsonAdapter(ManifestDeserializer.class) // Custom deserializer + public static class ManifestDeserializer implements JsonDeserializer { + @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; } - return this; } private static Manifest readManifest(Reader reader) { From 677c86c23373a5a333093598785017069daf7833 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 20 Nov 2024 11:23:03 -0500 Subject: [PATCH 5/9] change jsonadapter annotation --- sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java index 74dc1f10..b42fafc2 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -42,6 +42,7 @@ * of data integrity, encryption, payload, and assertions within a certain * context. */ +@JsonAdapter(Manifest.ManifestDeserializer.class) // Custom deserializer public class Manifest { private static final String kAssertionHash = "assertionHash"; @@ -531,7 +532,6 @@ private JWSVerifier createVerifier(AssertionConfig.AssertionKey assertionKey) th // } // } - @JsonAdapter(ManifestDeserializer.class) // Custom deserializer public static class ManifestDeserializer implements JsonDeserializer { @Override public Manifest deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { From a32a60e735695e81bced1b7adf7ee6893a71642a Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 20 Nov 2024 11:32:10 -0500 Subject: [PATCH 6/9] dont use jsonadapter annotation, call deserializer manually --- .../main/java/io/opentdf/platform/sdk/Manifest.java | 5 +++-- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 6 +++++- .../java/io/opentdf/platform/sdk/ZipReaderTest.java | 10 +++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java index b42fafc2..5ad91293 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -42,13 +42,14 @@ * of data integrity, encryption, payload, and assertions within a certain * context. */ -@JsonAdapter(Manifest.ManifestDeserializer.class) // Custom deserializer 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) { diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java index f5ea5cfc..92a7be8f 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -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; @@ -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) { diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/ZipReaderTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/ZipReaderTest.java index 1eb55307..5c47710c 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/ZipReaderTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/ZipReaderTest.java @@ -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; @@ -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(); } } From 9b3ca82ced23b82acd5cad3486c161ff12fe39d3 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 20 Nov 2024 11:45:39 -0500 Subject: [PATCH 7/9] add logging --- .../java/io/opentdf/platform/sdk/Manifest.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java index 5ad91293..51ff56f0 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -17,10 +17,10 @@ import org.apache.commons.codec.binary.Hex; import org.erdtman.jcs.JsonCanonicalizer; -// import org.slf4j.Logger; -// import org.slf4j.LoggerFactory; -// import org.slf4j.Logger; -// import org.slf4j.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.Reader; @@ -533,16 +533,20 @@ private JWSVerifier createVerifier(AssertionConfig.AssertionKey assertionKey) th // } // } - public static class ManifestDeserializer implements JsonDeserializer { + public static class ManifestDeserializer implements JsonDeserializer { + public static Logger logger = LoggerFactory.getLogger(ManifestDeserializer.class); @Override public Manifest deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + logger.info("deserializing manifest"); // Let Gson handle the default deserialization of the object first Manifest manifest = new Gson().fromJson(json, typeOfT); - + logger.info("after gson"); // Now check if the `assertions` field is null and replace it with an empty list if necessary if (manifest.assertions == null) { + logger.info("found null"); manifest.assertions = new ArrayList<>(); // Replace null with empty list } + logger.info(manifest.assertions.toString()); return manifest; } From 1a2d59ae6af4fbfe623eecbffff6ff65dface9ba Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 20 Nov 2024 11:49:14 -0500 Subject: [PATCH 8/9] add adapters to tests --- .../java/io/opentdf/platform/sdk/ManifestTest.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java index ae95f021..7a3a9c77 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java @@ -4,6 +4,8 @@ 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; @@ -63,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 @@ -143,7 +147,9 @@ void testAssertionNull() { "}"; 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 for sanity check From 962d5d06072fe68ccdcbeee67245955140867009 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 20 Nov 2024 11:57:07 -0500 Subject: [PATCH 9/9] cleanup --- .../io/opentdf/platform/sdk/Manifest.java | 79 ------------------- .../java/io/opentdf/platform/sdk/TDF.java | 2 - 2 files changed, 81 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java index 51ff56f0..479d7b0e 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -1,7 +1,6 @@ package io.opentdf.platform.sdk; import com.google.gson.*; -// import com.google.gson.reflect.TypeToken; import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; import com.nimbusds.jose.*; @@ -12,15 +11,10 @@ import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; -// import io.opentdf.platform.sdk.Manifest.ManifestDeserializer; import io.opentdf.platform.sdk.TDF.AssertionException; import org.apache.commons.codec.binary.Hex; import org.erdtman.jcs.JsonCanonicalizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.Reader; @@ -462,92 +456,19 @@ private JWSVerifier createVerifier(AssertionConfig.AssertionKey assertionKey) th } } - // // Cpublic static Logger logger = LoggerFactory.getLogger(TDF.class);ustom deserializer for the assertions field - // private static class AssertionSerializer implements JsonDeserializer, JsonSerializer { - // public static Logger logger = LoggerFactory.getLogger(AssertionSerializer.class); - // @Override - // public List deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - // logger.info("deserializing json assertions"); - // logger.info(json.toString()); - // if (json == null || json.isJsonNull()) { - // logger.info("found null"); - // return new ArrayList<>(); // Replace null with an empty list - // } - // // Deserialize the list normally if it exists - // return new Gson().fromJson(json, typeOfT); - // } - // @Override - // public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) { - // return context.serialize(src, typeOfSrc); - // } - // } - - // private static class PolicyBindingSerializer implements JsonDeserializer, JsonSerializer { - // @Override - // public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - // throws JsonParseException { - // if (json.isJsonObject()) { - // return context.deserialize(json, Manifest.PolicyBinding.class); - // } else if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isString()) { - // return json.getAsString(); - // } else { - // throw new JsonParseException("Unexpected type for policyBinding"); - // } - // } - - // @Override - // public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) { - // return context.serialize(src, typeOfSrc); - // } - // } - public EncryptionInformation encryptionInformation; public Payload payload; - // @JsonAdapter(AssertionSerializer.class) public List assertions = new ArrayList<>(); - // // Ensure assertions is never null after deserialization - // private Object readResolve() { - // if (assertions == null) { - // assertions = new ArrayList<>(); - // } - // return this; - // } - - // @JsonAdapter(ManifestDeserializer.class) - // class ManifestDeserializer implements JsonDeserializer { - // @Override - // public Manifest deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - // JsonObject jsonObject = json.getAsJsonObject(); - // Manifest manifest = new Manifest(); - - // // Handle the `assertions` field, replacing null with an empty list - // JsonElement assertionsElement = jsonObject.get("assertions"); - // if (assertionsElement == null || assertionsElement.isJsonNull()) { - // manifest.assertions = new ArrayList<>(); - // } else { - // // Deserialize the list normally - // manifest.assertions = new Gson().fromJson(assertionsElement, new TypeToken>() {}.getType()); } - - // return manifest; - // } - // } - public static class ManifestDeserializer implements JsonDeserializer { - public static Logger logger = LoggerFactory.getLogger(ManifestDeserializer.class); @Override public Manifest deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - logger.info("deserializing manifest"); // Let Gson handle the default deserialization of the object first Manifest manifest = new Gson().fromJson(json, typeOfT); - logger.info("after gson"); // Now check if the `assertions` field is null and replace it with an empty list if necessary if (manifest.assertions == null) { - logger.info("found null"); manifest.assertions = new ArrayList<>(); // Replace null with empty list } - logger.info(manifest.assertions.toString()); - return manifest; } } diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java index 92a7be8f..124ebe0f 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -699,8 +699,6 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } // Validate assertions - logger.info("ASS:"); - logger.info(manifest.assertions.toString()); for (var assertion : manifest.assertions) { // Skip assertion verification if disabled if (tdfReaderConfig.disableAssertionVerification) {