From 6b26274fde82d81e88ee0eca45122da5d8910e2e Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Mon, 2 Dec 2024 16:47:39 -0500 Subject: [PATCH 01/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] ??? --- 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/10] 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");