Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 49 additions & 65 deletions cmdline/src/main/java/io/opentdf/platform/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import io.opentdf.platform.sdk.Config;
import io.opentdf.platform.sdk.KeyType;
import io.opentdf.platform.sdk.Config.AssertionVerificationKeys;
import io.opentdf.platform.sdk.NanoTDF;
import io.opentdf.platform.sdk.SDK;
import io.opentdf.platform.sdk.SDKBuilder;
import io.opentdf.platform.sdk.TDF;
Expand Down Expand Up @@ -192,8 +191,8 @@ void encrypt(
} catch (JsonSyntaxException e) {
// try it as a file path
try {
String fielJson = new String(Files.readAllBytes(Paths.get(assertionConfig)));
assertionConfigs = gson.fromJson(fielJson, AssertionConfig[].class);
String fileJson = new String(Files.readAllBytes(Paths.get(assertionConfig)));
assertionConfigs = gson.fromJson(fileJson, AssertionConfig[].class);
} catch (JsonSyntaxException e2) {
throw new RuntimeException("Failed to parse assertion from file, expects an list of assertions", e2);
} catch(Exception e3) {
Expand Down Expand Up @@ -221,9 +220,7 @@ void encrypt(
var tdfConfig = Config.newTDFConfig(configs.toArray(Consumer[]::new));
try (var in = file.isEmpty() ? new BufferedInputStream(System.in) : new FileInputStream(file.get())) {
try (var out = new BufferedOutputStream(System.out)) {
new TDF().createTDF(in, out, tdfConfig,
sdk.getServices().kas(),
sdk.getServices().attributes());
sdk.createTDF(in, out, tdfConfig);
}
}
}
Expand All @@ -249,56 +246,53 @@ void decrypt(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,
@Option(names = { "--with-assertion-verification-keys" }, defaultValue = Option.NULL_VALUE) Optional<String> assertionVerification,
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
@Option(names = { "--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist)
throws IOException, TDF.FailedToCreateGMAC, JOSEException, ParseException, NoSuchAlgorithmException, DecoderException, InterruptedException, ExecutionException, URISyntaxException {
var sdk = buildSDK();
var opts = new ArrayList<Consumer<Config.TDFReaderConfig>>();
try (var in = FileChannel.open(tdfPath, StandardOpenOption.READ)) {
try (var stdout = new BufferedOutputStream(System.out)) {
if (assertionVerification.isPresent()) {
var assertionVerificationInput = assertionVerification.get();
Gson gson = new Gson();

AssertionVerificationKeys assertionVerificationKeys;
try {
assertionVerificationKeys = gson.fromJson(assertionVerificationInput, AssertionVerificationKeys.class);
} catch (JsonSyntaxException e) {
// try it as a file path
throws Exception {
try (var sdk = buildSDK()) {
var opts = new ArrayList<Consumer<Config.TDFReaderConfig>>();
try (var in = FileChannel.open(tdfPath, StandardOpenOption.READ)) {
try (var stdout = new BufferedOutputStream(System.out)) {
if (assertionVerification.isPresent()) {
var assertionVerificationInput = assertionVerification.get();
Gson gson = new Gson();

AssertionVerificationKeys assertionVerificationKeys;
try {
String fileJson = new String(Files.readAllBytes(Paths.get(assertionVerificationInput)));
assertionVerificationKeys = gson.fromJson(fileJson, AssertionVerificationKeys.class);
} catch (JsonSyntaxException e2) {
throw new RuntimeException("Failed to parse assertion verification keys from file", e2);
} catch(Exception e3) {
throw new RuntimeException("Could not parse assertion verification keys as json string or path to file", e3);
assertionVerificationKeys = gson.fromJson(assertionVerificationInput, AssertionVerificationKeys.class);
} catch (JsonSyntaxException e) {
// try it as a file path
try {
String fileJson = new String(Files.readAllBytes(Paths.get(assertionVerificationInput)));
assertionVerificationKeys = gson.fromJson(fileJson, AssertionVerificationKeys.class);
} catch (JsonSyntaxException e2) {
throw new RuntimeException("Failed to parse assertion verification keys from file", e2);
} catch (Exception e3) {
throw new RuntimeException("Could not parse assertion verification keys as json string or path to file", e3);
}
}
}

for (Map.Entry<String, AssertionConfig.AssertionKey> entry : assertionVerificationKeys.keys.entrySet()){
try {
Object correctedKey = correctKeyType(entry.getValue().alg, entry.getValue().key, true);
entry.setValue(new AssertionConfig.AssertionKey(entry.getValue().alg, correctedKey));
} catch (Exception e) {
throw new RuntimeException("Error with assertion verification key: " + e.getMessage(), e);
for (Map.Entry<String, AssertionConfig.AssertionKey> entry : assertionVerificationKeys.keys.entrySet()) {
try {
Object correctedKey = correctKeyType(entry.getValue().alg, entry.getValue().key, true);
entry.setValue(new AssertionConfig.AssertionKey(entry.getValue().alg, correctedKey));
} catch (Exception e) {
throw new RuntimeException("Error with assertion verification key: " + e.getMessage(), e);
}
}
opts.add(Config.withAssertionVerificationKeys(assertionVerificationKeys));
}
opts.add(Config.withAssertionVerificationKeys(assertionVerificationKeys));
}

if (disableAssertionVerification) {
opts.add(Config.withDisableAssertionVerification(true));
}
rewrapKeyType.map(Config::WithSessionKeyType).ifPresent(opts::add);
if (disableAssertionVerification) {
opts.add(Config.withDisableAssertionVerification(true));
}
rewrapKeyType.map(Config::WithSessionKeyType).ifPresent(opts::add);

if (ignoreAllowlist.isPresent()) {
opts.add(Config.WithIgnoreKasAllowlist(ignoreAllowlist.get()));
}
if (kasAllowlistStr.isPresent()) {
opts.add(Config.WithKasAllowlist(kasAllowlistStr.get().split(",")));
}
ignoreAllowlist.ifPresent(aBoolean -> opts.add(Config.WithIgnoreKasAllowlist(aBoolean)));
kasAllowlistStr.ifPresent(s -> opts.add(Config.WithKasAllowlist(s.split(","))));

var readerConfig = Config.newTDFReaderConfig(opts.toArray(new Consumer[0]));
var reader = new TDF().loadTDF(in, sdk.getServices().kas(), readerConfig, sdk.getServices().kasRegistry(), sdk.getPlatformUrl());
reader.readPayload(stdout);
var readerConfig = Config.newTDFReaderConfig(opts.toArray(new Consumer[0]));
var reader = sdk.loadTDF(in, readerConfig);
reader.readPayload(stdout);
}
}
}
}
Expand All @@ -313,15 +307,11 @@ void readMetadata(@Option(names = { "-f", "--file" }, required = true) Path tdfP
try (var in = FileChannel.open(tdfPath, StandardOpenOption.READ)) {
try (var stdout = new PrintWriter(System.out)) {

if (ignoreAllowlist.isPresent()) {
opts.add(Config.WithIgnoreKasAllowlist(ignoreAllowlist.get()));
}
if (kasAllowlistStr.isPresent()) {
opts.add(Config.WithKasAllowlist(kasAllowlistStr.get().split(",")));
}
ignoreAllowlist.map(Config::WithIgnoreKasAllowlist).ifPresent(opts::add);
kasAllowlistStr.map(s -> s.split(",")).map(Config::WithKasAllowlist).ifPresent(opts::add);

var readerConfig = Config.newTDFReaderConfig(opts.toArray(new Consumer[0]));
var reader = new TDF().loadTDF(in, sdk.getServices().kas(), readerConfig, sdk.getServices().kasRegistry(), sdk.getPlatformUrl());
var reader = sdk.loadTDF(in, readerConfig);
stdout.write(reader.getMetadata() == null ? "" : reader.getMetadata());
}
}
Expand Down Expand Up @@ -351,8 +341,7 @@ void createNanoTDF(
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());
sdk.createNanoTDF(ByteBuffer.wrap(in.readAllBytes()), out, nanoTDFConfig);
}
}
}
Expand All @@ -364,19 +353,14 @@ void readNanoTDF(@Option(names = { "-f", "--file" }, required = true) Path nanoT
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();
var opts = new ArrayList<Consumer<Config.NanoTDFReaderConfig>>();
if (ignoreAllowlist.isPresent()) {
opts.add(Config.WithNanoIgnoreKasAllowlist(ignoreAllowlist.get()));
}
if (kasAllowlistStr.isPresent()) {
opts.add(Config.WithNanoKasAllowlist(kasAllowlistStr.get().split(",")));
}
ignoreAllowlist.map(Config::WithNanoIgnoreKasAllowlist).ifPresent(opts::add);
kasAllowlistStr.map(s -> s.split(",")).map(Config::WithNanoKasAllowlist).ifPresent(opts::add);
var readerConfig = Config.newNanoTDFReaderConfig(opts.toArray(new Consumer[0]));
ntdf.readNanoTDF(buffer, stdout, sdk.getServices().kas(), readerConfig, sdk.getServices().kasRegistry(), sdk.getPlatformUrl());
sdk.readNanoTDF(buffer, stdout, readerConfig);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ public static void main(String[] args) throws IOException, NanoTDF.NanoTDFMaxSiz


// Convert String to InputStream
NanoTDF nanoTDFClient = new NanoTDF(true);

for (int i = 0; i < 50; i++) {
FileInputStream fis = new FileInputStream(String.format("out/my.%d_ciphertext", i));
nanoTDFClient.readNanoTDF(ByteBuffer.wrap(fis.readAllBytes()), System.out, sdk.getServices().kas(), sdk.getServices().kasRegistry(), sdk.getPlatformUrl());
sdk.readNanoTDF(ByteBuffer.wrap(fis.readAllBytes()), System.out, Config.newNanoTDFReaderConfig());
fis.close();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static void main(String[] args) throws IOException,

Path path = Paths.get("my.ciphertext");
try (var in = FileChannel.open(path, StandardOpenOption.READ)) {
var reader = new TDF().loadTDF(in, sdk.getServices().kas(), Config.newTDFReaderConfig(Config.WithSessionKeyType(sessionKeyType)), sdk.getServices().kasRegistry(), sdk.getPlatformUrl());
var reader = sdk.loadTDF(in, Config.newTDFReaderConfig(Config.WithSessionKeyType(sessionKeyType)));
reader.readPayload(System.out);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,9 @@ public static void main(String[] args) throws IOException, NanoTDF.NanoTDFMaxSiz

String str = "Hello, World!";

// Convert String to InputStream
var in = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
NanoTDF nanoTDFClient = new NanoTDF();

for (int i = 0; i < 50; i++) {
FileOutputStream fos = new FileOutputStream(String.format("out/my.%d_ciphertext", i));
nanoTDFClient.createNanoTDF(ByteBuffer.wrap(str.getBytes()), fos, tdfConfig,
sdk.getServices().kas());
sdk.createNanoTDF(ByteBuffer.wrap(str.getBytes(StandardCharsets.UTF_8)), fos, tdfConfig);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ public static void main(String[] args) throws IOException, JOSEException, AutoCo

FileOutputStream fos = new FileOutputStream("my.ciphertext");

new TDF().createTDF(in, fos, tdfConfig,
sdk.getServices().kas(),
sdk.getServices().attributes());
sdk.createTDF(in, fos, tdfConfig);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,11 @@
/**
* Exception thrown when automatic configuration fails.
*/
public class AutoConfigureException extends RuntimeException {
public class AutoConfigureException extends SDKException {
public AutoConfigureException(String message) {
super(message);
}

public AutoConfigureException(Exception e) {
super(e);
}

public AutoConfigureException(String message, Exception e) {
super(message, e);
public AutoConfigureException(String message, Exception cause) {
super(message, cause);
}
}
12 changes: 10 additions & 2 deletions sdk/src/main/java/io/opentdf/platform/sdk/Autoconfigure.java
Original file line number Diff line number Diff line change
Expand Up @@ -699,14 +699,22 @@ public static Granter newGranterFromAttributes(Value... attrValues) throws AutoC
}

// Gets a list of directory of KAS grants for a list of attribute FQNs
public static Granter newGranterFromService(AttributesServiceFutureStub as, KASKeyCache keyCache, AttributeValueFQN... fqns) throws AutoConfigureException, ExecutionException, InterruptedException {
static Granter newGranterFromService(AttributesServiceFutureStub as, KASKeyCache keyCache, AttributeValueFQN... fqns) throws AutoConfigureException {

GetAttributeValuesByFqnsRequest request = GetAttributeValuesByFqnsRequest.newBuilder()
.addAllFqns(Arrays.stream(fqns).map(AttributeValueFQN::toString).collect(Collectors.toList()))
.setWithValue(AttributeValueSelector.newBuilder().setWithKeyAccessGrants(true).build())
.build();

GetAttributeValuesByFqnsResponse av = as.getAttributeValuesByFqns(request).get();
GetAttributeValuesByFqnsResponse av = null;
try {
av = as.getAttributeValuesByFqns(request).get();
} catch (ExecutionException e) {
throw new AutoConfigureException("error getting attributes during autoconfiguration", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new AutoConfigureException("interrupted while getting attributes during autoconfiguration", e);
}

return getGranter(keyCache, new ArrayList<>(av.getFqnAttributeValuesMap().values()));
}
Expand Down
46 changes: 24 additions & 22 deletions sdk/src/main/java/io/opentdf/platform/sdk/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,9 @@ public static Consumer<TDFReaderConfig> WithSessionKeyType(KeyType keyType) {
return (TDFReaderConfig config) -> config.sessionKeyType = keyType;
}
public static Consumer<TDFReaderConfig> WithKasAllowlist(String... kasAllowlist) {
return (TDFReaderConfig config) -> {
config.kasAllowlist = Arrays.stream(kasAllowlist)
.map(s -> {
try {
return getKasAddress(s);
} catch (URISyntaxException e) {
throw new RuntimeException("Invalid URI: " + s, e);
}
}).collect(Collectors.toCollection(HashSet::new));
};
return (TDFReaderConfig config) -> config.kasAllowlist = Arrays
.stream(kasAllowlist)
.map(Config::getKasAddress).collect(Collectors.toSet());
}

public static Consumer<TDFReaderConfig> withKasAllowlist(Set<String> kasAllowlist) {
Expand Down Expand Up @@ -401,13 +394,8 @@ public static Consumer<NanoTDFReaderConfig> WithNanoKasAllowlist(String... kasAl
return (NanoTDFReaderConfig config) -> {
// apply getKasAddress to each kasAllowlist entry and add to hashset
config.kasAllowlist = Arrays.stream(kasAllowlist)
.map(s -> {
try {
return getKasAddress(s);
} catch (URISyntaxException e) {
throw new RuntimeException("Invalid URI: " + s, e);
}
}).collect(Collectors.toCollection(HashSet::new));
.map(Config::getKasAddress)
.collect(Collectors.toSet());
};
}

Expand Down Expand Up @@ -456,7 +444,7 @@ public CollectionConfig(boolean useCollection) {
this.useCollection = useCollection;
}

public synchronized HeaderInfo getHeaderInfo() throws InterruptedException {
public synchronized HeaderInfo getHeaderInfo() throws SDKException {
int iteration = iterationCounter;
iterationCounter = (iterationCounter + 1) % MAX_COLLECTION_ITERATION;

Expand All @@ -465,7 +453,12 @@ public synchronized HeaderInfo getHeaderInfo() throws InterruptedException {
return null;
}
while (!updatedHeaderInfo) {
this.wait();
try {
this.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new SDKException("interrupted while waiting for header info", e);
}
}
return new HeaderInfo(headerInfo.getHeader(), headerInfo.getKey(), iteration);
}
Expand All @@ -477,13 +470,18 @@ public synchronized void updateHeaderInfo(HeaderInfo headerInfo) {
}
}

public static String getKasAddress(String kasURL) throws URISyntaxException {
public static String getKasAddress(String kasURL) throws SDKException {
// Prepend "https://" if no scheme is provided
if (!kasURL.contains("://")) {
kasURL = "https://" + kasURL;
}

URI uri = new URI(kasURL);
URI uri;
try {
uri = new URI(kasURL);
} catch (URISyntaxException e) {
throw new SDKException("error constructing KAS url", e);
}

// Default to "https" if no scheme is provided
String scheme = uri.getScheme();
Expand All @@ -498,6 +496,10 @@ public static String getKasAddress(String kasURL) throws URISyntaxException {
}

// Reconstruct the URL with only the scheme, host, and port
return new URI(scheme, null, uri.getHost(), port, null, null, null).toString();
try {
return new URI(scheme, null, uri.getHost(), port, null, null, null).toString();
} catch (URISyntaxException e) {
throw new SDKException("error creating KAS URL from host and port", e);
}
}
}
Loading