Skip to content

Commit d235f13

Browse files
strantalismkleene
andauthored
feat: add system metadata assertion (#270)
Co-authored-by: Morgan Kleene <[email protected]>
1 parent c3b79db commit d235f13

File tree

9 files changed

+1019
-742
lines changed

9 files changed

+1019
-742
lines changed

.github/release-please/release-please-config.main.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
{
1313
"type": "generic",
1414
"path": "cmdline/src/main/java/io/opentdf/platform/Command.java"
15+
},
16+
{
17+
"type": "generic",
18+
"path": "sdk/src/main/java/io/opentdf/platform/sdk/Version.java"
1519
}
1620
]
1721
}

.github/release-please/release-please-config.release_branches.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
{
1313
"type": "generic",
1414
"path": "cmdline/src/main/java/io/opentdf/platform/Command.java"
15+
},
16+
{
17+
"type": "generic",
18+
"path": "sdk/src/main/java/io/opentdf/platform/sdk/Version.java"
1519
}
1620
]
1721
}

cmdline/src/main/java/io/opentdf/platform/Command.java

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,11 @@ class Versions {
5454
public static final String TDF_SPEC = "4.3.0";
5555
}
5656

57-
@CommandLine.Command(
58-
name = "tdf",
59-
subcommands = {HelpCommand.class},
60-
version =
61-
"{\"version\":\"" + Versions.SDK + "\",\"tdfSpecVersion\":\"" + Versions.TDF_SPEC + "\"}"
62-
)
57+
@CommandLine.Command(name = "tdf", subcommands = { HelpCommand.class }, version = "{\"version\":\"" + Versions.SDK
58+
+ "\",\"tdfSpecVersion\":\"" + Versions.TDF_SPEC + "\"}")
6359
class Command {
6460

65-
@Option(names = {"-V", "--version"}, versionHelp = true, description = "display version info")
61+
@Option(names = { "-V", "--version" }, versionHelp = true, description = "display version info")
6662
boolean versionInfoRequested;
6763

6864
private static final String PRIVATE_KEY_HEADER = "-----BEGIN PRIVATE KEY-----";
@@ -85,7 +81,8 @@ class Command {
8581
@Option(names = { "-p", "--platform-endpoint" }, required = true)
8682
private String platformEndpoint;
8783

88-
private Object correctKeyType(AssertionConfig.AssertionKeyAlg alg, Object key, boolean publicKey) throws RuntimeException{
84+
private Object correctKeyType(AssertionConfig.AssertionKeyAlg alg, Object key, boolean publicKey)
85+
throws RuntimeException {
8986
if (alg == AssertionConfig.AssertionKeyAlg.HS256) {
9087
if (key instanceof String) {
9188
key = ((String) key).getBytes(StandardCharsets.UTF_8);
@@ -101,14 +98,14 @@ private Object correctKeyType(AssertionConfig.AssertionKeyAlg alg, Object key, b
10198
}
10299
String pem = (String) key;
103100
String pemWithNewlines = pem.replace("\\n", "\n");
104-
if (publicKey){
105-
String base64EncodedPem= pemWithNewlines
106-
.replaceAll(PEM_HEADER, "")
107-
.replaceAll(PEM_FOOTER, "")
108-
.replaceAll("\\s", "")
109-
.replaceAll("\r\n", "")
110-
.replaceAll("\n", "")
111-
.trim();
101+
if (publicKey) {
102+
String base64EncodedPem = pemWithNewlines
103+
.replaceAll(PEM_HEADER, "")
104+
.replaceAll(PEM_FOOTER, "")
105+
.replaceAll("\\s", "")
106+
.replaceAll("\r\n", "")
107+
.replaceAll("\n", "")
108+
.trim();
112109
byte[] decoded = Base64.getDecoder().decode(base64EncodedPem);
113110
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
114111
KeyFactory kf = null;
@@ -122,7 +119,7 @@ private Object correctKeyType(AssertionConfig.AssertionKeyAlg alg, Object key, b
122119
} catch (InvalidKeySpecException e) {
123120
throw new RuntimeException(e);
124121
}
125-
}else {
122+
} else {
126123
String privateKeyPEM = pemWithNewlines
127124
.replace(PRIVATE_KEY_HEADER, "")
128125
.replace(PRIVATE_KEY_FOOTER, "")
@@ -174,6 +171,7 @@ void encrypt(
174171
List<Consumer<Config.TDFConfig>> configs = new ArrayList<>();
175172
configs.add(Config.withKasInformation(kasInfos));
176173
metadata.map(Config::withMetaData).ifPresent(configs::add);
174+
configs.add(Config.withSystemMetadataAssertion());
177175
autoconfigure.map(Config::withAutoconfigure).ifPresent(configs::add);
178176
encapKeyType.map(Config::WithWrappingKeyAlg).ifPresent(configs::add);
179177
mimeType.map(Config::withMimeType).ifPresent(configs::add);
@@ -191,8 +189,9 @@ void encrypt(
191189
String fileJson = new String(Files.readAllBytes(Paths.get(assertionConfig)));
192190
assertionConfigs = gson.fromJson(fileJson, AssertionConfig[].class);
193191
} catch (JsonSyntaxException e2) {
194-
throw new RuntimeException("Failed to parse assertion from file, expects an list of assertions", e2);
195-
} catch(Exception e3) {
192+
throw new RuntimeException("Failed to parse assertion from file, expects an list of assertions",
193+
e2);
194+
} catch (Exception e3) {
196195
throw new RuntimeException("Could not parse assertion as json string or path to file", e3);
197196
}
198197
}
@@ -238,11 +237,15 @@ private SDK buildSDK() {
238237

239238
@CommandLine.Command(name = "decrypt")
240239
void decrypt(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,
241-
@Option(names = { "--rewrap-key-type" }, defaultValue = Option.NULL_VALUE, description = "Preferred rewrap algorithm, one of ${COMPLETION-CANDIDATES}") Optional<KeyType> rewrapKeyType,
242-
@Option(names = { "--with-assertion-verification-disabled" }, defaultValue = "false") boolean disableAssertionVerification,
243-
@Option(names = { "--with-assertion-verification-keys" }, defaultValue = Option.NULL_VALUE) Optional<String> assertionVerification,
240+
@Option(names = {
241+
"--rewrap-key-type" }, defaultValue = Option.NULL_VALUE, description = "Preferred rewrap algorithm, one of ${COMPLETION-CANDIDATES}") Optional<KeyType> rewrapKeyType,
242+
@Option(names = {
243+
"--with-assertion-verification-disabled" }, defaultValue = "false") boolean disableAssertionVerification,
244+
@Option(names = {
245+
"--with-assertion-verification-keys" }, defaultValue = Option.NULL_VALUE) Optional<String> assertionVerification,
244246
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
245-
@Option(names = { "--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist)
247+
@Option(names = {
248+
"--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist)
246249
throws Exception {
247250
try (var sdk = buildSDK()) {
248251
var opts = new ArrayList<Consumer<Config.TDFReaderConfig>>();
@@ -254,7 +257,8 @@ void decrypt(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,
254257

255258
AssertionVerificationKeys assertionVerificationKeys;
256259
try {
257-
assertionVerificationKeys = gson.fromJson(assertionVerificationInput, AssertionVerificationKeys.class);
260+
assertionVerificationKeys = gson.fromJson(assertionVerificationInput,
261+
AssertionVerificationKeys.class);
258262
} catch (JsonSyntaxException e) {
259263
// try it as a file path
260264
try {
@@ -263,16 +267,20 @@ void decrypt(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,
263267
} catch (JsonSyntaxException e2) {
264268
throw new RuntimeException("Failed to parse assertion verification keys from file", e2);
265269
} catch (Exception e3) {
266-
throw new RuntimeException("Could not parse assertion verification keys as json string or path to file", e3);
270+
throw new RuntimeException(
271+
"Could not parse assertion verification keys as json string or path to file",
272+
e3);
267273
}
268274
}
269275

270-
for (Map.Entry<String, AssertionConfig.AssertionKey> entry : assertionVerificationKeys.keys.entrySet()) {
276+
for (Map.Entry<String, AssertionConfig.AssertionKey> entry : assertionVerificationKeys.keys
277+
.entrySet()) {
271278
try {
272279
Object correctedKey = correctKeyType(entry.getValue().alg, entry.getValue().key, true);
273280
entry.setValue(new AssertionConfig.AssertionKey(entry.getValue().alg, correctedKey));
274281
} catch (Exception e) {
275-
throw new RuntimeException("Error with assertion verification key: " + e.getMessage(), e);
282+
throw new RuntimeException("Error with assertion verification key: " + e.getMessage(),
283+
e);
276284
}
277285
}
278286
opts.add(Config.withAssertionVerificationKeys(assertionVerificationKeys));
@@ -296,8 +304,10 @@ void decrypt(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,
296304

297305
@CommandLine.Command(name = "metadata")
298306
void readMetadata(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,
299-
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
300-
@Option(names = { "--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist) throws IOException {
307+
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
308+
@Option(names = {
309+
"--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist)
310+
throws IOException {
301311
var sdk = buildSDK();
302312
var opts = new ArrayList<Consumer<Config.TDFReaderConfig>>();
303313
try (var in = FileChannel.open(tdfPath, StandardOpenOption.READ)) {
@@ -344,8 +354,10 @@ void createNanoTDF(
344354

345355
@CommandLine.Command(name = "decryptnano")
346356
void readNanoTDF(@Option(names = { "-f", "--file" }, required = true) Path nanoTDFPath,
347-
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
348-
@Option(names = { "--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist) throws Exception {
357+
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
358+
@Option(names = {
359+
"--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist)
360+
throws Exception {
349361
var sdk = buildSDK();
350362
try (var in = FileChannel.open(nanoTDFPath, StandardOpenOption.READ)) {
351363
try (var stdout = new BufferedOutputStream(System.out)) {

0 commit comments

Comments
 (0)