diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index bad81bea..0c9e5b12 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -169,6 +169,30 @@ jobs: exit 1 fi working-directory: cmdline + + - name: Encrypt/Decrypt NanoTDF + run: | + echo 'here is some data to encrypt' > data + + java -jar target/cmdline.jar \ + --client-id=opentdf-sdk \ + --client-secret=secret \ + --platform-endpoint=localhost:8080 \ + -i \ + encryptnano --kas-url=http://localhost:8080 -f data -m 'here is some metadata' > nano.ntdf + + java -jar target/cmdline.jar \ + --client-id=opentdf-sdk \ + --client-secret=secret \ + --platform-endpoint=localhost:8080 \ + -i \ + decryptnano -f nano.ntdf > decrypted + + if ! diff -q data decrypted; then + printf 'decrypted data is incorrect [%s]' "$(< decrypted)" + exit 1 + fi + working-directory: cmdline ci: needs: - platform-integration diff --git a/cmdline/src/main/java/io/opentdf/platform/Command.java b/cmdline/src/main/java/io/opentdf/platform/Command.java index b07988f7..743d24a8 100644 --- a/cmdline/src/main/java/io/opentdf/platform/Command.java +++ b/cmdline/src/main/java/io/opentdf/platform/Command.java @@ -1,8 +1,6 @@ package io.opentdf.platform; -import io.opentdf.platform.sdk.Config; -import io.opentdf.platform.sdk.SDK; -import io.opentdf.platform.sdk.SDKBuilder; +import io.opentdf.platform.sdk.*; import io.opentdf.platform.sdk.TDF; import picocli.CommandLine; import picocli.CommandLine.Option; @@ -18,6 +16,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Path; import java.nio.file.StandardOpenOption; @@ -98,4 +97,43 @@ void readMetadata(@Option(names = {"-f", "--file"}, required = true) Path tdfPat } } } + + @CommandLine.Command(name = "encryptnano") + void createNanoTDF( + @Option(names = {"-f", "--file"}, defaultValue = Option.NULL_VALUE) Optional file, + @Option(names = {"-k", "--kas-url"}, required = true) List kas, + @Option(names = {"-m", "--metadata"}, defaultValue = Option.NULL_VALUE) Optional metadata) throws Exception { + + var sdk = buildSDK(); + var kasInfos = kas.stream().map(k -> { + var ki = new Config.KASInfo(); + ki.URL = k; + return ki; + }).toArray(Config.KASInfo[]::new); + + List> configs = new ArrayList<>(); + configs.add(Config.withNanoKasInformation(kasInfos)); + + var nanoTDFConfig = Config.newNanoTDFConfig(configs.toArray(Consumer[]::new)); + try (var in = file.isEmpty() ? new BufferedInputStream(System.in) : new FileInputStream(file.get())) { + try (var out = new BufferedOutputStream(System.out)) { + NanoTDF ntdf = new NanoTDF(); + ntdf.createNanoTDF(ByteBuffer.wrap(in.readAllBytes()), out, nanoTDFConfig, sdk.getServices().kas()); + } + } + } + + @CommandLine.Command(name = "decryptnano") + void readNanoTDF(@Option(names = {"-f", "--file"}, required = true) Path nanoTDFPath) throws Exception { + var sdk = buildSDK(); + try (var in = FileChannel.open(nanoTDFPath, StandardOpenOption.READ)) { + try (var stdout = new BufferedOutputStream(System.out)) { + NanoTDF ntdf = new NanoTDF(); + ByteBuffer buffer = ByteBuffer.allocate((int) in.size()); + in.read(buffer); + buffer.flip(); + ntdf.readNanoTDF(buffer, stdout, sdk.getServices().kas()); + } + } + } }