From 6b26274fde82d81e88ee0eca45122da5d8910e2e Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Mon, 2 Dec 2024 16:47:39 -0500 Subject: [PATCH 01/20] remove hex-encoding --- .../io/opentdf/platform/sdk/Manifest.java | 4 +- .../java/io/opentdf/platform/sdk/TDF.java | 52 ++++++++++--------- 2 files changed, 30 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 479d7b0e..a5edc13e 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -343,7 +343,7 @@ public int hashCode() { return Objects.hash(id, type, scope, appliesToState, statement, binding); } - public String hash() throws IOException { + public byte[] hash() throws IOException { MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-256"); @@ -353,7 +353,7 @@ public String hash() throws IOException { var assertionAsJson = gson.toJson(this); JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); - return Hex.encodeHexString(digest.digest(jc.getEncodedUTF8())); + return digest.digest(jc.getEncodedUTF8()); } // Sign the assertion with the given hash and signature using the key. 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 124ebe0f..e33452fb 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -373,9 +373,8 @@ public void readPayload(OutputStream outputStream) throws TDFReadFailed, } var payloadSig = calculateSignature(readBuf, payloadKey, sigAlg); - byte[] payloadSigAsBytes = payloadSig.getBytes(StandardCharsets.UTF_8); - if (segment.hash.compareTo(Base64.getEncoder().encodeToString(payloadSigAsBytes)) != 0) { + if (segment.hash.compareTo(Base64.getEncoder().encodeToString(payloadSig)) != 0) { throw new SegmentSignatureMismatch("segment signature miss match"); } @@ -398,18 +397,16 @@ public PolicyObject readPolicyObject() { } } - private static String calculateSignature(byte[] data, byte[] secret, Config.IntegrityAlgorithm algorithm) { + private static byte[] calculateSignature(byte[] data, byte[] secret, Config.IntegrityAlgorithm algorithm) { if (algorithm == Config.IntegrityAlgorithm.HS256) { - byte[] hmac = CryptoUtils.CalculateSHA256Hmac(secret, data); - return Hex.encodeHexString(hmac); + return CryptoUtils.CalculateSHA256Hmac(secret, data); } if (kGMACPayloadLength > data.length) { throw new FailedToCreateGMAC("fail to create gmac signature"); } - byte[] gmacPayload = Arrays.copyOfRange(data, data.length - kGMACPayloadLength, data.length); - return Hex.encodeHexString(gmacPayload); + return Arrays.copyOfRange(data, data.length - kGMACPayloadLength, data.length); } public TDFObject createTDF(InputStream payload, @@ -449,7 +446,7 @@ public TDFObject createTDF(InputStream payload, long encryptedSegmentSize = tdfConfig.defaultSegmentSize + kGcmIvSize + kAesBlockSize; TDFWriter tdfWriter = new TDFWriter(outputStream); - StringBuilder aggregateHash = new StringBuilder(); + ByteArrayOutputStream aggregateHash = new ByteArrayOutputStream(); byte[] readBuf = new byte[tdfConfig.defaultSegmentSize]; tdfObject.manifest.encryptionInformation.integrityInformation.segments = new ArrayList<>(); @@ -471,7 +468,7 @@ public TDFObject createTDF(InputStream payload, } byte[] cipherData; - String segmentSig; + byte[] segmentSig; Manifest.Segment segmentInfo = new Manifest.Segment(); // encrypt @@ -479,9 +476,9 @@ public TDFObject createTDF(InputStream payload, payloadOutput.write(cipherData); segmentSig = calculateSignature(cipherData, tdfObject.payloadKey, tdfConfig.segmentIntegrityAlgorithm); - segmentInfo.hash = Base64.getEncoder().encodeToString(segmentSig.getBytes(StandardCharsets.UTF_8)); + segmentInfo.hash = Base64.getEncoder().encodeToString(segmentSig); - aggregateHash.append(segmentSig); + aggregateHash.write(segmentSig); segmentInfo.segmentSize = readThisLoop; segmentInfo.encryptedSegmentSize = cipherData.length; @@ -491,9 +488,9 @@ public TDFObject createTDF(InputStream payload, Manifest.RootSignature rootSignature = new Manifest.RootSignature(); - String rootSig = calculateSignature(aggregateHash.toString().getBytes(), + byte[] rootSig = calculateSignature(aggregateHash.toByteArray(), tdfObject.payloadKey, tdfConfig.integrityAlgorithm); - rootSignature.signature = Base64.getEncoder().encodeToString(rootSig.getBytes(StandardCharsets.UTF_8)); + rootSignature.signature = Base64.getEncoder().encodeToString(rootSig); String alg = kGmacIntegrityAlgorithm; if (tdfConfig.integrityAlgorithm == Config.IntegrityAlgorithm.HS256) { @@ -531,18 +528,22 @@ public TDFObject createTDF(InputStream payload, assertion.appliesToState = assertionConfig.appliesToState.toString(); var assertionHash = assertion.hash(); - var completeHashBuilder = new StringBuilder(aggregateHash); - completeHashBuilder.append(assertionHash); + byte[] completeHash = new byte[aggregateHash.size() + assertionHash.length]; + System.arraycopy(aggregateHash.toByteArray(), 0, completeHash, 0, aggregateHash.size()); + System.arraycopy(assertionHash, 0, completeHash, aggregateHash.size(), assertionHash.length); - var encodedHash = Base64.getEncoder().encodeToString(completeHashBuilder.toString().getBytes()); + var encodedHash = Base64.getEncoder().encodeToString(completeHash); var assertionSigningKey = new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.HS256, tdfObject.aesGcm.getKey()); if (assertionConfig.assertionKey != null && assertionConfig.assertionKey.isDefined()) { assertionSigningKey = assertionConfig.assertionKey; } - - assertion.sign(new Manifest.Assertion.HashValues(assertionHash, encodedHash), assertionSigningKey); + var hashValues = new Manifest.Assertion.HashValues( + Base64.getEncoder().encodeToString(assertionHash), + encodedHash + ); + assertion.sign(hashValues, assertionSigningKey); signedAssertions.add(assertion); } @@ -589,7 +590,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, byte[] payloadKey = new byte[GCM_KEY_SIZE]; String unencryptedMetadata = null; - Set knownSplits = new HashSet(); + Set knownSplits = new HashSet<>(); Set foundSplits = new HashSet<>(); Map skippedSplits = new HashMap<>(); @@ -681,7 +682,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } var sig = calculateSignature(aggregateHash.toByteArray(), payloadKey, sigAlg); - rootSigValue = Base64.getEncoder().encodeToString(sig.getBytes(StandardCharsets.UTF_8)); + rootSigValue = Base64.getEncoder().encodeToString(sig); } else { rootSigValue = Base64.getEncoder().encodeToString(digest.digest(aggregateHash.toString().getBytes())); @@ -698,6 +699,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, throw new SegmentSizeMismatch("mismatch encrypted segment size in manifest"); } + var aggregateSignatureBytes = aggregateHash.toByteArray(); // Validate assertions for (var assertion : manifest.assertions) { // Skip assertion verification if disabled @@ -718,11 +720,13 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, 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 hashOfAssertion = digest.digest(jc.getEncodedUTF8()); + var signature = new byte[aggregateSignatureBytes.length + hashOfAssertion.length]; + System.arraycopy(aggregateSignatureBytes, 0, signature, 0, aggregateSignatureBytes.length); + System.arraycopy(hashOfAssertion, 0, signature, aggregateSignatureBytes.length, hashOfAssertion.length); + var encodeSignature = Base64.getEncoder().encodeToString(signature); - if (!Objects.equals(hashOfAssertion, hashValues.getAssertionHash())) { + if (!Objects.equals(Base64.getEncoder().encodeToString(hashOfAssertion), hashValues.getAssertionHash())) { throw new AssertionException("assertion hash mismatch", assertion.id); } From 5d2397009eddc7d3d2a00b512ad36a451732b12b Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 3 Dec 2024 09:31:07 -0500 Subject: [PATCH 02/20] cleanup --- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e33452fb..d66135f4 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -628,7 +628,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, AesGcm aesGcm = new AesGcm(unwrappedKey); String decodedMetadata = new String(Base64.getDecoder().decode(keyAccess.encryptedMetadata), - "UTF-8"); + StandardCharsets.UTF_8); EncryptedMetadata encryptedMetadata = gson.fromJson(decodedMetadata, EncryptedMetadata.class); var encryptedData = new AesGcm.Encrypted( From 033be9f6792e474c4df33fac1e03fc33e7a8881d Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 3 Dec 2024 10:03:23 -0500 Subject: [PATCH 03/20] add back hex encoding --- .../io/opentdf/platform/sdk/Manifest.java | 31 ++++++++++++------- .../java/io/opentdf/platform/sdk/TDF.java | 18 ++++++++--- 2 files changed, 32 insertions(+), 17 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 a5edc13e..63e76424 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -1,19 +1,28 @@ package io.opentdf.platform.sdk; -import com.google.gson.*; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.nimbusds.jose.*; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.JWSSigner; +import com.nimbusds.jose.JWSVerifier; +import com.nimbusds.jose.KeyLengthException; import com.nimbusds.jose.crypto.MACSigner; import com.nimbusds.jose.crypto.MACVerifier; import com.nimbusds.jose.crypto.RSASSASigner; import com.nimbusds.jose.crypto.RSASSAVerifier; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; - import io.opentdf.platform.sdk.TDF.AssertionException; - -import org.apache.commons.codec.binary.Hex; import org.erdtman.jcs.JsonCanonicalizer; import java.io.IOException; @@ -44,21 +53,19 @@ public class Manifest { private static final Gson gson = new GsonBuilder() .registerTypeAdapter(Manifest.class, new ManifestDeserializer()) .create(); + String version; @Override public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; Manifest manifest = (Manifest) o; - return Objects.equals(encryptionInformation, manifest.encryptionInformation) - && Objects.equals(payload, manifest.payload) && Objects.equals(assertions, manifest.assertions); + return Objects.equals(version, manifest.version) && Objects.equals(encryptionInformation, manifest.encryptionInformation) && Objects.equals(payload, manifest.payload) && Objects.equals(assertions, manifest.assertions); } @Override public int hashCode() { - return Objects.hash(encryptionInformation, payload, assertions); + return Objects.hash(version, encryptionInformation, payload, assertions); } private static class PolicyBindingSerializer implements JsonDeserializer, JsonSerializer { 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 d66135f4..83bad8c2 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -38,6 +38,7 @@ */ public class TDF { + private static final String TDF_VERSION = "x.x.x"; private final long maximumSize; /** @@ -450,6 +451,7 @@ public TDFObject createTDF(InputStream payload, byte[] readBuf = new byte[tdfConfig.defaultSegmentSize]; tdfObject.manifest.encryptionInformation.integrityInformation.segments = new ArrayList<>(); + tdfObject.manifest.version = TDF_VERSION; long totalSize = 0; boolean finished; try (var payloadOutput = tdfWriter.payload()) { @@ -682,8 +684,10 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } var sig = calculateSignature(aggregateHash.toByteArray(), payloadKey, sigAlg); + if (manifest.version == null || manifest.version.isEmpty()) { + sig = Hex.encodeHexString(sig).getBytes(StandardCharsets.UTF_8); + } rootSigValue = Base64.getEncoder().encodeToString(sig); - } else { rootSigValue = Base64.getEncoder().encodeToString(digest.digest(aggregateHash.toString().getBytes())); } @@ -721,15 +725,19 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, var assertionAsJson = gson.toJson(assertion); JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); var hashOfAssertion = digest.digest(jc.getEncodedUTF8()); - var signature = new byte[aggregateSignatureBytes.length + hashOfAssertion.length]; - System.arraycopy(aggregateSignatureBytes, 0, signature, 0, aggregateSignatureBytes.length); - System.arraycopy(hashOfAssertion, 0, signature, aggregateSignatureBytes.length, hashOfAssertion.length); - var encodeSignature = Base64.getEncoder().encodeToString(signature); + if (manifest.version == null || manifest.version.isEmpty()) { + hashOfAssertion = Hex.encodeHexString(hashOfAssertion).getBytes(StandardCharsets.UTF_8); + } if (!Objects.equals(Base64.getEncoder().encodeToString(hashOfAssertion), hashValues.getAssertionHash())) { throw new AssertionException("assertion hash mismatch", assertion.id); } + var signature = new byte[aggregateSignatureBytes.length + hashOfAssertion.length]; + System.arraycopy(aggregateSignatureBytes, 0, signature, 0, aggregateSignatureBytes.length); + System.arraycopy(hashOfAssertion, 0, signature, aggregateSignatureBytes.length, hashOfAssertion.length); + var encodeSignature = Base64.getEncoder().encodeToString(signature); + if (!Objects.equals(encodeSignature, hashValues.getSignature())) { throw new AssertionException("failed integrity check on assertion signature", assertion.id); } From df2ea720c9170ab0833b22091263c1f6bc0975b9 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 3 Dec 2024 10:38:23 -0500 Subject: [PATCH 04/20] change name --- sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java | 6 +++--- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 8 +++----- 2 files changed, 6 insertions(+), 8 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 63e76424..74a49f72 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -53,19 +53,19 @@ public class Manifest { private static final Gson gson = new GsonBuilder() .registerTypeAdapter(Manifest.class, new ManifestDeserializer()) .create(); - String version; + String tdfVersion; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Manifest manifest = (Manifest) o; - return Objects.equals(version, manifest.version) && Objects.equals(encryptionInformation, manifest.encryptionInformation) && Objects.equals(payload, manifest.payload) && Objects.equals(assertions, manifest.assertions); + return Objects.equals(tdfVersion, manifest.tdfVersion) && Objects.equals(encryptionInformation, manifest.encryptionInformation) && Objects.equals(payload, manifest.payload) && Objects.equals(assertions, manifest.assertions); } @Override public int hashCode() { - return Objects.hash(version, encryptionInformation, payload, assertions); + return Objects.hash(tdfVersion, encryptionInformation, payload, assertions); } private static class PolicyBindingSerializer implements JsonDeserializer, JsonSerializer { 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 83bad8c2..2efa118f 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -17,11 +17,9 @@ 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; @@ -451,7 +449,7 @@ public TDFObject createTDF(InputStream payload, byte[] readBuf = new byte[tdfConfig.defaultSegmentSize]; tdfObject.manifest.encryptionInformation.integrityInformation.segments = new ArrayList<>(); - tdfObject.manifest.version = TDF_VERSION; + tdfObject.manifest.tdfVersion = TDF_VERSION; long totalSize = 0; boolean finished; try (var payloadOutput = tdfWriter.payload()) { @@ -684,7 +682,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } var sig = calculateSignature(aggregateHash.toByteArray(), payloadKey, sigAlg); - if (manifest.version == null || manifest.version.isEmpty()) { + if (manifest.tdfVersion == null || manifest.tdfVersion.isEmpty()) { sig = Hex.encodeHexString(sig).getBytes(StandardCharsets.UTF_8); } rootSigValue = Base64.getEncoder().encodeToString(sig); @@ -725,7 +723,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, var assertionAsJson = gson.toJson(assertion); JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); var hashOfAssertion = digest.digest(jc.getEncodedUTF8()); - if (manifest.version == null || manifest.version.isEmpty()) { + if (manifest.tdfVersion == null || manifest.tdfVersion.isEmpty()) { hashOfAssertion = Hex.encodeHexString(hashOfAssertion).getBytes(StandardCharsets.UTF_8); } From abebe46fb73b9b0e59adb69b429a0673e1e4fb46 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 3 Dec 2024 11:16:02 -0500 Subject: [PATCH 05/20] set this in a better place --- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2efa118f..1c2b08a4 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -201,6 +201,7 @@ PolicyObject createPolicyObject(List attributes private static final Base64.Encoder encoder = Base64.getEncoder(); private void prepareManifest(Config.TDFConfig tdfConfig, SDK.KAS kas) { + manifest.tdfVersion = TDF_VERSION; manifest.encryptionInformation.keyAccessType = kSplitKeyType; manifest.encryptionInformation.keyAccessObj = new ArrayList<>(); @@ -449,7 +450,6 @@ public TDFObject createTDF(InputStream payload, byte[] readBuf = new byte[tdfConfig.defaultSegmentSize]; tdfObject.manifest.encryptionInformation.integrityInformation.segments = new ArrayList<>(); - tdfObject.manifest.tdfVersion = TDF_VERSION; long totalSize = 0; boolean finished; try (var payloadOutput = tdfWriter.payload()) { From 5c4c16d6854cce2ef37955f0dfa2416935784886 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 3 Dec 2024 11:38:26 -0500 Subject: [PATCH 06/20] refactor --- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 1c2b08a4..3794119d 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -675,6 +675,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } String rootSigValue; + boolean isLegacyTdf = manifest.tdfVersion == null || manifest.tdfVersion.isEmpty(); if (manifest.payload.isEncrypted) { Config.IntegrityAlgorithm sigAlg = Config.IntegrityAlgorithm.HS256; if (rootAlgorithm.compareToIgnoreCase(kGmacIntegrityAlgorithm) == 0) { @@ -682,7 +683,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } var sig = calculateSignature(aggregateHash.toByteArray(), payloadKey, sigAlg); - if (manifest.tdfVersion == null || manifest.tdfVersion.isEmpty()) { + if (isLegacyTdf) { sig = Hex.encodeHexString(sig).getBytes(StandardCharsets.UTF_8); } rootSigValue = Base64.getEncoder().encodeToString(sig); @@ -723,7 +724,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, var assertionAsJson = gson.toJson(assertion); JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); var hashOfAssertion = digest.digest(jc.getEncodedUTF8()); - if (manifest.tdfVersion == null || manifest.tdfVersion.isEmpty()) { + if (isLegacyTdf) { hashOfAssertion = Hex.encodeHexString(hashOfAssertion).getBytes(StandardCharsets.UTF_8); } From b6679c3ce8ad15bf32a2499c59cf14ed95617616 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 3 Dec 2024 11:46:30 -0500 Subject: [PATCH 07/20] try to use the right encoding for legacy --- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 3794119d..d179cd28 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -724,11 +724,9 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, var assertionAsJson = gson.toJson(assertion); JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); var hashOfAssertion = digest.digest(jc.getEncodedUTF8()); - if (isLegacyTdf) { - hashOfAssertion = Hex.encodeHexString(hashOfAssertion).getBytes(StandardCharsets.UTF_8); - } + var assertionCompare = isLegacyTdf ? Hex.encodeHexString(hashOfAssertion) : Base64.getEncoder().encodeToString(hashOfAssertion); - if (!Objects.equals(Base64.getEncoder().encodeToString(hashOfAssertion), hashValues.getAssertionHash())) { + if (!Objects.equals(assertionCompare, hashValues.getAssertionHash())) { throw new AssertionException("assertion hash mismatch", assertion.id); } From fc7bcb6d7e3797ce00468a03bbcaca8e6f3b1b2e Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 3 Dec 2024 12:08:04 -0500 Subject: [PATCH 08/20] more signature incorrectness --- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 4 ++++ 1 file changed, 4 insertions(+) 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 d179cd28..c87315a0 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -730,6 +730,10 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, throw new AssertionException("assertion hash mismatch", assertion.id); } + if (isLegacyTdf) { + hashOfAssertion = Hex.encodeHexString(hashOfAssertion).getBytes(StandardCharsets.UTF_8); + } + var signature = new byte[aggregateSignatureBytes.length + hashOfAssertion.length]; System.arraycopy(aggregateSignatureBytes, 0, signature, 0, aggregateSignatureBytes.length); System.arraycopy(hashOfAssertion, 0, signature, aggregateSignatureBytes.length, hashOfAssertion.length); From 196106cd1eb3d557f46246eddce4234873ee2be3 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 3 Dec 2024 12:34:01 -0500 Subject: [PATCH 09/20] ??? --- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 c87315a0..e252a49a 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -684,7 +684,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, var sig = calculateSignature(aggregateHash.toByteArray(), payloadKey, sigAlg); if (isLegacyTdf) { - sig = Hex.encodeHexString(sig).getBytes(StandardCharsets.UTF_8); + sig = Hex.encodeHexString(sig).getBytes(); } rootSigValue = Base64.getEncoder().encodeToString(sig); } else { @@ -731,7 +731,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } if (isLegacyTdf) { - hashOfAssertion = Hex.encodeHexString(hashOfAssertion).getBytes(StandardCharsets.UTF_8); + hashOfAssertion = Hex.encodeHexString(hashOfAssertion).getBytes(); } var signature = new byte[aggregateSignatureBytes.length + hashOfAssertion.length]; From ca72c7423c13b70409b064ea102d0c71d45f5068 Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Tue, 3 Dec 2024 12:46:20 -0500 Subject: [PATCH 10/20] missed one --- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 5 +++++ 1 file changed, 5 insertions(+) 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 e252a49a..f1582488 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -365,6 +365,8 @@ public void readPayload(OutputStream outputStream) throws TDFReadFailed, throw new TDFReadFailed("failed to read payload"); } + var isLegacyTdf = manifest.tdfVersion == null || manifest.tdfVersion.isEmpty(); + if (manifest.payload.isEncrypted) { String segHashAlg = manifest.encryptionInformation.integrityInformation.segmentHashAlg; Config.IntegrityAlgorithm sigAlg = Config.IntegrityAlgorithm.HS256; @@ -373,6 +375,9 @@ public void readPayload(OutputStream outputStream) throws TDFReadFailed, } var payloadSig = calculateSignature(readBuf, payloadKey, sigAlg); + if (isLegacyTdf) { + payloadSig = Hex.encodeHexString(payloadSig).getBytes(StandardCharsets.UTF_8); + } if (segment.hash.compareTo(Base64.getEncoder().encodeToString(payloadSig)) != 0) { throw new SegmentSignatureMismatch("segment signature miss match"); From b64d1818ff1a8e12da391cb961110074e6d1c65b Mon Sep 17 00:00:00 2001 From: sujan kota Date: Mon, 16 Dec 2024 19:00:41 -0500 Subject: [PATCH 11/20] fix the tdfversion field --- sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java | 1 + 1 file changed, 1 insertion(+) 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 74a49f72..39a495f9 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -53,6 +53,7 @@ public class Manifest { private static final Gson gson = new GsonBuilder() .registerTypeAdapter(Manifest.class, new ManifestDeserializer()) .create(); + @SerializedName(value = "tdf_spec_version") String tdfVersion; @Override From e88f1e6d6d3cf5605d526ee3c1f6378a024cb7b2 Mon Sep 17 00:00:00 2001 From: sujan kota Date: Tue, 17 Dec 2024 09:03:53 -0500 Subject: [PATCH 12/20] fix assertion hash --- .../io/opentdf/platform/sdk/Manifest.java | 5 ++-- .../java/io/opentdf/platform/sdk/TDF.java | 26 ++++++++----------- 2 files changed, 14 insertions(+), 17 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 39a495f9..12e5f8a7 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -23,6 +23,7 @@ import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import io.opentdf.platform.sdk.TDF.AssertionException; +import org.apache.commons.codec.binary.Hex; import org.erdtman.jcs.JsonCanonicalizer; import java.io.IOException; @@ -351,7 +352,7 @@ public int hashCode() { return Objects.hash(id, type, scope, appliesToState, statement, binding); } - public byte[] hash() throws IOException { + public String hash() throws IOException { MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-256"); @@ -361,7 +362,7 @@ public byte[] hash() throws IOException { var assertionAsJson = gson.toJson(this); JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); - return digest.digest(jc.getEncodedUTF8()); + return Hex.encodeHexString(digest.digest(jc.getEncodedUTF8())); } // Sign the assertion with the given hash and signature using the key. 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 f1582488..f5e87083 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -417,7 +417,7 @@ private static byte[] calculateSignature(byte[] data, byte[] secret, Config.Inte public TDFObject createTDF(InputStream payload, OutputStream outputStream, Config.TDFConfig tdfConfig, SDK.KAS kas, AttributesServiceFutureStub attrService) - throws IOException, JOSEException, AutoConfigureException, InterruptedException, ExecutionException { + throws IOException, JOSEException, AutoConfigureException, InterruptedException, ExecutionException, DecoderException { if (tdfConfig.autoconfigure) { Autoconfigure.Granter granter = new Autoconfigure.Granter(new ArrayList<>()); @@ -532,7 +532,8 @@ public TDFObject createTDF(InputStream payload, assertion.statement = assertionConfig.statement; assertion.appliesToState = assertionConfig.appliesToState.toString(); - var assertionHash = assertion.hash(); + var assertionHashAsHex = assertion.hash(); + var assertionHash = Hex.decodeHex(assertionHashAsHex); byte[] completeHash = new byte[aggregateHash.size() + assertionHash.length]; System.arraycopy(aggregateHash.toByteArray(), 0, completeHash, 0, aggregateHash.size()); System.arraycopy(assertionHash, 0, completeHash, aggregateHash.size(), assertionHash.length); @@ -545,7 +546,7 @@ public TDFObject createTDF(InputStream payload, assertionSigningKey = assertionConfig.assertionKey; } var hashValues = new Manifest.Assertion.HashValues( - Base64.getEncoder().encodeToString(assertionHash), + assertionHashAsHex, encodedHash ); assertion.sign(hashValues, assertionSigningKey); @@ -707,7 +708,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, throw new SegmentSizeMismatch("mismatch encrypted segment size in manifest"); } - var aggregateSignatureBytes = aggregateHash.toByteArray(); + var aggregateHashByteArrayBytes = aggregateHash.toByteArray(); // Validate assertions for (var assertion : manifest.assertions) { // Skip assertion verification if disabled @@ -726,22 +727,17 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, } var hashValues = assertion.verify(assertionKey); - var assertionAsJson = gson.toJson(assertion); - JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); - var hashOfAssertion = digest.digest(jc.getEncodedUTF8()); - var assertionCompare = isLegacyTdf ? Hex.encodeHexString(hashOfAssertion) : Base64.getEncoder().encodeToString(hashOfAssertion); + var hashOfAssertionAsHex = assertion.hash(); - if (!Objects.equals(assertionCompare, hashValues.getAssertionHash())) { + if (!Objects.equals(hashOfAssertionAsHex, hashValues.getAssertionHash())) { throw new AssertionException("assertion hash mismatch", assertion.id); } - if (isLegacyTdf) { - hashOfAssertion = Hex.encodeHexString(hashOfAssertion).getBytes(); - } + var hashOfAssertion = Hex.decodeHex(hashOfAssertionAsHex); - var signature = new byte[aggregateSignatureBytes.length + hashOfAssertion.length]; - System.arraycopy(aggregateSignatureBytes, 0, signature, 0, aggregateSignatureBytes.length); - System.arraycopy(hashOfAssertion, 0, signature, aggregateSignatureBytes.length, hashOfAssertion.length); + var signature = new byte[aggregateHashByteArrayBytes.length + hashOfAssertion.length]; + System.arraycopy(aggregateHashByteArrayBytes, 0, signature, 0, aggregateHashByteArrayBytes.length); + System.arraycopy(hashOfAssertion, 0, signature, aggregateHashByteArrayBytes.length, hashOfAssertion.length); var encodeSignature = Base64.getEncoder().encodeToString(signature); if (!Objects.equals(encodeSignature, hashValues.getSignature())) { From b2bc54026abc1f65b3c439470c0b9131d4089c15 Mon Sep 17 00:00:00 2001 From: sujan kota Date: Tue, 17 Dec 2024 09:12:03 -0500 Subject: [PATCH 13/20] fix the build --- cmdline/src/main/java/io/opentdf/platform/Command.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmdline/src/main/java/io/opentdf/platform/Command.java b/cmdline/src/main/java/io/opentdf/platform/Command.java index 513c226b..5f8aa02d 100644 --- a/cmdline/src/main/java/io/opentdf/platform/Command.java +++ b/cmdline/src/main/java/io/opentdf/platform/Command.java @@ -69,7 +69,7 @@ void encrypt( @Option(names = { "--mime-type" }, defaultValue = Option.NULL_VALUE) Optional mimeType, @Option(names = { "--with-assertions" }, defaultValue = Option.NULL_VALUE) Optional assertion) - throws IOException, JOSEException, AutoConfigureException, InterruptedException, ExecutionException { + throws IOException, JOSEException, AutoConfigureException, InterruptedException, ExecutionException, DecoderException { var sdk = buildSDK(); var kasInfos = kas.stream().map(k -> { From e2c4e4e8012433ad462ba7a193376c87963cce33 Mon Sep 17 00:00:00 2001 From: sujan kota Date: Tue, 17 Dec 2024 09:32:48 -0500 Subject: [PATCH 14/20] fix the build --- .../src/main/java/io/opentdf/platform/EncryptExample.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/src/main/java/io/opentdf/platform/EncryptExample.java b/examples/src/main/java/io/opentdf/platform/EncryptExample.java index 6da5d47c..6dcccb0b 100644 --- a/examples/src/main/java/io/opentdf/platform/EncryptExample.java +++ b/examples/src/main/java/io/opentdf/platform/EncryptExample.java @@ -6,11 +6,13 @@ import java.io.FileOutputStream; import com.nimbusds.jose.JOSEException; +import org.apache.commons.codec.DecoderException; + import java.io.IOException; import java.util.concurrent.ExecutionException; public class EncryptExample { - public static void main(String[] args) throws IOException, JOSEException, AutoConfigureException, InterruptedException, ExecutionException { + public static void main(String[] args) throws IOException, JOSEException, AutoConfigureException, InterruptedException, ExecutionException, DecoderException { String clientId = "opentdf"; String clientSecret = "secret"; String platformEndpoint = "localhost:8080"; From a4212bd0cdeca8e53bd82740615c9e005e03a21f Mon Sep 17 00:00:00 2001 From: sujan kota Date: Thu, 19 Dec 2024 10:45:16 -0500 Subject: [PATCH 15/20] add correct version --- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f5e87083..a305abef 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -36,7 +36,7 @@ */ public class TDF { - private static final String TDF_VERSION = "x.x.x"; + private static final String TDF_VERSION = "1.0.0"; private final long maximumSize; /** From f1cce4fc5f4ba65e7a6d081d75a9f86bf8de51ce Mon Sep 17 00:00:00 2001 From: sujan kota Date: Thu, 2 Jan 2025 17:23:40 -0500 Subject: [PATCH 16/20] Fix the issues bug - can't decrypt tdfs with assertion created with older version of sdks --- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 a305abef..7ffc83ba 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -36,7 +36,7 @@ */ public class TDF { - private static final String TDF_VERSION = "1.0.0"; + private static final String TDF_VERSION = "4.3.0"; private final long maximumSize; /** @@ -733,8 +733,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas, throw new AssertionException("assertion hash mismatch", assertion.id); } - var hashOfAssertion = Hex.decodeHex(hashOfAssertionAsHex); - + byte[] hashOfAssertion = isLegacyTdf ? hashOfAssertionAsHex.getBytes(StandardCharsets.UTF_8) : Hex.decodeHex(hashOfAssertionAsHex); var signature = new byte[aggregateHashByteArrayBytes.length + hashOfAssertion.length]; System.arraycopy(aggregateHashByteArrayBytes, 0, signature, 0, aggregateHashByteArrayBytes.length); System.arraycopy(hashOfAssertion, 0, signature, aggregateHashByteArrayBytes.length, hashOfAssertion.length); From 741a1fed72410f362203d3fe1f2c74869e3be9cf Mon Sep 17 00:00:00 2001 From: David Mihalcik Date: Tue, 7 Jan 2025 16:39:17 -0500 Subject: [PATCH 17/20] adds --version option --- cmdline/src/main/java/io/opentdf/platform/Command.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmdline/src/main/java/io/opentdf/platform/Command.java b/cmdline/src/main/java/io/opentdf/platform/Command.java index 5f8aa02d..845d109e 100644 --- a/cmdline/src/main/java/io/opentdf/platform/Command.java +++ b/cmdline/src/main/java/io/opentdf/platform/Command.java @@ -39,9 +39,16 @@ import javax.net.ssl.TrustManager; -@CommandLine.Command(name = "tdf", subcommands = {HelpCommand.class}) +@CommandLine.Command( + name = "tdf", + subcommands = {HelpCommand.class}, + version = "{\"version\":\"0.7.5\",\"tdfSpecVersion\":\"4.3.0\"}" +) class Command { + @Option(names = {"-V", "--version"}, versionHelp = true, description = "display version info") + boolean versionInfoRequested; + @Option(names = { "--client-secret" }, required = true) private String clientSecret; From 2fb17d3b9456b56214d6dad64d13c24da8e8bcaf Mon Sep 17 00:00:00 2001 From: sujan kota Date: Wed, 8 Jan 2025 11:48:07 -0500 Subject: [PATCH 18/20] add build meta to the tdf version --- sdk/pom.xml | 5 +++++ sdk/src/main/java/io/opentdf/platform/sdk/Config.java | 5 +++++ .../main/java/io/opentdf/platform/sdk/Manifest.java | 2 +- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 9 ++++++++- .../test/java/io/opentdf/platform/sdk/TDFTest.java | 11 ++++++++++- 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/sdk/pom.xml b/sdk/pom.xml index 6685f513..18a38a0d 100644 --- a/sdk/pom.xml +++ b/sdk/pom.xml @@ -44,6 +44,11 @@ gson 2.11.0 + + com.vdurmont + semver4j + 3.1.0 + commons-codec commons-codec diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Config.java b/sdk/src/main/java/io/opentdf/platform/sdk/Config.java index a8b58c4b..f63b35df 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Config.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Config.java @@ -128,6 +128,7 @@ public static class TDFConfig { public String tdfPublicKey; public String tdfPrivateKey; public String metaData; + public String buildMetadata; public IntegrityAlgorithm integrityAlgorithm; public IntegrityAlgorithm segmentIntegrityAlgorithm; public List attributes; @@ -229,6 +230,10 @@ public static Consumer withMetaData(String metaData) { return (TDFConfig config) -> config.metaData = metaData; } + public static Consumer withBuildMetadata(String buildMetadata) { + return (TDFConfig config) -> config.buildMetadata = buildMetadata; + } + public static Consumer withSegmentSize(int size) { if (size > MAX_SEGMENT_SIZE) { throw new IllegalArgumentException("Segment size " + size + " exceeds the maximum " + MAX_SEGMENT_SIZE); 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 f85ea634..7a6989eb 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -54,7 +54,7 @@ public class Manifest { private static final Gson gson = new GsonBuilder() .registerTypeAdapter(Manifest.class, new ManifestDeserializer()) .create(); - @SerializedName(value = "tdf_spec_version") + @SerializedName(value = "schemaVersion") String tdfVersion; @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 b1178229..234462f5 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -4,6 +4,7 @@ import com.google.gson.GsonBuilder; import com.nimbusds.jose.*; +import com.vdurmont.semver4j.Semver; import io.opentdf.platform.policy.Value; import io.opentdf.platform.policy.attributes.AttributesServiceGrpc.AttributesServiceFutureStub; import io.opentdf.platform.sdk.Config.TDFConfig; @@ -202,7 +203,13 @@ PolicyObject createPolicyObject(List attributes private static final Base64.Encoder encoder = Base64.getEncoder(); private void prepareManifest(Config.TDFConfig tdfConfig, SDK.KAS kas) { - manifest.tdfVersion = TDF_VERSION; + Semver semver = new Semver(TDF_VERSION); + + if (tdfConfig.buildMetadata != null && !tdfConfig.buildMetadata.trim().isEmpty()) { + semver = semver.withBuild(tdfConfig.buildMetadata.trim()); + } + + manifest.tdfVersion = semver.toString(); manifest.encryptionInformation.keyAccessType = kSplitKeyType; manifest.encryptionInformation.keyAccessObj = new ArrayList<>(); diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java index fdf3144d..bf04b878 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java @@ -1,6 +1,10 @@ package io.opentdf.platform.sdk; import com.nimbusds.jose.JOSEException; +import com.vdurmont.semver4j.Semver; +import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsRequest; +import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsResponse; +import io.opentdf.platform.policy.attributes.AttributesServiceGrpc; import io.opentdf.platform.sdk.Config.KASInfo; import io.opentdf.platform.sdk.TDF.Reader; import io.opentdf.platform.sdk.nanotdf.NanoTDFType; @@ -88,6 +92,7 @@ void testSimpleTDFEncryptAndDecrypt() throws Exception { byte[] key = new byte[32]; secureRandom.nextBytes(key); + var buildMetadata = "test.01"; var assertion1 = new AssertionConfig(); assertion1.id = "assertion1"; assertion1.type = AssertionConfig.Type.BaseAssertion; @@ -104,7 +109,8 @@ void testSimpleTDFEncryptAndDecrypt() throws Exception { 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)); + Config.withAssertionConfig(assertion1), + Config.withBuildMetadata(buildMetadata)); String plainText = "this is extremely sensitive stuff!!!"; InputStream plainTextInputStream = new ByteArrayInputStream(plainText.getBytes()); @@ -132,6 +138,9 @@ void testSimpleTDFEncryptAndDecrypt() throws Exception { .isEqualTo(plainText); assertThat(reader.getMetadata()).isEqualTo("here is some metadata"); + Semver semver = new Semver( reader.getManifest().tdfVersion); + assertThat(semver.getBuild()).isEqualTo(buildMetadata); + var policyObject = reader.readPolicyObject(); assertThat(policyObject).isNotNull(); assertThat(policyObject.body.dataAttributes.stream().map(a -> a.attribute).collect(Collectors.toList())).asList() From a9995955bdb26a8ffd65c77a0a01f1eca728ff58 Mon Sep 17 00:00:00 2001 From: sujan kota Date: Sun, 12 Jan 2025 16:44:25 -0500 Subject: [PATCH 19/20] add schema version in key access object --- sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java | 6 ++++-- sdk/src/main/java/io/opentdf/platform/sdk/TDF.java | 2 ++ 2 files changed, 6 insertions(+), 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 7a6989eb..cb0be95e 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -192,6 +192,7 @@ static public class KeyAccess { public String encryptedMetadata; public String kid; public String sid; + public String schemaVersion; @Override public boolean equals(Object o) { @@ -204,12 +205,13 @@ public boolean equals(Object o) { && Objects.equals(protocol, keyAccess.protocol) && Objects.equals(wrappedKey, keyAccess.wrappedKey) && Objects.equals(policyBinding, keyAccess.policyBinding) && Objects.equals(encryptedMetadata, keyAccess.encryptedMetadata) - && Objects.equals(kid, keyAccess.kid); + && Objects.equals(kid, keyAccess.kid) + && Objects.equals(schemaVersion, keyAccess.schemaVersion); } @Override public int hashCode() { - return Objects.hash(keyType, url, protocol, wrappedKey, policyBinding, encryptedMetadata, kid); + return Objects.hash(keyType, url, protocol, wrappedKey, policyBinding, encryptedMetadata, kid, schemaVersion); } } 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 234462f5..6854b10b 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -39,6 +39,7 @@ public class TDF { private static final String TDF_VERSION = "4.3.0"; + private static final String KEY_ACCESS_SECHMA_VERSION = "4.3.0"; private final long maximumSize; /** @@ -314,6 +315,7 @@ private void prepareManifest(Config.TDFConfig tdfConfig, SDK.KAS kas) { keyAccess.wrappedKey = encoder.encodeToString(wrappedKey); keyAccess.encryptedMetadata = encryptedMetadata; keyAccess.sid = splitID; + keyAccess.schemaVersion = KEY_ACCESS_SECHMA_VERSION; manifest.encryptionInformation.keyAccessObj.add(keyAccess); } From 2bbb08e2cba1a40a10b239a54411c5691c0bfb85 Mon Sep 17 00:00:00 2001 From: sujan kota Date: Thu, 16 Jan 2025 13:40:44 -0500 Subject: [PATCH 20/20] Removed the meta data changes --- .../java/io/opentdf/platform/sdk/Config.java | 5 ----- .../main/java/io/opentdf/platform/sdk/TDF.java | 9 +-------- .../java/io/opentdf/platform/sdk/TDFTest.java | 17 ++--------------- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Config.java b/sdk/src/main/java/io/opentdf/platform/sdk/Config.java index f63b35df..a8b58c4b 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Config.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Config.java @@ -128,7 +128,6 @@ public static class TDFConfig { public String tdfPublicKey; public String tdfPrivateKey; public String metaData; - public String buildMetadata; public IntegrityAlgorithm integrityAlgorithm; public IntegrityAlgorithm segmentIntegrityAlgorithm; public List attributes; @@ -230,10 +229,6 @@ public static Consumer withMetaData(String metaData) { return (TDFConfig config) -> config.metaData = metaData; } - public static Consumer withBuildMetadata(String buildMetadata) { - return (TDFConfig config) -> config.buildMetadata = buildMetadata; - } - public static Consumer withSegmentSize(int size) { if (size > MAX_SEGMENT_SIZE) { throw new IllegalArgumentException("Segment size " + size + " exceeds the maximum " + MAX_SEGMENT_SIZE); 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 6854b10b..83a570ab 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -4,7 +4,6 @@ import com.google.gson.GsonBuilder; import com.nimbusds.jose.*; -import com.vdurmont.semver4j.Semver; import io.opentdf.platform.policy.Value; import io.opentdf.platform.policy.attributes.AttributesServiceGrpc.AttributesServiceFutureStub; import io.opentdf.platform.sdk.Config.TDFConfig; @@ -204,13 +203,7 @@ PolicyObject createPolicyObject(List attributes private static final Base64.Encoder encoder = Base64.getEncoder(); private void prepareManifest(Config.TDFConfig tdfConfig, SDK.KAS kas) { - Semver semver = new Semver(TDF_VERSION); - - if (tdfConfig.buildMetadata != null && !tdfConfig.buildMetadata.trim().isEmpty()) { - semver = semver.withBuild(tdfConfig.buildMetadata.trim()); - } - - manifest.tdfVersion = semver.toString(); + manifest.tdfVersion = TDF_VERSION; manifest.encryptionInformation.keyAccessType = kSplitKeyType; manifest.encryptionInformation.keyAccessObj = new ArrayList<>(); diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java index bf04b878..87090bf5 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java @@ -1,16 +1,11 @@ package io.opentdf.platform.sdk; import com.nimbusds.jose.JOSEException; -import com.vdurmont.semver4j.Semver; -import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsRequest; -import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsResponse; -import io.opentdf.platform.policy.attributes.AttributesServiceGrpc; import io.opentdf.platform.sdk.Config.KASInfo; import io.opentdf.platform.sdk.TDF.Reader; import io.opentdf.platform.sdk.nanotdf.NanoTDFType; import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import javax.annotation.Nonnull; @@ -27,9 +22,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.mock; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -92,8 +84,7 @@ void testSimpleTDFEncryptAndDecrypt() throws Exception { byte[] key = new byte[32]; secureRandom.nextBytes(key); - var buildMetadata = "test.01"; - var assertion1 = new AssertionConfig(); + var assertion1 = new AssertionConfig(); assertion1.id = "assertion1"; assertion1.type = AssertionConfig.Type.BaseAssertion; assertion1.scope = AssertionConfig.Scope.TrustedDataObj; @@ -109,8 +100,7 @@ void testSimpleTDFEncryptAndDecrypt() throws Exception { 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), - Config.withBuildMetadata(buildMetadata)); + Config.withAssertionConfig(assertion1)); String plainText = "this is extremely sensitive stuff!!!"; InputStream plainTextInputStream = new ByteArrayInputStream(plainText.getBytes()); @@ -138,9 +128,6 @@ void testSimpleTDFEncryptAndDecrypt() throws Exception { .isEqualTo(plainText); assertThat(reader.getMetadata()).isEqualTo("here is some metadata"); - Semver semver = new Semver( reader.getManifest().tdfVersion); - assertThat(semver.getBuild()).isEqualTo(buildMetadata); - var policyObject = reader.readPolicyObject(); assertThat(policyObject).isNotNull(); assertThat(policyObject.body.dataAttributes.stream().map(a -> a.attribute).collect(Collectors.toList())).asList()