From f1f2ce3a02acc51fb849422bf59fb1f6f3b555ae Mon Sep 17 00:00:00 2001 From: Morgan Kleene Date: Fri, 22 Nov 2024 16:25:50 -0500 Subject: [PATCH] add a class that does all hex encoding --- .../io/opentdf/platform/sdk/HexString.java | 15 +++++++ .../io/opentdf/platform/sdk/Manifest.java | 3 +- .../java/io/opentdf/platform/sdk/TDF.java | 42 +++++++++++-------- 3 files changed, 40 insertions(+), 20 deletions(-) create mode 100644 sdk/src/main/java/io/opentdf/platform/sdk/HexString.java diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/HexString.java b/sdk/src/main/java/io/opentdf/platform/sdk/HexString.java new file mode 100644 index 0000000..3ae24b9 --- /dev/null +++ b/sdk/src/main/java/io/opentdf/platform/sdk/HexString.java @@ -0,0 +1,15 @@ +package io.opentdf.platform.sdk; + +import org.apache.commons.codec.binary.Hex; + +public class HexString { + private final byte[] value; + + public HexString(byte[] value) { + this.value = value; + } + + String hexValue() { + return Hex.encodeHexString(value); + } +} 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 479d7b0..dc74d82 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java @@ -13,7 +13,6 @@ import io.opentdf.platform.sdk.TDF.AssertionException; -import org.apache.commons.codec.binary.Hex; import org.erdtman.jcs.JsonCanonicalizer; import java.io.IOException; @@ -353,7 +352,7 @@ public String hash() throws IOException { var assertionAsJson = gson.toJson(this); JsonCanonicalizer jc = new JsonCanonicalizer(assertionAsJson); - return Hex.encodeHexString(digest.digest(jc.getEncodedUTF8())); + return new HexString(digest.digest(jc.getEncodedUTF8())).hexValue(); } // 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 124ebe0..4c63a9f 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java @@ -2,32 +2,39 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.nimbusds.jose.*; - +import com.nimbusds.jose.JOSEException; 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; - +import io.opentdf.platform.sdk.Config.TDFConfig; +import io.opentdf.platform.sdk.Manifest.ManifestDeserializer; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import org.erdtman.jcs.JsonCanonicalizer; 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; -import java.security.*; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.text.ParseException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.ExecutionException; /** @@ -268,11 +275,10 @@ private void prepareManifest(Config.TDFConfig tdfConfig, SDK.KAS kas) { symKeys.add(symKey); // Add policyBinding - var hexBinding = Hex.encodeHexString( - CryptoUtils.CalculateSHA256Hmac(symKey, base64PolicyObject.getBytes(StandardCharsets.UTF_8))); + var hexBinding = new HexString(CryptoUtils.CalculateSHA256Hmac(symKey, base64PolicyObject.getBytes(StandardCharsets.UTF_8))); var policyBinding = new Manifest.PolicyBinding(); policyBinding.alg = kHmacIntegrityAlgorithm; - policyBinding.hash = encoder.encodeToString(hexBinding.getBytes(StandardCharsets.UTF_8)); + policyBinding.hash = encoder.encodeToString(hexBinding.hexValue().getBytes(StandardCharsets.UTF_8)); // Add meta data var encryptedMetadata = new String(); @@ -383,8 +389,8 @@ public void readPayload(OutputStream outputStream) throws TDFReadFailed, outputStream.write(writeBuf); } else { - String segmentSig = Hex.encodeHexString(digest.digest(readBuf)); - if (segment.hash.compareTo(segmentSig) != 0) { + var segmentSig = new HexString(digest.digest(readBuf)); + if (segment.hash.compareTo(segmentSig.hexValue()) != 0) { throw new SegmentSignatureMismatch("segment signature miss match"); } @@ -401,7 +407,7 @@ public PolicyObject readPolicyObject() { private static String calculateSignature(byte[] data, byte[] secret, Config.IntegrityAlgorithm algorithm) { if (algorithm == Config.IntegrityAlgorithm.HS256) { byte[] hmac = CryptoUtils.CalculateSHA256Hmac(secret, data); - return Hex.encodeHexString(hmac); + return new HexString(hmac).hexValue(); } if (kGMACPayloadLength > data.length) { @@ -409,7 +415,7 @@ private static String calculateSignature(byte[] data, byte[] secret, Config.Inte } byte[] gmacPayload = Arrays.copyOfRange(data, data.length - kGMACPayloadLength, data.length); - return Hex.encodeHexString(gmacPayload); + return new HexString(gmacPayload).hexValue(); } public TDFObject createTDF(InputStream payload, @@ -718,8 +724,8 @@ 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 hashOfAssertion = new HexString(digest.digest(jc.getEncodedUTF8())); + var signature = aggregateHash + hashOfAssertion.hexValue(); var encodeSignature = Base64.getEncoder().encodeToString(signature.getBytes()); if (!Objects.equals(hashOfAssertion, hashValues.getAssertionHash())) {