Skip to content

Commit

Permalink
use a readresolve
Browse files Browse the repository at this point in the history
  • Loading branch information
elizabethhealy committed Nov 20, 2024
1 parent 2342df3 commit b1dec75
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 26 deletions.
52 changes: 52 additions & 0 deletions sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Object>, JsonSerializer<Object> {
// public static Logger logger = LoggerFactory.getLogger(AssertionSerializer.class);
// @Override
// public List<Assertion> 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<Object>, JsonSerializer<Object> {
// @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<Assertion> 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);
}
Expand Down
52 changes: 26 additions & 26 deletions sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
64 changes: 64 additions & 0 deletions sdk/src/test/java/io/opentdf/platform/sdk/ManifestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);

}
}

0 comments on commit b1dec75

Please sign in to comment.