From 90bbbc505016c4edde402746352bd6d6e80c6433 Mon Sep 17 00:00:00 2001
From: Paul Flynn <43211074+pflynn-virtru@users.noreply.github.com>
Date: Wed, 16 Oct 2024 14:49:42 -0400
Subject: [PATCH 01/14] ci: SonarCloud coverage (#195)
Introduce a new Maven profile for JaCoCo test coverage reporting in the
`pom.xml`. Additionally, update the GitHub Actions workflow to include a
SonarCloud scan that uses the JaCoCo coverage data.
DSP-119
DSP-120
---
.github/workflows/checks.yaml | 25 ++++++++++++++++--
pom.xml | 49 +++++++++++++++++++++++++++++++++++
sdk/pom.xml | 29 +++++++++++++++++++++
3 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml
index fa06679e..98b89f76 100644
--- a/.github/workflows/checks.yaml
+++ b/.github/workflows/checks.yaml
@@ -42,11 +42,31 @@ jobs:
distribution: "adopt"
server-id: github
- name: Maven Verify
- run: |
- mvn --batch-mode verify
+ run: mvn --batch-mode verify
+ env:
+ BUF_INPUT_HTTPS_USERNAME: opentdf-bot
+ BUF_INPUT_HTTPS_PASSWORD: ${{ secrets.PERSONAL_ACCESS_TOKEN_OPENTDF }}
+
+ sonarcloud:
+ name: SonarCloud Scan
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: bufbuild/buf-setup-action@2211e06e8cf26d628cda2eea15c95f8c42b080b3
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ - name: Set up JDK
+ uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7
+ with:
+ java-version: "17"
+ distribution: "temurin"
+ server-id: github
+ - name: Maven Test Coverage
env:
BUF_INPUT_HTTPS_USERNAME: opentdf-bot
BUF_INPUT_HTTPS_PASSWORD: ${{ secrets.PERSONAL_ACCESS_TOKEN_OPENTDF }}
+ run: mvn --batch-mode clean verify -P coverage
platform-integration:
runs-on: ubuntu-22.04
@@ -257,6 +277,7 @@ jobs:
- platform-integration
- platform-xtest
- mavenverify
+ - sonarcloud
- pr
runs-on: ubuntu-latest
if: always()
diff --git a/pom.xml b/pom.xml
index 3307b7e1..4e186854 100644
--- a/pom.xml
+++ b/pom.xml
@@ -342,5 +342,54 @@
+
+ coverage
+
+ sdk
+
+
+ opentdf
+ opentdf_java-sdk
+ https://sonarcloud.io
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.12
+
+
+ prepare-agent
+
+ prepare-agent
+ report-aggregate
+
+
+
+ report
+ test
+
+ report
+
+
+ ${project.parent.basedir}/target/jacoco.exec
+
+ XML
+
+
+
+
+ post-test-report
+ prepare-package
+
+ report
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sdk/pom.xml b/sdk/pom.xml
index 890ba1e3..b6f06e1e 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -275,6 +275,35 @@
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.12
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+ ${project.parent.basedir}/target/jacoco.exec
+
+
+
+ report
+ test
+
+ report
+
+
+ ${project.parent.basedir}/target/jacoco.exec
+
+ XML
+
+
+
+
+
\ No newline at end of file
From 210a1576290ceb2f356c7e6143a706176c6072ed Mon Sep 17 00:00:00 2001
From: Mike Jensen
Date: Thu, 17 Oct 2024 08:26:42 -0600
Subject: [PATCH 02/14] chore(ci): Add initial CodeQL workflow configuration
(#197)
I want to explore using CodeQL to assist as part of our static analysis
strategy. Because this tool is available for free to open source
projects, opentdf is a good place to start this testing.
This PR adds an initial configuration which will scan the codebase once
a week. These results can be ignored for the time being. Instead the
security team will review the results and make sure we tune away any
noise first (or help in opening PR's to address any valid issues found).
---
.github/workflows/codeql.yaml | 45 +++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 .github/workflows/codeql.yaml
diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml
new file mode 100644
index 00000000..755b2183
--- /dev/null
+++ b/.github/workflows/codeql.yaml
@@ -0,0 +1,45 @@
+name: "CodeQL"
+
+on:
+ schedule:
+ - cron: '0 13 * * 1' # At 1:00 PM UTC every Monday
+ pull_request:
+ paths:
+ - '.github/workflows/codeql.yaml'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'java' ]
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Buf setup
+ uses: bufbuild/buf-setup-action@2211e06e8cf26d628cda2eea15c95f8c42b080b3
+
+ - name: Initialize the CodeQL tools for scanning
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+ timeout-minutes: 5
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v3
+ timeout-minutes: 10
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
+ timeout-minutes: 10
From 33c9513de68954cccba854d501ba26b62216df89 Mon Sep 17 00:00:00 2001
From: Paul Flynn <43211074+pflynn-virtru@users.noreply.github.com>
Date: Fri, 18 Oct 2024 11:03:10 -0400
Subject: [PATCH 03/14] docs: JavaDoc (#196)
Added JavaDoc comments to multiple classes and methods across the SDK,
providing detailed descriptions of their functionality and usage. This
enhances the readability and maintainability of the code.
DSP-119
---
.../java/io/opentdf/platform/sdk/AesGcm.java | 5 +++++
.../opentdf/platform/sdk/AssertionConfig.java | 4 ++++
.../opentdf/platform/sdk/AsymDecryption.java | 3 +++
.../opentdf/platform/sdk/AsymEncryption.java | 4 ++++
.../platform/sdk/AutoConfigureException.java | 3 +++
.../opentdf/platform/sdk/Autoconfigure.java | 12 +++++++++-
.../java/io/opentdf/platform/sdk/Config.java | 4 ++++
.../io/opentdf/platform/sdk/CryptoUtils.java | 3 +++
.../platform/sdk/InvalidZipException.java | 5 +++++
.../io/opentdf/platform/sdk/KASClient.java | 5 +++++
.../io/opentdf/platform/sdk/KASKeyCache.java | 22 +++++++++++++++++++
.../io/opentdf/platform/sdk/Manifest.java | 4 ++++
.../java/io/opentdf/platform/sdk/NanoTDF.java | 5 +++++
.../io/opentdf/platform/sdk/PolicyObject.java | 3 +++
.../java/io/opentdf/platform/sdk/SDK.java | 14 +++++++++++-
.../io/opentdf/platform/sdk/SDKBuilder.java | 2 --
.../io/opentdf/platform/sdk/SDKException.java | 5 +++++
.../java/io/opentdf/platform/sdk/TDF.java | 13 +++++++++++
.../io/opentdf/platform/sdk/TDFReader.java | 5 +++++
.../io/opentdf/platform/sdk/TDFWriter.java | 4 ++++
.../io/opentdf/platform/sdk/ZipReader.java | 6 +++++
.../io/opentdf/platform/sdk/ZipWriter.java | 4 ++++
.../io/opentdf/platform/sdk/package-info.java | 19 ++++++++++++++++
23 files changed, 150 insertions(+), 4 deletions(-)
create mode 100644 sdk/src/main/java/io/opentdf/platform/sdk/package-info.java
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/AesGcm.java b/sdk/src/main/java/io/opentdf/platform/sdk/AesGcm.java
index 0d79c460..71445f69 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/AesGcm.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/AesGcm.java
@@ -12,6 +12,11 @@
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
+/**
+ * The AesGcm class provides encryption and decryption methods using AES-GCM mode.
+ * It includes methods to encrypt and decrypt byte arrays using a specified
+ * symmetric key.
+ */
public class AesGcm {
public static final int GCM_NONCE_LENGTH = 12; // in bytes
public static final int GCM_TAG_LENGTH = 16; // in bytes
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/AssertionConfig.java b/sdk/src/main/java/io/opentdf/platform/sdk/AssertionConfig.java
index 510a008c..100f824f 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/AssertionConfig.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/AssertionConfig.java
@@ -3,6 +3,10 @@
import java.util.Objects;
+/**
+ * Represents the configuration for assertions, encapsulating various types, scopes, states, keys,
+ * and statements involved in assertion handling.
+ */
public class AssertionConfig {
public enum Type {
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/AsymDecryption.java b/sdk/src/main/java/io/opentdf/platform/sdk/AsymDecryption.java
index b7eb1e92..b76d1523 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/AsymDecryption.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/AsymDecryption.java
@@ -9,6 +9,9 @@
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
+/**
+ * Class providing functionality for asymmetric decryption using an RSA private key.
+ */
public class AsymDecryption {
private final PrivateKey privateKey;
private static final String PRIVATE_KEY_HEADER = "-----BEGIN PRIVATE KEY-----";
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/AsymEncryption.java b/sdk/src/main/java/io/opentdf/platform/sdk/AsymEncryption.java
index 415fc375..3a81b1f5 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/AsymEncryption.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/AsymEncryption.java
@@ -15,6 +15,10 @@
import java.util.Base64;
import java.util.Objects;
+/**
+ * AsymEncryption class provides methods for asymmetric encryption and
+ * handling public keys in PEM format.
+ */
public class AsymEncryption {
private final PublicKey publicKey;
private static final String PUBLIC_KEY_HEADER = "-----BEGIN PUBLIC KEY-----";
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/AutoConfigureException.java b/sdk/src/main/java/io/opentdf/platform/sdk/AutoConfigureException.java
index c134806c..157e6a8a 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/AutoConfigureException.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/AutoConfigureException.java
@@ -1,5 +1,8 @@
package io.opentdf.platform.sdk;
+/**
+ * Exception thrown when automatic configuration fails.
+ */
public class AutoConfigureException extends RuntimeException {
public AutoConfigureException(String message) {
super(message);
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/Autoconfigure.java b/sdk/src/main/java/io/opentdf/platform/sdk/Autoconfigure.java
index 372daee2..6113a681 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/Autoconfigure.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/Autoconfigure.java
@@ -35,7 +35,11 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-// Attribute rule types: operators!
+/**
+ * The RuleType class defines a set of constants that represent various types of attribute rules.
+ * These constants are used to specify the nature and behavior of attribute rules in the context
+ * of key management and policy enforcement.
+ */
class RuleType {
public static final String HIERARCHY = "hierarchy";
public static final String ALL_OF = "allOf";
@@ -44,6 +48,12 @@ class RuleType {
public static final String EMPTY_TERM = "DEFAULT";
}
+/**
+ * The Autoconfigure class provides methods for configuring and retrieving
+ * grants related to attribute values and KAS (Key Access Server) keys.
+ * This class includes functionality to create granter instances based on
+ * attributes either from a list of attribute values or from a service.
+ */
public class Autoconfigure {
public static Logger logger = LoggerFactory.getLogger(Autoconfigure.class);
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 a8766820..c7d4f092 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/Config.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/Config.java
@@ -10,6 +10,10 @@
import java.util.*;
import java.util.function.Consumer;
+/**
+ * Configuration class for setting various configurations related to TDF.
+ * Contains nested classes and enums for specific configuration settings.
+ */
public class Config {
public static final int TDF3_KEY_SIZE = 2048;
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/CryptoUtils.java b/sdk/src/main/java/io/opentdf/platform/sdk/CryptoUtils.java
index 6a53e7e5..404637df 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/CryptoUtils.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/CryptoUtils.java
@@ -5,6 +5,9 @@
import java.security.*;
import java.util.Base64;
+/**
+ * Utility class for cryptographic operations such as generating RSA key pairs and calculating HMAC.
+ */
public class CryptoUtils {
private static final int KEYPAIR_SIZE = 2048;
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/InvalidZipException.java b/sdk/src/main/java/io/opentdf/platform/sdk/InvalidZipException.java
index e8ac4648..8bba58bd 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/InvalidZipException.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/InvalidZipException.java
@@ -1,5 +1,10 @@
package io.opentdf.platform.sdk;
+/**
+ * InvalidZipException is thrown to indicate that a ZIP file being read
+ * is invalid or corrupted in some way. This exception extends RuntimeException,
+ * allowing it to be thrown during the normal operation of the Java Virtual Machine.
+ */
public class InvalidZipException extends RuntimeException {
public InvalidZipException(String message) {
super(message);
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java b/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java
index 4732865b..727eda83 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java
@@ -30,6 +30,11 @@
import static java.lang.String.format;
+/**
+ * A client implementation that communicates with a Key Access Service (KAS).
+ * This class provides methods to retrieve public keys, unwrap encrypted keys,
+ * and manage key caches.
+ */
public class KASClient implements SDK.KAS {
private final Function channelFactory;
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/KASKeyCache.java b/sdk/src/main/java/io/opentdf/platform/sdk/KASKeyCache.java
index 22c4764c..5879dd05 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/KASKeyCache.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/KASKeyCache.java
@@ -8,6 +8,10 @@
import java.util.HashMap;
import java.util.Map;
+/**
+ * Class representing a cache for KAS (Key Access Server) information.
+ * It stores key information along with a timestamp to manage the freshness of cached data.
+ */
public class KASKeyCache {
private static final Logger log = LoggerFactory.getLogger(KASKeyCache.class);
Map cache;
@@ -50,6 +54,17 @@ public void store(Config.KASInfo kasInfo) {
}
}
+/**
+ * A class representing Key Aggregation Service (KAS) information along with a timestamp.
+ *
+ * This class holds information related to KAS, as well as a timestamp indicating when the
+ * information was recorded or generated. It encapsulates two main attributes: {@code kasInfo}
+ * and {@code timestamp}.
+ *
+ * The {@code kasInfo} field is an instance of {@code Config.KASInfo}, which contains the KAS-specific
+ * data. The {@code timestamp} field is an instance of {@code LocalDateTime}, representing
+ * the date and time when the KAS information was recorded.
+ */
class TimeStampedKASInfo {
Config.KASInfo kasInfo;
LocalDateTime timestamp;
@@ -60,6 +75,13 @@ public TimeStampedKASInfo(Config.KASInfo kasInfo, LocalDateTime timestamp) {
}
}
+/**
+ * Represents a request for a Key Access Server (KAS) key.
+ * This class is used to request keys using a specified URL and algorithm.
+ *
+ * This class also overrides equals and hashCode methods
+ * to ensure proper functioning within hash-based collections.
+ */
class KASKeyRequest {
private String url;
private String algorithm;
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 f9434c6b..bc4c4c3c 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java
@@ -27,6 +27,10 @@
import java.util.List;
import java.util.Objects;
+/**
+ * The Manifest class represents a detailed structure encapsulating various aspects
+ * of data integrity, encryption, payload, and assertions within a certain context.
+ */
public class Manifest {
private static final String kAssertionHash = "assertionHash";
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java b/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
index 9132e570..75d0e734 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
@@ -16,6 +16,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+/**
+ * The NanoTDF class provides methods to create and read NanoTDF (Tiny Data Format) files.
+ * The NanoTDF format is intended for securely encrypting small data payloads using elliptic-curve cryptography
+ * and authenticated encryption.
+ */
public class NanoTDF {
public static Logger logger = LoggerFactory.getLogger(NanoTDF.class);
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyObject.java b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyObject.java
index 15d2d0bb..9d708699 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/PolicyObject.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/PolicyObject.java
@@ -2,6 +2,9 @@
import java.util.List;
+/**
+ * The PolicyObject class represents a policy with a unique identifier and a body containing data attributes.
+ */
public class PolicyObject {
static public class AttributeObject {
public String attribute;
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java b/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java
index fe2a8005..14affa4c 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java
@@ -34,11 +34,20 @@ public class SDK implements AutoCloseable {
private static final Logger log = LoggerFactory.getLogger(SDK.class);
+ /**
+ * Closes the SDK, including its associated services.
+ *
+ * @throws Exception if an error occurs while closing the services.
+ */
@Override
public void close() throws Exception {
services.close();
}
+ /**
+ * KAS (Key Access Service) interface to define methods related to key access and management.
+ * This interface extends AutoCloseable to allow for resource management during close operations.
+ */
public interface KAS extends AutoCloseable {
Config.KASInfo getPublicKey(Config.KASInfo kasInfo);
@@ -51,7 +60,10 @@ public interface KAS extends AutoCloseable {
KASKeyCache getKeyCache();
}
- // TODO: add KAS
+ /**
+ * The Services interface provides access to various gRPC service stubs and a Key Authority Service (KAS).
+ * It extends the AutoCloseable interface, allowing for the release of resources when no longer needed.
+ */
public interface Services extends AutoCloseable {
AuthorizationServiceFutureStub authorization();
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/SDKBuilder.java b/sdk/src/main/java/io/opentdf/platform/sdk/SDKBuilder.java
index 4068b5e0..8c6b1804 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/SDKBuilder.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/SDKBuilder.java
@@ -69,7 +69,6 @@ public SDKBuilder sslFactory(SSLFactory sslFactory) {
* Add SSL Context with trusted certs from certDirPath
*
* @param certsDirPath Path to a directory containing .pem or .crt trusted certs
- * @return
*/
public SDKBuilder sslFactoryFromDirectory(String certsDirPath) throws Exception {
File certsDir = new File(certsDirPath);
@@ -91,7 +90,6 @@ public SDKBuilder sslFactoryFromDirectory(String certsDirPath) throws Exception
*
* @param keystorePath Path to keystore
* @param keystorePassword Password to keystore
- * @return
*/
public SDKBuilder sslFactoryFromKeyStore(String keystorePath, String keystorePassword) {
this.sslFactory = SSLFactory.builder().withDefaultTrustMaterial().withSystemTrustMaterial()
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/SDKException.java b/sdk/src/main/java/io/opentdf/platform/sdk/SDKException.java
index 2d0b390d..58e7adbe 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/SDKException.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/SDKException.java
@@ -1,5 +1,10 @@
package io.opentdf.platform.sdk;
+/**
+ * SDKException serves as a custom exception class for handling errors
+ * specific to the SDK's operations and processes. It extends
+ * RuntimeException, making it an unchecked exception.
+ */
public class SDKException extends RuntimeException {
public SDKException(String message, Exception reason) {
super(message, reason);
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 ba7c5b97..aec26e80 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
@@ -28,10 +28,23 @@
import java.util.*;
import java.util.concurrent.ExecutionException;
+/**
+ * The TDF class is responsible for handling operations related to
+ * Trusted Data Format (TDF). It includes methods to create and load
+ * TDF objects, as well as utility functions to handle cryptographic
+ * operations and configurations.
+ */
public class TDF {
private final long maximumSize;
+ /**
+ * Constructs a new TDF instance using the default maximum input size defined by MAX_TDF_INPUT_SIZE.
+ *
+ * This constructor is primarily used to initialize the TDF object with the standard maximum
+ * input size, which controls the maximum size of the input data that can be processed.
+ * For test purposes, an alternative constructor allows for setting a custom maximum input size.
+ */
public TDF() {
this(MAX_TDF_INPUT_SIZE);
}
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/TDFReader.java b/sdk/src/main/java/io/opentdf/platform/sdk/TDFReader.java
index 24b05940..6691888a 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/TDFReader.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDFReader.java
@@ -12,6 +12,11 @@
import static io.opentdf.platform.sdk.TDFWriter.TDF_MANIFEST_FILE_NAME;
import static io.opentdf.platform.sdk.TDFWriter.TDF_PAYLOAD_FILE_NAME;
+/**
+ * TDFReader is responsible for reading and processing Trusted Data Format (TDF) files.
+ * The class initializes with a TDF file channel, extracts the manifest and payload entries,
+ * and provides methods to retrieve the manifest content, read payload bytes, and read policy objects.
+ */
public class TDFReader {
private final ZipReader.Entry manifestEntry;
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/TDFWriter.java b/sdk/src/main/java/io/opentdf/platform/sdk/TDFWriter.java
index a5f3509b..048822f6 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/TDFWriter.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDFWriter.java
@@ -4,6 +4,10 @@
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
+/**
+ * The TDFWriter class provides functionalities for creating a TDF (Trusted Data Format) archive.
+ * This includes appending a manifest file and appending payload data to the archive.
+ */
public class TDFWriter {
public static final String TDF_PAYLOAD_FILE_NAME = "0.payload";
public static final String TDF_MANIFEST_FILE_NAME = "0.manifest.json";
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/ZipReader.java b/sdk/src/main/java/io/opentdf/platform/sdk/ZipReader.java
index 17bc51c5..cb6d5ffd 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/ZipReader.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/ZipReader.java
@@ -12,6 +12,12 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * The ZipReader class provides functionality to read basic ZIP file
+ * structures, such as the End of Central Directory Record and the
+ * Local File Header. This class supports standard ZIP archives as well
+ * as ZIP64 format.
+ */
public class ZipReader {
public static final Logger logger = LoggerFactory.getLogger(ZipReader.class);
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/ZipWriter.java b/sdk/src/main/java/io/opentdf/platform/sdk/ZipWriter.java
index d775a0a8..71aea34c 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/ZipWriter.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/ZipWriter.java
@@ -9,6 +9,10 @@
import java.util.ArrayList;
import java.util.zip.CRC32;
+/**
+ * The ZipWriter class provides functionalities to create ZIP archive files.
+ * It writes files and data to an underlying output stream in the ZIP file format.
+ */
public class ZipWriter {
private static final int ZIP_VERSION = 0x2D;
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/package-info.java b/sdk/src/main/java/io/opentdf/platform/sdk/package-info.java
new file mode 100644
index 00000000..cd3ae44a
--- /dev/null
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/package-info.java
@@ -0,0 +1,19 @@
+/**
+ * The io.opentdf.platform.sdk package provides a comprehensive set of
+ * classes, interfaces, enums, and exceptions designed for interacting with
+ * the OpenTDF platform. At its core, the {@link io.opentdf.platform.sdk.SDK} class
+ * serves as the centerpiece for this package, representing a software development kit
+ * that facilitates integration with the OpenTDF services. The package also includes
+ * classes for various encryption and decryption operations such as {@link io.opentdf.platform.sdk.AesGcm}
+ * and its inner classes, as well as support for assertions and configurations through
+ * classes like {@link io.opentdf.platform.sdk.AssertionConfig} and {@link io.opentdf.platform.sdk.Config}.
+ * Additionally, utility classes such as {@link io.opentdf.platform.sdk.CryptoUtils} and
+ * functionality for reading and writing TDF files are provided via {@link io.opentdf.platform.sdk.TDFReader}
+ * and {@link io.opentdf.platform.sdk.TDFWriter}. The package also defines a collection of
+ * enums for various configurations and state definitions, alongside a comprehensive
+ * set of exceptions to handle different error scenarios, ensuring robust and secure
+ * operations within the OpenTDF ecosystem.
+ *
+ * @since 1.0
+ */
+package io.opentdf.platform.sdk;
\ No newline at end of file
From dcfbb56d39a6f3a634df1ba6ae030c4be8e68d28 Mon Sep 17 00:00:00 2001
From: Paul Flynn <43211074+pflynn-virtru@users.noreply.github.com>
Date: Mon, 21 Oct 2024 13:48:05 -0400
Subject: [PATCH 04/14] ci: coverage report fix (#198)
Configured the Jacoco plugin to specify the output directory for report
generation. This change ensures that the report is consistently placed
in the target directory for easier access and management.
---
.github/workflows/checks.yaml | 18 +++++++++++++++++-
sdk/pom.xml | 1 +
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml
index 98b89f76..91e4e99b 100644
--- a/.github/workflows/checks.yaml
+++ b/.github/workflows/checks.yaml
@@ -53,6 +53,8 @@ jobs:
steps:
- name: Check out repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ with:
+ fetch-depth: 0
- uses: bufbuild/buf-setup-action@2211e06e8cf26d628cda2eea15c95f8c42b080b3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
@@ -62,11 +64,25 @@ jobs:
java-version: "17"
distribution: "temurin"
server-id: github
+ - name: Cache SonarCloud packages
+ uses: actions/cache@v4
+ with:
+ path: ~/.sonar/cache
+ key: ${{ runner.os }}-sonar
+ restore-keys: ${{ runner.os }}-sonar
+ - name: Cache Maven packages
+ uses: actions/cache@v4
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ restore-keys: ${{ runner.os }}-m2
- name: Maven Test Coverage
env:
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUF_INPUT_HTTPS_USERNAME: opentdf-bot
BUF_INPUT_HTTPS_PASSWORD: ${{ secrets.PERSONAL_ACCESS_TOKEN_OPENTDF }}
- run: mvn --batch-mode clean verify -P coverage
+ run: mvn --batch-mode clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=opentdf_java-sdk -P coverage
platform-integration:
runs-on: ubuntu-22.04
diff --git a/sdk/pom.xml b/sdk/pom.xml
index b6f06e1e..0e608949 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -297,6 +297,7 @@
${project.parent.basedir}/target/jacoco.exec
+ ${project.parent.basedir}/target/site/jacoco/XML
From 1dffd35374c40ebaa095594d2a5db138957c6e38 Mon Sep 17 00:00:00 2001
From: sujankota
Date: Thu, 24 Oct 2024 11:13:08 -0400
Subject: [PATCH 05/14] fix(sdk): returns the correct string associated with
enums (#200)
---
.../io/opentdf/platform/sdk/AssertionConfig.java | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/AssertionConfig.java b/sdk/src/main/java/io/opentdf/platform/sdk/AssertionConfig.java
index 100f824f..c31fc1b0 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/AssertionConfig.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/AssertionConfig.java
@@ -34,6 +34,11 @@ public enum Scope {
Scope(String scope) {
this.scope = scope;
}
+
+ @Override
+ public String toString() {
+ return scope;
+ }
}
public enum AssertionKeyAlg {
@@ -51,6 +56,11 @@ public enum AppliesToState {
AppliesToState(String state) {
this.state = state;
}
+
+ @Override
+ public String toString() {
+ return state;
+ }
}
public enum BindingMethod {
@@ -61,6 +71,11 @@ public enum BindingMethod {
BindingMethod(String method) {
this.method = method;
}
+
+ @Override
+ public String toString() {
+ return method;
+ }
}
static public class AssertionKey {
From 4084f44b31830b3385dcc641d1388fe2c769bd28 Mon Sep 17 00:00:00 2001
From: "opentdf-automation[bot]"
<149537512+opentdf-automation[bot]@users.noreply.github.com>
Date: Thu, 24 Oct 2024 15:40:56 -0400
Subject: [PATCH 06/14] chore(main): release 0.7.4 (#194)
:robot: I have created a release *beep* *boop*
---
0.7.4
## [0.7.4](https://github.com/opentdf/java-sdk/compare/v0.7.3...v0.7.4)
(2024-10-24)
### Bug Fixes
* **sdk:** returns the correct string associated with enums
([#200](https://github.com/opentdf/java-sdk/issues/200))
([1dffd35](https://github.com/opentdf/java-sdk/commit/1dffd35374c40ebaa095594d2a5db138957c6e38))
### Documentation
* JavaDoc ([#196](https://github.com/opentdf/java-sdk/issues/196))
([33c9513](https://github.com/opentdf/java-sdk/commit/33c9513de68954cccba854d501ba26b62216df89))
* minor Java SDK README updates
([#193](https://github.com/opentdf/java-sdk/issues/193))
([e9dc738](https://github.com/opentdf/java-sdk/commit/e9dc738cc40ffc97d3f0084086b1afa1c283850c))
---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com>
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 13 +++++++++++++
cmdline/pom.xml | 2 +-
pom.xml | 2 +-
sdk/pom.xml | 2 +-
5 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 88ca3ece..904b037e 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.7.3"
+ ".": "0.7.4"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d54306d4..453b346e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## [0.7.4](https://github.com/opentdf/java-sdk/compare/v0.7.3...v0.7.4) (2024-10-24)
+
+
+### Bug Fixes
+
+* **sdk:** returns the correct string associated with enums ([#200](https://github.com/opentdf/java-sdk/issues/200)) ([1dffd35](https://github.com/opentdf/java-sdk/commit/1dffd35374c40ebaa095594d2a5db138957c6e38))
+
+
+### Documentation
+
+* JavaDoc ([#196](https://github.com/opentdf/java-sdk/issues/196)) ([33c9513](https://github.com/opentdf/java-sdk/commit/33c9513de68954cccba854d501ba26b62216df89))
+* minor Java SDK README updates ([#193](https://github.com/opentdf/java-sdk/issues/193)) ([e9dc738](https://github.com/opentdf/java-sdk/commit/e9dc738cc40ffc97d3f0084086b1afa1c283850c))
+
## [0.7.3](https://github.com/opentdf/java-sdk/compare/v0.7.2...v0.7.3) (2024-10-09)
diff --git a/cmdline/pom.xml b/cmdline/pom.xml
index 705455f6..897f5658 100644
--- a/cmdline/pom.xml
+++ b/cmdline/pom.xml
@@ -4,7 +4,7 @@
io.opentdf.platformsdk-pom
- 0.7.4-SNAPSHOT
+ 0.7.4cmdline
diff --git a/pom.xml b/pom.xml
index 4e186854..30fe54e6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
io.opentdf.platformsdk-pom
- 0.7.4-SNAPSHOT
+ 0.7.4io.opentdf.platform:sdk-pomOpenTDF Java SDKhttps://github.com/opentdf/java-sdk
diff --git a/sdk/pom.xml b/sdk/pom.xml
index 0e608949..db01dbc2 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -6,7 +6,7 @@
sdk-pomio.opentdf.platform
- 0.7.4-SNAPSHOT
+ 0.7.4jar
From ac13a0a7c82caed920238244cf7adaca3039fdea Mon Sep 17 00:00:00 2001
From: Elizabeth Healy <35498075+elizabethhealy@users.noreply.github.com>
Date: Mon, 28 Oct 2024 14:22:18 -0400
Subject: [PATCH 07/14] feat: Examples module (#202)
The examples that we provide in the docs repo
Add a module to manage them here
Compile in ci to ensure there are no breaking changes to docs
---
examples/buf.gen.yaml | 14 ++
examples/buf.lock | 18 ++
examples/buf.yaml | 22 +++
examples/pom.xml | 179 ++++++++++++++++++
.../main/java/io/opentdf/platform/App.java | 7 +
.../io/opentdf/platform/CreateAttribute.java | 36 ++++
.../io/opentdf/platform/CreateNamespace.java | 27 +++
.../platform/CreateSubjectConditionSet.java | 47 +++++
.../platform/CreateSubjectMapping.java | 34 ++++
.../io/opentdf/platform/DecryptExample.java | 42 ++++
.../io/opentdf/platform/EncryptExample.java | 39 ++++
.../io/opentdf/platform/GetDecisions.java | 37 ++++
.../io/opentdf/platform/GetEntitlements.java | 32 ++++
.../io/opentdf/platform/ListAttributes.java | 34 ++++
.../io/opentdf/platform/ListNamespaces.java | 27 +++
.../opentdf/platform/ListSubjectMappings.java | 32 ++++
examples/src/main/resources/log4j2.xml | 16 ++
pom.xml | 1 +
18 files changed, 644 insertions(+)
create mode 100644 examples/buf.gen.yaml
create mode 100644 examples/buf.lock
create mode 100644 examples/buf.yaml
create mode 100644 examples/pom.xml
create mode 100644 examples/src/main/java/io/opentdf/platform/App.java
create mode 100644 examples/src/main/java/io/opentdf/platform/CreateAttribute.java
create mode 100644 examples/src/main/java/io/opentdf/platform/CreateNamespace.java
create mode 100644 examples/src/main/java/io/opentdf/platform/CreateSubjectConditionSet.java
create mode 100644 examples/src/main/java/io/opentdf/platform/CreateSubjectMapping.java
create mode 100644 examples/src/main/java/io/opentdf/platform/DecryptExample.java
create mode 100644 examples/src/main/java/io/opentdf/platform/EncryptExample.java
create mode 100644 examples/src/main/java/io/opentdf/platform/GetDecisions.java
create mode 100644 examples/src/main/java/io/opentdf/platform/GetEntitlements.java
create mode 100644 examples/src/main/java/io/opentdf/platform/ListAttributes.java
create mode 100644 examples/src/main/java/io/opentdf/platform/ListNamespaces.java
create mode 100644 examples/src/main/java/io/opentdf/platform/ListSubjectMappings.java
create mode 100644 examples/src/main/resources/log4j2.xml
diff --git a/examples/buf.gen.yaml b/examples/buf.gen.yaml
new file mode 100644
index 00000000..6bb9c4e3
--- /dev/null
+++ b/examples/buf.gen.yaml
@@ -0,0 +1,14 @@
+version: v1
+managed:
+ enabled: true
+ java_package_prefix:
+ default: io.opentdf.platform
+ except:
+ - buf.build/bufbuild/protovalidate
+ - buf.build/googleapis/googleapis
+ - buf.build/grpc-ecosystem/grpc-gateway
+plugins:
+ - plugin: buf.build/protocolbuffers/java:v25.3
+ out: ./
+ - plugin: buf.build/grpc/java:v1.61.1
+ out: ./
diff --git a/examples/buf.lock b/examples/buf.lock
new file mode 100644
index 00000000..deef61e8
--- /dev/null
+++ b/examples/buf.lock
@@ -0,0 +1,18 @@
+# Generated by buf. DO NOT EDIT.
+version: v1
+deps:
+ - remote: buf.build
+ owner: bufbuild
+ repository: protovalidate
+ commit: f05a6f4403ce4327bae4f50f281c3ed0
+ digest: shake256:668a0661b8df44d41839194896329330965fc215f3d2f88057fd60eeb759c2daf6cc6edfdd13b2a653d49fe2896ebedcb1a33c4c5b2dd10919f03ffb7fc52ae6
+ - remote: buf.build
+ owner: googleapis
+ repository: googleapis
+ commit: 7e6f6e774e29406da95bd61cdcdbc8bc
+ digest: shake256:fe43dd2265ea0c07d76bd925eeba612667cf4c948d2ce53d6e367e1b4b3cb5fa69a51e6acb1a6a50d32f894f054a35e6c0406f6808a483f2752e10c866ffbf73
+ - remote: buf.build
+ owner: grpc-ecosystem
+ repository: grpc-gateway
+ commit: 3f42134f4c564983838425bc43c7a65f
+ digest: shake256:3d11d4c0fe5e05fda0131afefbce233940e27f0c31c5d4e385686aea58ccd30f72053f61af432fa83f1fc11cda57f5f18ca3da26a29064f73c5a0d076bba8d92
\ No newline at end of file
diff --git a/examples/buf.yaml b/examples/buf.yaml
new file mode 100644
index 00000000..2dc8eb0e
--- /dev/null
+++ b/examples/buf.yaml
@@ -0,0 +1,22 @@
+version: v1
+deps:
+ - buf.build/bufbuild/protovalidate
+ - buf.build/googleapis/googleapis
+ - buf.build/grpc-ecosystem/grpc-gateway
+breaking:
+ use:
+ - FILE
+ - PACKAGE
+ - WIRE_JSON
+ - WIRE
+lint:
+ allow_comment_ignores: true
+ use:
+ - DEFAULT
+ except:
+ - PACKAGE_VERSION_SUFFIX
+ ignore_only:
+ PACKAGE_VERSION_SUFFIX:
+ - google/api/annotations.proto
+ - google/api/http.proto
+ - google/protobuf/wrappers.proto
diff --git a/examples/pom.xml b/examples/pom.xml
new file mode 100644
index 00000000..28915c44
--- /dev/null
+++ b/examples/pom.xml
@@ -0,0 +1,179 @@
+
+
+ 4.0.0
+
+ sdk-pom
+ io.opentdf.platform
+ 0.7.4
+
+
+ io.opentdf.platform
+ examples
+ 0.7.4
+
+ examples
+
+ http://www.example.com
+
+
+ UTF-8
+ 11
+
+
+
+
+
+ org.junit
+ junit-bom
+ 5.11.0
+ pom
+ import
+
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
+
+ io.opentdf.platform
+ sdk
+ ${project.version}
+
+
+ com.google.code.gson
+ gson
+ 2.11.0
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+
+
+ org.apache.logging.log4j
+ log4j-core
+
+
+ org.apache.logging.log4j
+ log4j-api
+
+
+ javax.annotation
+ javax.annotation-api
+ 1.3.2
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.4
+
+
+ package
+
+ shade
+
+
+ false
+
+
+ io.opentdf.platform.App
+
+ ${project.version}
+ io.opentdf.platform.App
+
+
+
+
+
+
+ *:*
+
+ META-INF/*.SF
+ META-INF/*.DSA
+ META-INF/*.RSA
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.0.0
+
+ io.opentdf.platform.App
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 3.1.0
+
+
+
+ generateSources
+ generate-sources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.5.0
+
+
+ add-source
+ generate-sources
+
+ add-source
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/src/main/java/io/opentdf/platform/App.java b/examples/src/main/java/io/opentdf/platform/App.java
new file mode 100644
index 00000000..22958126
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/App.java
@@ -0,0 +1,7 @@
+package io.opentdf.platform;
+
+public class App {
+ public static void main(String[] args) {
+ System.out.println("opentdf examples");
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/CreateAttribute.java b/examples/src/main/java/io/opentdf/platform/CreateAttribute.java
new file mode 100644
index 00000000..ba72189e
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/CreateAttribute.java
@@ -0,0 +1,36 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+
+import java.util.concurrent.ExecutionException;
+
+import io.opentdf.platform.policy.AttributeRuleTypeEnum;
+
+import io.opentdf.platform.policy.attributes.*;
+import io.opentdf.platform.policy.Attribute;
+
+import java.util.Arrays;
+
+public class CreateAttribute {
+ public static void main(String[] args) throws ExecutionException, InterruptedException{
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ CreateAttributeRequest request = CreateAttributeRequest.newBuilder()
+ .setNamespaceId("877990d1-609b-42ab-a273-4253b8b321eb")
+ .setName("test")
+ .setRule(AttributeRuleTypeEnum.forNumber(AttributeRuleTypeEnum.ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF_VALUE))
+ .addAllValues(Arrays.asList("test1", "test2")).build();
+
+ CreateAttributeResponse resp = sdk.getServices().attributes().createAttribute(request).get();
+
+ Attribute attribute = resp.getAttribute();
+
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/CreateNamespace.java b/examples/src/main/java/io/opentdf/platform/CreateNamespace.java
new file mode 100644
index 00000000..112cde4f
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/CreateNamespace.java
@@ -0,0 +1,27 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+
+import java.util.concurrent.ExecutionException;
+
+import io.opentdf.platform.policy.namespaces.*;
+
+public class CreateNamespace {
+ public static void main(String[] args) throws ExecutionException, InterruptedException{
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ CreateNamespaceRequest request = CreateNamespaceRequest.newBuilder().setName("mynamespace.com").build();
+
+ CreateNamespaceResponse resp = sdk.getServices().namespaces().createNamespace(request).get();
+
+ System.out.println(resp.getNamespace().getName());
+
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/CreateSubjectConditionSet.java b/examples/src/main/java/io/opentdf/platform/CreateSubjectConditionSet.java
new file mode 100644
index 00000000..0eb6c5a2
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/CreateSubjectConditionSet.java
@@ -0,0 +1,47 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+
+import java.util.concurrent.ExecutionException;
+
+import io.opentdf.platform.policy.subjectmapping.*;
+import io.opentdf.platform.policy.SubjectMapping;
+import io.opentdf.platform.policy.SubjectConditionSet;
+import io.opentdf.platform.policy.SubjectSet;
+import io.opentdf.platform.policy.ConditionGroup;
+import io.opentdf.platform.policy.Condition;
+import io.opentdf.platform.policy.ConditionBooleanTypeEnum;
+import io.opentdf.platform.policy.SubjectMappingOperatorEnum;
+
+
+public class CreateSubjectConditionSet {
+ public static void main(String[] args) throws ExecutionException, InterruptedException{
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ var subjectset = SubjectSet.newBuilder().addConditionGroups(ConditionGroup.newBuilder()
+ .setBooleanOperator(ConditionBooleanTypeEnum.CONDITION_BOOLEAN_TYPE_ENUM_AND)
+ .addConditions(Condition.newBuilder()
+ .setSubjectExternalSelectorValue(".myfield")
+ .setOperator(SubjectMappingOperatorEnum.SUBJECT_MAPPING_OPERATOR_ENUM_IN)
+ .addSubjectExternalValues("myvalue")
+ ));
+
+ CreateSubjectConditionSetRequest request = CreateSubjectConditionSetRequest.newBuilder()
+ .setSubjectConditionSet(
+ SubjectConditionSetCreate.newBuilder().addSubjectSets(subjectset))
+ .build();
+
+ CreateSubjectConditionSetResponse resp = sdk.getServices().subjectMappings().createSubjectConditionSet(request).get();
+
+ SubjectConditionSet scs = resp.getSubjectConditionSet();
+
+ System.out.println(scs.getId());
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/CreateSubjectMapping.java b/examples/src/main/java/io/opentdf/platform/CreateSubjectMapping.java
new file mode 100644
index 00000000..41f07336
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/CreateSubjectMapping.java
@@ -0,0 +1,34 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+
+import java.util.concurrent.ExecutionException;
+
+import io.opentdf.platform.policy.subjectmapping.*;
+import io.opentdf.platform.policy.SubjectMapping;
+import io.opentdf.platform.policy.Action;
+
+public class CreateSubjectMapping {
+ public static void main(String[] args) throws ExecutionException, InterruptedException{
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ CreateSubjectMappingRequest request = CreateSubjectMappingRequest.newBuilder()
+ .setAttributeValueId("33c47777-f3b6-492d-bcd2-5329e0aab642")
+ .addActions(Action.newBuilder().setStandard(Action.StandardAction.STANDARD_ACTION_DECRYPT))
+ .setExistingSubjectConditionSetId("9009fde8-d22b-4dfb-a456-f9ce6943244a")
+ .build();
+
+ CreateSubjectMappingResponse resp = sdk.getServices().subjectMappings().createSubjectMapping(request).get();
+
+ SubjectMapping sm = resp.getSubjectMapping();
+
+ System.out.println(sm.getId());
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/DecryptExample.java b/examples/src/main/java/io/opentdf/platform/DecryptExample.java
new file mode 100644
index 00000000..693192ca
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/DecryptExample.java
@@ -0,0 +1,42 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+import java.nio.file.StandardOpenOption;
+import java.nio.channels.FileChannel;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.nimbusds.jose.JOSEException;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.text.ParseException;
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import org.apache.commons.codec.DecoderException;
+
+
+public class DecryptExample {
+ public static void main(String[] args) throws IOException,
+ InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException,
+ BadPaddingException, InvalidKeyException, TDF.FailedToCreateGMAC,
+ JOSEException, ParseException, NoSuchAlgorithmException, DecoderException {
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ Path path = Paths.get("my.ciphertext");
+ try (var in = FileChannel.open(path, StandardOpenOption.READ)) {
+ var reader = new TDF().loadTDF(in, sdk.getServices().kas());
+ reader.readPayload(System.out);
+ }
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/EncryptExample.java b/examples/src/main/java/io/opentdf/platform/EncryptExample.java
new file mode 100644
index 00000000..6da5d47c
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/EncryptExample.java
@@ -0,0 +1,39 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+import java.io.ByteArrayInputStream;
+import java.io.BufferedOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.io.FileOutputStream;
+
+import com.nimbusds.jose.JOSEException;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+
+public class EncryptExample {
+ public static void main(String[] args) throws IOException, JOSEException, AutoConfigureException, InterruptedException, ExecutionException {
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ var kasInfo = new Config.KASInfo();
+ kasInfo.URL = "http://localhost:8080/kas";
+
+ var tdfConfig = Config.newTDFConfig(Config.withKasInformation(kasInfo), Config.withDataAttributes("https://example.com/attr/color/value/red"));
+
+ String str = "Hello, World!";
+
+ // Convert String to InputStream
+ var in = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+
+ FileOutputStream fos = new FileOutputStream("my.ciphertext");
+
+ new TDF().createTDF(in, fos, tdfConfig,
+ sdk.getServices().kas(),
+ sdk.getServices().attributes());
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/GetDecisions.java b/examples/src/main/java/io/opentdf/platform/GetDecisions.java
new file mode 100644
index 00000000..4bac7694
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/GetDecisions.java
@@ -0,0 +1,37 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+
+import java.util.concurrent.ExecutionException;
+
+import io.opentdf.platform.authorization.*;
+import io.opentdf.platform.policy.Action;
+
+import java.util.List;
+
+public class GetDecisions {
+ public static void main(String[] args) throws ExecutionException, InterruptedException{
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ GetDecisionsRequest request = GetDecisionsRequest.newBuilder()
+ .addDecisionRequests(DecisionRequest.newBuilder()
+ .addEntityChains(EntityChain.newBuilder().setId("ec1").addEntities(Entity.newBuilder().setId("entity-1").setClientId("opentdf")))
+ .addActions(Action.newBuilder().setStandard(Action.StandardAction.STANDARD_ACTION_DECRYPT))
+ .addResourceAttributes(ResourceAttribute.newBuilder().setResourceAttributesId("resource-attribute-1")
+ .addAttributeValueFqns("https://mynamespace.com/attr/test/value/test1"))
+ ).build();
+
+ GetDecisionsResponse resp = sdk.getServices().authorization().getDecisions(request).get();
+
+ List decisions = resp.getDecisionResponsesList();
+
+ System.out.println(DecisionResponse.Decision.forNumber(decisions.get(0).getDecisionValue()));
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/GetEntitlements.java b/examples/src/main/java/io/opentdf/platform/GetEntitlements.java
new file mode 100644
index 00000000..ff484b80
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/GetEntitlements.java
@@ -0,0 +1,32 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+
+import java.util.concurrent.ExecutionException;
+
+import io.opentdf.platform.authorization.*;
+
+import java.util.List;
+
+public class GetEntitlements {
+ public static void main(String[] args) throws ExecutionException, InterruptedException{
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ GetEntitlementsRequest request = GetEntitlementsRequest.newBuilder()
+ .addEntities(Entity.newBuilder().setId("entity-1").setClientId("opentdf"))
+ .build();
+
+ GetEntitlementsResponse resp = sdk.getServices().authorization().getEntitlements(request).get();
+
+ List entitlements = resp.getEntitlementsList();
+
+ System.out.println(entitlements.get(0).getAttributeValueFqnsList());
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/ListAttributes.java b/examples/src/main/java/io/opentdf/platform/ListAttributes.java
new file mode 100644
index 00000000..366af20a
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/ListAttributes.java
@@ -0,0 +1,34 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+
+import java.util.concurrent.ExecutionException;
+
+import io.opentdf.platform.policy.AttributeRuleTypeEnum;
+
+import io.opentdf.platform.policy.attributes.*;
+import io.opentdf.platform.policy.Attribute;
+
+import java.util.List;
+
+public class ListAttributes {
+ public static void main(String[] args) throws ExecutionException, InterruptedException{
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ ListAttributesRequest request = ListAttributesRequest.newBuilder()
+ .setNamespace("mynamespace.com").build();
+
+ ListAttributesResponse resp = sdk.getServices().attributes().listAttributes(request).get();
+
+ List attributes = resp.getAttributesList();
+
+ System.out.println(resp.getAttributesCount());
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/ListNamespaces.java b/examples/src/main/java/io/opentdf/platform/ListNamespaces.java
new file mode 100644
index 00000000..43e514a5
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/ListNamespaces.java
@@ -0,0 +1,27 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+
+import java.util.concurrent.ExecutionException;
+
+import io.opentdf.platform.policy.namespaces.*;
+import io.opentdf.platform.policy.Namespace;
+
+public class ListNamespaces {
+ public static void main(String[] args) throws ExecutionException, InterruptedException{
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ ListNamespacesRequest request = ListNamespacesRequest.newBuilder().build();
+
+ ListNamespacesResponse resp = sdk.getServices().namespaces().listNamespaces(request).get();
+
+ java.util.List namespaces = resp.getNamespacesList();
+ }
+}
diff --git a/examples/src/main/java/io/opentdf/platform/ListSubjectMappings.java b/examples/src/main/java/io/opentdf/platform/ListSubjectMappings.java
new file mode 100644
index 00000000..12bc4ab7
--- /dev/null
+++ b/examples/src/main/java/io/opentdf/platform/ListSubjectMappings.java
@@ -0,0 +1,32 @@
+package io.opentdf.platform;
+import io.opentdf.platform.sdk.*;
+
+import java.util.concurrent.ExecutionException;
+
+import io.opentdf.platform.policy.subjectmapping.*;
+import io.opentdf.platform.policy.SubjectMapping;
+
+import java.util.List;
+
+public class ListSubjectMappings {
+ public static void main(String[] args) throws ExecutionException, InterruptedException{
+
+ String clientId = "opentdf";
+ String clientSecret = "secret";
+ String platformEndpoint = "localhost:8080";
+
+ SDKBuilder builder = new SDKBuilder();
+ SDK sdk = builder.platformEndpoint(platformEndpoint)
+ .clientSecret(clientId, clientSecret).useInsecurePlaintextConnection(true)
+ .build();
+
+ ListSubjectMappingsRequest request = ListSubjectMappingsRequest.newBuilder().build();
+
+ ListSubjectMappingsResponse resp = sdk.getServices().subjectMappings().listSubjectMappings(request).get();
+
+ List sms = resp.getSubjectMappingsList();
+
+ System.out.println(sms.size());
+ System.out.println(sms.get(0).getId());
+ }
+}
diff --git a/examples/src/main/resources/log4j2.xml b/examples/src/main/resources/log4j2.xml
new file mode 100644
index 00000000..da185a60
--- /dev/null
+++ b/examples/src/main/resources/log4j2.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 30fe54e6..e1b0ec0f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -267,6 +267,7 @@
sdkcmdline
+ examplestrue
From 78d7b66e40bb52340e604ab645830287c91ba534 Mon Sep 17 00:00:00 2001
From: sujankota
Date: Tue, 29 Oct 2024 14:11:12 -0400
Subject: [PATCH 08/14] fix(sdk): option to disable assertion verification
(#205)
---
.../java/io/opentdf/platform/sdk/Config.java | 8 ++-
.../java/io/opentdf/platform/sdk/TDF.java | 18 ++++-
.../io/opentdf/platform/sdk/TDFE2ETest.java | 2 +-
.../java/io/opentdf/platform/sdk/TDFTest.java | 67 ++++++++++++++++++-
4 files changed, 87 insertions(+), 8 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 c7d4f092..1f44854a 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/Config.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/Config.java
@@ -91,12 +91,14 @@ AssertionConfig.AssertionKey getKey(String key) {
public static class TDFReaderConfig {
// Optional Map of Assertion Verification Keys
- AssertionVerificationKeys assertionVerificationKeys;
+ AssertionVerificationKeys assertionVerificationKeys = new AssertionVerificationKeys();
+ boolean disableAssertionVerification;
}
@SafeVarargs
public static TDFReaderConfig newTDFReaderConfig(Consumer... options) {
TDFReaderConfig config = new TDFReaderConfig();
+ config.disableAssertionVerification = false;
for (Consumer option : options) {
option.accept(config);
}
@@ -108,6 +110,10 @@ public static Consumer withAssertionVerificationKeys(
return (TDFReaderConfig config) -> config.assertionVerificationKeys = assertionVerificationKeys;
}
+ public static Consumer withDisableAssertionVerification(boolean disable) {
+ return (TDFReaderConfig config) -> config.disableAssertionVerification = disable;
+ }
+
public static class TDFConfig {
public Boolean autoconfigure;
public int defaultSegmentSize;
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 aec26e80..d694cea7 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
@@ -550,8 +550,14 @@ public List defaultKases(TDFConfig config) {
return defk;
}
+ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas)
+ throws DecoderException, IOException, ParseException, NoSuchAlgorithmException, JOSEException {
+ return loadTDF(tdf, kas, new Config.TDFReaderConfig());
+ }
+
+
public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas,
- Config.AssertionVerificationKeys... assertionVerificationKeys)
+ Config.TDFReaderConfig tdfReaderConfig)
throws NotValidateRootSignature, SegmentSizeMismatch,
IOException, FailedToCreateGMAC, JOSEException, ParseException, NoSuchAlgorithmException, DecoderException {
@@ -672,10 +678,16 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas,
// Validate assertions
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);
- if (assertionVerificationKeys != null && assertionVerificationKeys.length > 0) {
- var keyForAssertion = assertionVerificationKeys[0].getKey(assertion.id);
+ Config.AssertionVerificationKeys assertionVerificationKeys = tdfReaderConfig.assertionVerificationKeys;
+ if (!assertionVerificationKeys.isEmpty()) {
+ var keyForAssertion = assertionVerificationKeys.getKey(assertion.id);
if (keyForAssertion != null) {
assertionKey = keyForAssertion;
}
diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/TDFE2ETest.java b/sdk/src/test/java/io/opentdf/platform/sdk/TDFE2ETest.java
index fb44663c..11a41bc8 100644
--- a/sdk/src/test/java/io/opentdf/platform/sdk/TDFE2ETest.java
+++ b/sdk/src/test/java/io/opentdf/platform/sdk/TDFE2ETest.java
@@ -38,7 +38,7 @@ public void createAndDecryptTdfIT() throws Exception {
tdf.createTDF(plainTextInputStream, tdfOutputStream, config, sdk.kas(), sdk.attributes());
var unwrappedData = new java.io.ByteArrayOutputStream();
- var reader = tdf.loadTDF(new SeekableInMemoryByteChannel(tdfOutputStream.toByteArray()), sdk.kas());
+ var reader = tdf.loadTDF(new SeekableInMemoryByteChannel(tdfOutputStream.toByteArray()), sdk.kas());
reader.readPayload(unwrappedData);
assertThat(unwrappedData.toString(StandardCharsets.UTF_8)).isEqualTo("text");
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 e4fed930..8afb5545 100644
--- a/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java
+++ b/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java
@@ -2,6 +2,7 @@
import com.google.common.util.concurrent.ListenableFuture;
+import com.nimbusds.jose.JOSEException;
import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsRequest;
import io.opentdf.platform.policy.attributes.GetAttributeValuesByFqnsResponse;
import io.opentdf.platform.policy.attributes.AttributesServiceGrpc;
@@ -136,8 +137,10 @@ void testSimpleTDFEncryptAndDecrypt() throws Exception {
key);
var unwrappedData = new ByteArrayOutputStream();
+ Config.TDFReaderConfig readerConfig = Config.newTDFReaderConfig(
+ Config.withAssertionVerificationKeys(assertionVerificationKeys));
var reader = tdf.loadTDF(new SeekableInMemoryByteChannel(tdfOutputStream.toByteArray()), kas,
- assertionVerificationKeys);
+ readerConfig);
assertThat(reader.getManifest().payload.mimeType).isEqualTo("application/octet-stream");
reader.readPayload(unwrappedData);
@@ -192,8 +195,10 @@ void testSimpleTDFWithAssertionWithRS256() throws Exception {
new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.RS256, keypair.getPublic()));
var unwrappedData = new ByteArrayOutputStream();
+ Config.TDFReaderConfig readerConfig = Config.newTDFReaderConfig(
+ Config.withAssertionVerificationKeys(assertionVerificationKeys));
var reader = tdf.loadTDF(new SeekableInMemoryByteChannel(tdfOutputStream.toByteArray()), kas,
- assertionVerificationKeys);
+ readerConfig);
reader.readPayload(unwrappedData);
assertThat(unwrappedData.toString(StandardCharsets.UTF_8))
@@ -201,6 +206,61 @@ void testSimpleTDFWithAssertionWithRS256() throws Exception {
.isEqualTo(plainText);
}
+ @Test
+ void testWithAssertionVerificationDisabled() throws Exception {
+
+ ListenableFuture resp1 = mock(ListenableFuture.class);
+ lenient().when(resp1.get()).thenReturn(GetAttributeValuesByFqnsResponse.newBuilder().build());
+ lenient().when(attributeGrpcStub.getAttributeValuesByFqns(any(GetAttributeValuesByFqnsRequest.class)))
+ .thenReturn(resp1);
+
+ String assertion1Id = "assertion1";
+ var keypair = CryptoUtils.generateRSAKeypair();
+ var assertionConfig = new AssertionConfig();
+ assertionConfig.id = assertion1Id;
+ assertionConfig.type = AssertionConfig.Type.BaseAssertion;
+ assertionConfig.scope = AssertionConfig.Scope.TrustedDataObj;
+ assertionConfig.appliesToState = AssertionConfig.AppliesToState.Unencrypted;
+ assertionConfig.statement = new AssertionConfig.Statement();
+ assertionConfig.statement.format = "base64binary";
+ assertionConfig.statement.schema = "text";
+ assertionConfig.statement.value = "ICAgIDxlZGoOkVkaD4=";
+ assertionConfig.assertionKey = new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.RS256,
+ keypair.getPrivate());
+
+ Config.TDFConfig config = Config.newTDFConfig(
+ Config.withAutoconfigure(false),
+ Config.withKasInformation(getKASInfos()),
+ Config.withAssertionConfig(assertionConfig));
+
+ String plainText = "this is extremely sensitive stuff!!!";
+ InputStream plainTextInputStream = new ByteArrayInputStream(plainText.getBytes());
+ ByteArrayOutputStream tdfOutputStream = new ByteArrayOutputStream();
+
+ TDF tdf = new TDF();
+ tdf.createTDF(plainTextInputStream, tdfOutputStream, config, kas, attributeGrpcStub);
+
+ var assertionVerificationKeys = new Config.AssertionVerificationKeys();
+ assertionVerificationKeys.keys.put(assertion1Id,
+ new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.RS256, keypair.getPublic()));
+
+ var unwrappedData = new ByteArrayOutputStream();
+ assertThrows(JOSEException.class, () -> {
+ tdf.loadTDF(new SeekableInMemoryByteChannel(tdfOutputStream.toByteArray()), kas,
+ new Config.TDFReaderConfig());
+ });
+
+ // try with assertion verification disabled and not passing the assertion verification keys
+ Config.TDFReaderConfig readerConfig = Config.newTDFReaderConfig(
+ Config.withDisableAssertionVerification(true));
+ var reader = tdf.loadTDF(new SeekableInMemoryByteChannel(tdfOutputStream.toByteArray()), kas,
+ readerConfig);
+ reader.readPayload(unwrappedData);
+
+ assertThat(unwrappedData.toString(StandardCharsets.UTF_8))
+ .withFailMessage("extracted data does not match")
+ .isEqualTo(plainText);
+ }
@Test
void testSimpleTDFWithAssertionWithHS256() throws Exception {
@@ -244,7 +304,8 @@ void testSimpleTDFWithAssertionWithHS256() throws Exception {
tdf.createTDF(plainTextInputStream, tdfOutputStream, config, kas, attributeGrpcStub);
var unwrappedData = new ByteArrayOutputStream();
- var reader = tdf.loadTDF(new SeekableInMemoryByteChannel(tdfOutputStream.toByteArray()), kas);
+ var reader = tdf.loadTDF(new SeekableInMemoryByteChannel(tdfOutputStream.toByteArray()),
+ kas, new Config.TDFReaderConfig());
reader.readPayload(unwrappedData);
assertThat(unwrappedData.toString(StandardCharsets.UTF_8))
From 088b88e48a63066880e840c9104df84ec0cb22c9 Mon Sep 17 00:00:00 2001
From: "opentdf-automation[bot]"
<149537512+opentdf-automation[bot]@users.noreply.github.com>
Date: Tue, 29 Oct 2024 15:12:44 -0400
Subject: [PATCH 09/14] chore(main): release 0.7.5-SNAPSHOT (#203)
:robot: I have created a release *beep* *boop*
---
0.7.5-SNAPSHOT
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
---------
Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com>
Co-authored-by: Morgan Kleene
---
cmdline/pom.xml | 2 +-
examples/pom.xml | 4 ++--
pom.xml | 2 +-
sdk/pom.xml | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/cmdline/pom.xml b/cmdline/pom.xml
index 897f5658..55916094 100644
--- a/cmdline/pom.xml
+++ b/cmdline/pom.xml
@@ -4,7 +4,7 @@
io.opentdf.platformsdk-pom
- 0.7.4
+ 0.7.5-SNAPSHOTcmdline
diff --git a/examples/pom.xml b/examples/pom.xml
index 28915c44..922f6b8b 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -4,12 +4,12 @@
sdk-pomio.opentdf.platform
- 0.7.4
+ 0.7.5-SNAPSHOTio.opentdf.platformexamples
- 0.7.4
+ 0.7.5-SNAPSHOTexamples
diff --git a/pom.xml b/pom.xml
index e1b0ec0f..d37b49cf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
io.opentdf.platformsdk-pom
- 0.7.4
+ 0.7.5-SNAPSHOTio.opentdf.platform:sdk-pomOpenTDF Java SDKhttps://github.com/opentdf/java-sdk
diff --git a/sdk/pom.xml b/sdk/pom.xml
index db01dbc2..5dfe5539 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -6,7 +6,7 @@
sdk-pomio.opentdf.platform
- 0.7.4
+ 0.7.5-SNAPSHOTjar
From 94b161d5330fbbf32923a4065c5dfa77a6a06f1b Mon Sep 17 00:00:00 2001
From: "opentdf-automation[bot]"
<149537512+opentdf-automation[bot]@users.noreply.github.com>
Date: Tue, 29 Oct 2024 15:45:14 -0400
Subject: [PATCH 10/14] chore(main): release 0.7.5 (#206)
:robot: I have created a release *beep* *boop*
---
0.7.5
## [0.7.5](https://github.com/opentdf/java-sdk/compare/v0.7.4...v0.7.5)
(2024-10-29)
### Features
* Examples module
([#202](https://github.com/opentdf/java-sdk/issues/202))
([ac13a0a](https://github.com/opentdf/java-sdk/commit/ac13a0a7c82caed920238244cf7adaca3039fdea))
### Bug Fixes
* **sdk:** option to disable assertion verification
([#205](https://github.com/opentdf/java-sdk/issues/205))
([78d7b66](https://github.com/opentdf/java-sdk/commit/78d7b66e40bb52340e604ab645830287c91ba534))
---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
---------
Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com>
Co-authored-by: Morgan Kleene
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 12 ++++++++++++
cmdline/pom.xml | 2 +-
examples/pom.xml | 3 +--
pom.xml | 2 +-
sdk/pom.xml | 2 +-
6 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 904b037e..5a8dc58d 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.7.4"
+ ".": "0.7.5"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 453b346e..59e03bdf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+## [0.7.5](https://github.com/opentdf/java-sdk/compare/v0.7.4...v0.7.5) (2024-10-29)
+
+
+### Features
+
+* Examples module ([#202](https://github.com/opentdf/java-sdk/issues/202)) ([ac13a0a](https://github.com/opentdf/java-sdk/commit/ac13a0a7c82caed920238244cf7adaca3039fdea))
+
+
+### Bug Fixes
+
+* **sdk:** option to disable assertion verification ([#205](https://github.com/opentdf/java-sdk/issues/205)) ([78d7b66](https://github.com/opentdf/java-sdk/commit/78d7b66e40bb52340e604ab645830287c91ba534))
+
## [0.7.4](https://github.com/opentdf/java-sdk/compare/v0.7.3...v0.7.4) (2024-10-24)
diff --git a/cmdline/pom.xml b/cmdline/pom.xml
index 55916094..bc33e5cc 100644
--- a/cmdline/pom.xml
+++ b/cmdline/pom.xml
@@ -4,7 +4,7 @@
io.opentdf.platformsdk-pom
- 0.7.5-SNAPSHOT
+ 0.7.5cmdline
diff --git a/examples/pom.xml b/examples/pom.xml
index 922f6b8b..47bb4783 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -4,12 +4,11 @@
sdk-pomio.opentdf.platform
- 0.7.5-SNAPSHOT
+ 0.7.5io.opentdf.platformexamples
- 0.7.5-SNAPSHOTexamples
diff --git a/pom.xml b/pom.xml
index d37b49cf..826a7dcc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
io.opentdf.platformsdk-pom
- 0.7.5-SNAPSHOT
+ 0.7.5io.opentdf.platform:sdk-pomOpenTDF Java SDKhttps://github.com/opentdf/java-sdk
diff --git a/sdk/pom.xml b/sdk/pom.xml
index 5dfe5539..678c78b0 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -6,7 +6,7 @@
sdk-pomio.opentdf.platform
- 0.7.5-SNAPSHOT
+ 0.7.5jar
From b4f95e6756f1f60fdfc8b0c2addc4e51aca4352b Mon Sep 17 00:00:00 2001
From: Elizabeth Healy <35498075+elizabethhealy@users.noreply.github.com>
Date: Wed, 30 Oct 2024 13:39:50 -0400
Subject: [PATCH 11/14] feat(sdk): Add and expose tamper error types (#187)
Exception type for tamper detection -- make it the parent to the
exception types we want to be able to catch for tamper
---------
Co-authored-by: Dave Mihalcik
---
.../io/opentdf/platform/sdk/KASClient.java | 20 ++++++-
.../io/opentdf/platform/sdk/Manifest.java | 5 +-
.../java/io/opentdf/platform/sdk/TDF.java | 38 ++++++++----
.../java/io/opentdf/platform/sdk/TDFTest.java | 58 ++++++++++++++++++-
4 files changed, 106 insertions(+), 15 deletions(-)
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java b/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java
index 727eda83..806d48d0 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java
@@ -9,13 +9,17 @@
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import io.grpc.ManagedChannel;
+import io.grpc.StatusRuntimeException;
+import io.grpc.Status;
import io.opentdf.platform.kas.AccessServiceGrpc;
import io.opentdf.platform.kas.PublicKeyRequest;
import io.opentdf.platform.kas.PublicKeyResponse;
import io.opentdf.platform.kas.RewrapRequest;
+import io.opentdf.platform.kas.RewrapResponse;
import io.opentdf.platform.sdk.Config.KASInfo;
import io.opentdf.platform.sdk.nanotdf.ECKeyPair;
import io.opentdf.platform.sdk.nanotdf.NanoTDFType;
+import io.opentdf.platform.sdk.TDF.KasBadRequestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -182,9 +186,19 @@ public byte[] unwrap(Manifest.KeyAccess keyAccess, String policy) {
.newBuilder()
.setSignedRequestToken(jwt.serialize())
.build();
- var response = getStub(keyAccess.url).rewrap(request);
- var wrappedKey = response.getEntityWrappedKey().toByteArray();
- return decryptor.decrypt(wrappedKey);
+ RewrapResponse response;
+ try {
+ response = getStub(keyAccess.url).rewrap(request);
+ var wrappedKey = response.getEntityWrappedKey().toByteArray();
+ return decryptor.decrypt(wrappedKey);
+ } catch (StatusRuntimeException e) {
+ if (e.getStatus().getCode() == Status.Code.INVALID_ARGUMENT) {
+ // 400 Bad Request
+ throw new KasBadRequestException("rewrap request 400: " + e.toString());
+ }
+ throw e;
+ }
+
}
public byte[] unwrapNanoTDF(NanoTDFType.ECCurve curve, String header, String kasURL) {
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 bc4c4c3c..aca6d1cd 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/Manifest.java
@@ -10,6 +10,9 @@
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;
@@ -381,7 +384,7 @@ public void sign(final HashValues hashValues, final AssertionConfig.AssertionKey
public Assertion.HashValues verify(AssertionConfig.AssertionKey assertionKey)
throws ParseException, JOSEException {
if (binding == null) {
- throw new SDKException("Binding is null in assertion");
+ throw new AssertionException("Binding is null in assertion", this.id);
}
String signatureString = binding.signature;
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 d694cea7..4c6eb6da 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
@@ -119,30 +119,48 @@ public FailedToCreateGMAC(String errorMessage) {
}
}
- public static class NotValidateRootSignature extends RuntimeException {
- public NotValidateRootSignature(String errorMessage) {
+ public static class TDFReadFailed extends RuntimeException {
+ public TDFReadFailed(String errorMessage) {
+ super(errorMessage);
+ }
+ }
+
+ public static class TamperException extends SDKException {
+ public TamperException(String errorMessage) {
+ super("[tamper detected] "+errorMessage);
+ }
+ }
+
+ public static class RootSignatureValidationException extends TamperException {
+ public RootSignatureValidationException(String errorMessage) {
super(errorMessage);
}
}
- public static class SegmentSizeMismatch extends RuntimeException {
+ public static class SegmentSizeMismatch extends TamperException {
public SegmentSizeMismatch(String errorMessage) {
super(errorMessage);
}
}
- public static class SegmentSignatureMismatch extends RuntimeException {
+ public static class SegmentSignatureMismatch extends TamperException {
public SegmentSignatureMismatch(String errorMessage) {
super(errorMessage);
}
}
- public static class TDFReadFailed extends RuntimeException {
- public TDFReadFailed(String errorMessage) {
+ public static class KasBadRequestException extends TamperException {
+ public KasBadRequestException(String errorMessage) {
super(errorMessage);
}
}
+ public static class AssertionException extends TamperException {
+ public AssertionException(String errorMessage, String id) {
+ super("assertion id: "+ id + "; " + errorMessage);
+ }
+ }
+
public static class EncryptedMetadata {
private String ciphertext;
private String iv;
@@ -558,7 +576,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas)
public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas,
Config.TDFReaderConfig tdfReaderConfig)
- throws NotValidateRootSignature, SegmentSizeMismatch,
+ throws RootSignatureValidationException, SegmentSizeMismatch,
IOException, FailedToCreateGMAC, JOSEException, ParseException, NoSuchAlgorithmException, DecoderException {
TDFReader tdfReader = new TDFReader(tdf);
@@ -666,7 +684,7 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas,
}
if (rootSignature.compareTo(rootSigValue) != 0) {
- throw new NotValidateRootSignature("root signature validation failed");
+ throw new RootSignatureValidationException("root signature validation failed");
}
int segmentSize = manifest.encryptionInformation.integrityInformation.segmentSizeDefault;
@@ -701,11 +719,11 @@ public Reader loadTDF(SeekableByteChannel tdf, SDK.KAS kas,
var encodeSignature = Base64.getEncoder().encodeToString(signature.getBytes());
if (!Objects.equals(hashOfAssertion, hashValues.getAssertionHash())) {
- throw new SDKException("assertion hash mismatch");
+ throw new AssertionException("assertion hash mismatch", assertion.id);
}
if (!Objects.equals(encodeSignature, hashValues.getSignature())) {
- throw new SDKException("failed integrity check on assertion signature");
+ throw new AssertionException("failed integrity check on assertion signature", assertion.id);
}
}
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 8afb5545..acd1fd15 100644
--- a/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java
+++ b/sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java
@@ -7,6 +7,7 @@
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;
@@ -30,7 +31,6 @@
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;
@@ -333,6 +333,62 @@ void testSimpleTDFWithAssertionWithHS256() throws Exception {
}
}
+ @Test
+ void testSimpleTDFWithAssertionWithHS256Failure() throws Exception {
+
+ ListenableFuture resp1 = mock(ListenableFuture.class);
+ lenient().when(resp1.get()).thenReturn(GetAttributeValuesByFqnsResponse.newBuilder().build());
+ lenient().when(attributeGrpcStub.getAttributeValuesByFqns(any(GetAttributeValuesByFqnsRequest.class)))
+ .thenReturn(resp1);
+
+ // var keypair = CryptoUtils.generateRSAKeypair();
+ SecureRandom secureRandom = new SecureRandom();
+ byte[] key = new byte[32];
+ secureRandom.nextBytes(key);
+
+ String assertion1Id = "assertion1";
+ var assertionConfig1 = new AssertionConfig();
+ assertionConfig1.id = assertion1Id;
+ assertionConfig1.type = AssertionConfig.Type.BaseAssertion;
+ assertionConfig1.scope = AssertionConfig.Scope.TrustedDataObj;
+ assertionConfig1.appliesToState = AssertionConfig.AppliesToState.Unencrypted;
+ assertionConfig1.statement = new AssertionConfig.Statement();
+ assertionConfig1.statement.format = "base64binary";
+ assertionConfig1.statement.schema = "text";
+ assertionConfig1.statement.value = "ICAgIDxlZGoOkVkaD4=";
+ assertionConfig1.assertionKey = new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.HS256, key);
+
+ Config.TDFConfig config = Config.newTDFConfig(
+ Config.withAutoconfigure(false),
+ Config.withKasInformation(getKASInfos()),
+ Config.withAssertionConfig(assertionConfig1));
+
+ String plainText = "this is extremely sensitive stuff!!!";
+ InputStream plainTextInputStream = new ByteArrayInputStream(plainText.getBytes());
+ ByteArrayOutputStream tdfOutputStream = new ByteArrayOutputStream();
+
+ TDF tdf = new TDF();
+ tdf.createTDF(plainTextInputStream, tdfOutputStream, config, kas, attributeGrpcStub);
+
+ byte[] notkey = new byte[32];
+ secureRandom.nextBytes(notkey);
+ var assertionVerificationKeys = new Config.AssertionVerificationKeys();
+ assertionVerificationKeys.defaultKey = new AssertionConfig.AssertionKey(AssertionConfig.AssertionKeyAlg.HS256,
+ notkey);
+ Config.TDFReaderConfig readerConfig = Config.newTDFReaderConfig(
+ Config.withAssertionVerificationKeys(assertionVerificationKeys));
+
+ var unwrappedData = new ByteArrayOutputStream();
+ Reader reader;
+ try {
+ reader = tdf.loadTDF(new SeekableInMemoryByteChannel(tdfOutputStream.toByteArray()), kas, readerConfig);
+ throw new RuntimeException("assertion verify key error thrown");
+
+ } catch (SDKException e) {
+ assertThat(e).hasMessageContaining("verify");
+ }
+ }
+
@Test
public void testCreatingTDFWithMultipleSegments() throws Exception {
From 6301d32c17b31c710073d898edcc2fb4ff1d3e36 Mon Sep 17 00:00:00 2001
From: Mike Jensen
Date: Tue, 5 Nov 2024 09:45:47 -0700
Subject: [PATCH 12/14] fix: NanoTDF secure key from debug logging and iv
conflict risk (#208)
This change is motivated from the CodeQL result:
https://github.com/opentdf/java-sdk/security/code-scanning/1
Although that use of a static IV is deliberate, it helped highlight that
we should ensure that there is no reuse of the IV when encrypting the
data.
In addition it was found that there were two places the key was logged,
due to the sensitivity of the key this has been removed.
---
sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java b/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
index 75d0e734..39170b97 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
@@ -88,7 +88,6 @@ public int createNanoTDF(ByteBuffer data, OutputStream outputStream,
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashOfSalt = digest.digest(MAGIC_NUMBER_AND_VERSION);
byte[] key = ECKeyPair.calculateHKDF(hashOfSalt, symmetricKey);
- logger.debug("createNanoTDF key is - {}", Base64.getEncoder().encodeToString(key));
// Encrypt policy
PolicyObject policyObject = createPolicyObject(nanoTDFConfig.attributes);
@@ -135,9 +134,11 @@ public int createNanoTDF(ByteBuffer data, OutputStream outputStream,
// Encrypt the data
byte[] actualIV = new byte[kIvPadding + kNanoTDFIvSize];
- byte[] iv = new byte[kNanoTDFIvSize];
- SecureRandom.getInstanceStrong().nextBytes(iv);
- System.arraycopy(iv, 0, actualIV, kIvPadding, iv.length);
+ do {
+ byte[] iv = new byte[kNanoTDFIvSize];
+ SecureRandom.getInstanceStrong().nextBytes(iv);
+ System.arraycopy(iv, 0, actualIV, kIvPadding, iv.length);
+ } while (Arrays.equals(actualIV, kEmptyIV)); // if match, we need to retry to prevent key + iv reuse with the policy
byte[] cipherData = gcm.encrypt(actualIV, authTagSize, data.array(), 0, dataSize);
@@ -173,7 +174,6 @@ public void readNanoTDF(ByteBuffer nanoTDF, OutputStream outputStream,
byte[] key = kas.unwrapNanoTDF(header.getECCMode().getEllipticCurveType(),
base64HeaderData,
kasUrl);
- logger.debug("readNanoTDF key is {}", Base64.getEncoder().encodeToString(key));
byte[] payloadLengthBuf = new byte[4];
nanoTDF.get(payloadLengthBuf, 1, 3);
From 332511402d9cdaf57e3e25f5030dbc0107994d9b Mon Sep 17 00:00:00 2001
From: sujankota
Date: Wed, 6 Nov 2024 11:49:57 -0500
Subject: [PATCH 13/14] feat(cmdline): assertions cli support (#204)
Co-authored-by: Dave Mihalcik
Co-authored-by: Elizabeth Healy <35498075+elizabethhealy@users.noreply.github.com>
---
.../java/io/opentdf/platform/Command.java | 21 ++++++++++++++++++-
1 file changed, 20 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 f8b37d0e..513c226b 100644
--- a/cmdline/src/main/java/io/opentdf/platform/Command.java
+++ b/cmdline/src/main/java/io/opentdf/platform/Command.java
@@ -1,9 +1,11 @@
package io.opentdf.platform;
+import com.google.gson.JsonSyntaxException;
import com.nimbusds.jose.JOSEException;
import io.opentdf.platform.sdk.*;
import io.opentdf.platform.sdk.TDF;
+import com.google.gson.Gson;
import org.apache.commons.codec.DecoderException;
import picocli.CommandLine;
import picocli.CommandLine.HelpCommand;
@@ -64,7 +66,9 @@ void encrypt(
@Option(names = { "-a", "--attr" }, defaultValue = Option.NULL_VALUE) Optional attributes,
@Option(names = { "-c",
"--autoconfigure" }, defaultValue = Option.NULL_VALUE) Optional autoconfigure,
- @Option(names = { "--mime-type" }, defaultValue = Option.NULL_VALUE) Optional mimeType)
+ @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 {
var sdk = buildSDK();
@@ -79,6 +83,21 @@ void encrypt(
metadata.map(Config::withMetaData).ifPresent(configs::add);
autoconfigure.map(Config::withAutoconfigure).ifPresent(configs::add);
mimeType.map(Config::withMimeType).ifPresent(configs::add);
+
+ if (assertion.isPresent()) {
+ var assertionConfig = assertion.get();
+ Gson gson = new Gson();
+
+ AssertionConfig[] assertionConfigs;
+ try {
+ assertionConfigs = gson.fromJson(assertionConfig, AssertionConfig[].class);
+ } catch (JsonSyntaxException e) {
+ throw new RuntimeException("Failed to parse assertion, expects an list of assertions", e);
+ }
+
+ configs.add(Config.withAssertionConfig(assertionConfigs));
+ }
+
if (attributes.isPresent()) {
configs.add(Config.withDataAttributes(attributes.get().split(",")));
}
From 0d6e7616f0d57d461a0f9002f395f8e2c7365cd3 Mon Sep 17 00:00:00 2001
From: dominic reed
Date: Thu, 7 Nov 2024 10:47:51 -0800
Subject: [PATCH 14/14] fix(sdk): uses offset for ByteBuffer array offset
(#209)
ByteBuffer could have an array offset. We consider the length of the
ByteBuffer, but we do not consider the offset and default it to 0. This
PR fixes this problem by adding in the array offset when encrypting.
---
sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java b/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
index 39170b97..5695713a 100644
--- a/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
+++ b/sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
@@ -140,7 +140,7 @@ public int createNanoTDF(ByteBuffer data, OutputStream outputStream,
System.arraycopy(iv, 0, actualIV, kIvPadding, iv.length);
} while (Arrays.equals(actualIV, kEmptyIV)); // if match, we need to retry to prevent key + iv reuse with the policy
- byte[] cipherData = gcm.encrypt(actualIV, authTagSize, data.array(), 0, dataSize);
+ byte[] cipherData = gcm.encrypt(actualIV, authTagSize, data.array(), data.arrayOffset(), dataSize);
// Write the length of the payload as int24
int cipherDataLengthWithoutPadding = cipherData.length - kIvPadding;