Skip to content

Commit 79606a2

Browse files
authored
feat: add OSCAL signing and verification flow (#2253)
* feat: add OSCAL signing and verification flow Signed-off-by: Matteo Fari <matteofari06@gmail.com> * fix: address signing and verification review feedback Signed-off-by: Matteo Fari <matteofari06@gmail.com> * fix: gate signing commands behind beta feature Signed-off-by: Matteo Fari <matteofari06@gmail.com> --------- Signed-off-by: Matteo Fari <matteofari06@gmail.com>
1 parent 9199eb6 commit 79606a2

12 files changed

Lines changed: 1399 additions & 2 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Trestle provides tooling to help orchestrate the compliance process across a num
3030
- Tooling manage authoring and governance of markdown and drawio files within a repository.
3131
- Support within trestle to streamline management within a managed git environment.
3232
- An underlying object model that supports developers interacting with OSCAL artifacts.
33+
- Detached signing and verification for JSON artifacts.
3334

3435
## Why Trestle
3536

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Trestle provides tooling to help orchestrate the compliance process across a num
3434
- Tooling manage authoring and governance of markdown and drawio files withn a repository.
3535
- Support within trestle to streamline management within a managed git environment.
3636
- An underlying object model that supports developers interacting with OSCAL artefacts.
37+
- Detached signing and verification for JSON artifacts. See the [`trestle sign` and `trestle verify` CLI documentation](tutorials/cli.md#trestle-sign).
3738

3839
## Important Note:
3940

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
title: OSCAL Signing Predicate v1
3+
description: Predicate type used by compliance-trestle detached JSON signatures
4+
---
5+
6+
# OSCAL Signing Predicate v1
7+
8+
Trestle uses this predicate type in the in-toto Statement created by `trestle sign`:
9+
10+
```text
11+
https://oscal-compass.github.io/compliance-trestle/predicates/oscal-signing/v1
12+
```
13+
14+
The predicate describes how trestle created the digest for a signed JSON artifact.
15+
The predicate type URI is recorded in the signed Statement and is not fetched
16+
during verification.
17+
18+
For command usage, see the [`trestle sign` and `trestle verify` CLI documentation](../../tutorials/cli.md#trestle-sign).
19+
20+
## What is signed
21+
22+
`trestle sign` creates a detached DSSE envelope. The envelope payload is an in-toto Statement that records:
23+
24+
- the subject file name
25+
- the SHA-256 digest of the RFC 8785 canonical JSON bytes
26+
- the predicate type and predicate fields described below
27+
28+
The DSSE signature is made over the DSSE pre-authentication encoding of the
29+
Statement payload. The original JSON file is not modified.
30+
31+
## Statement
32+
33+
The DSSE payload is a base64-encoded in-toto Statement with exactly one subject:
34+
35+
```json
36+
{
37+
"_type": "https://in-toto.io/Statement/v1",
38+
"subject": [
39+
{
40+
"name": "catalog.json",
41+
"digest": {
42+
"sha256": "..."
43+
}
44+
}
45+
],
46+
"predicateType": "https://oscal-compass.github.io/compliance-trestle/predicates/oscal-signing/v1",
47+
"predicate": {
48+
"canonicalization": "RFC8785",
49+
"digestAlgorithm": "sha256",
50+
"digestSource": "canonical-json",
51+
"tool": "compliance-trestle"
52+
}
53+
}
54+
```
55+
56+
## Predicate fields
57+
58+
| Field | Description |
59+
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
60+
| `canonicalization` | The canonicalization algorithm applied before hashing. Trestle uses `RFC8785`. |
61+
| `digestAlgorithm` | The digest algorithm used over the canonical JSON bytes. Trestle uses `sha256`. |
62+
| `digestSource` | The bytes that were hashed. `canonical-json` means the digest was computed over the RFC 8785 canonical JSON bytes, not the original file bytes. |
63+
| `tool` | The producer of the predicate. Trestle writes `compliance-trestle`. |

docs/tutorials/cli.md

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ description: An introductory tutorial into trestle's CLI and OSCAL use cases
55

66
# trestle CLI Overview and OSCAL usecases
77

8-
The trestle CLI has five primary use cases:
8+
The trestle CLI has six primary use cases:
99

1010
- Serve as tooling to generate and manipulate OSCAL files directly by an end user. The objective is to reduce the complexity of creating and editing workflows. Example commands are: `trestle import`, `trestle create`, `trestle split`, `trestle merge`.
1111
- Act as an automation tool that, by design, can be an integral part of a CI/CD pipeline e.g. `trestle validate`, `trestle tasks`.
1212
- Allow governance of markdown documents so they conform to specific style or structure requirements.
1313
- Canonicalize JSON documents with `trestle canonicalize`. See [Canonicalizing JSON documents](canonicalization.md).
1414
- Manage experimental commands with `trestle beta`.
15+
- Sign and verify JSON artifacts with detached DSSE envelopes.
1516

1617
To support each of these use cases trestle creates an opinionated directory structure to manage governed documents.
1718

@@ -593,6 +594,68 @@ By default validate will display warning messages and a message indicating the f
593594
The links validator is special because it always returns success that the file is valid - but it will list any inconsistencies it finds between the
594595
references to links, and corresponding links in the backmatter.
595596

597+
## `trestle sign`
598+
599+
Trestle sign writes a detached DSSE envelope for a JSON file. It canonicalizes the JSON using RFC 8785, computes a SHA-256 digest, records that digest in an in-toto Statement, and signs the Statement with a PEM private key.
600+
601+
The sign and verify commands are beta features. Enable them before use:
602+
603+
```bash
604+
trestle beta enable json-signing
605+
```
606+
607+
You can also pass `--beta` to `trestle sign` or `trestle verify` to run the beta command one time without writing beta state to config.
608+
609+
Generate an Ed25519 private/public key pair with OpenSSL:
610+
611+
```bash
612+
openssl genpkey -algorithm ed25519 -out private.pem
613+
openssl pkey -in private.pem -pubout -out public.pem
614+
chmod 600 private.pem
615+
```
616+
617+
The private key is used for signing. Keep it secret. The public key can be shared with users or systems that need to verify signatures.
618+
619+
```bash
620+
trestle sign \
621+
-f catalog.json \
622+
--key private.pem \
623+
-o catalog.json.dsse
624+
```
625+
626+
For an encrypted private key, use `--key-password-env`. The option names an environment variable that contains the password, so the password is not passed as a command-line argument.
627+
628+
```bash
629+
export TRESTLE_KEY_PASSWORD='replace-with-your-password'
630+
openssl genpkey -algorithm ed25519 -aes-256-cbc -pass env:TRESTLE_KEY_PASSWORD -out private-encrypted.pem
631+
openssl pkey -in private-encrypted.pem -passin env:TRESTLE_KEY_PASSWORD -pubout -out public.pem
632+
chmod 600 private-encrypted.pem
633+
trestle sign \
634+
-f catalog.json \
635+
--key private-encrypted.pem \
636+
--key-password-env TRESTLE_KEY_PASSWORD \
637+
-o catalog.json.dsse
638+
```
639+
640+
RSA PEM keys may also be used.
641+
642+
The `--subject-name` option records a subject name other than the input file name. Verification must use the same subject name.
643+
644+
The signed Statement uses the [OSCAL signing predicate](../predicates/oscal-signing/v1.md).
645+
646+
## `trestle verify`
647+
648+
Trestle verify checks a JSON file against a detached DSSE envelope and a PEM public key. Verification checks the DSSE signature, the predicate fields, and the SHA-256 digest of the RFC 8785 canonical JSON bytes.
649+
650+
```bash
651+
trestle verify \
652+
-f catalog.json \
653+
--signature catalog.json.dsse \
654+
--key public.pem
655+
```
656+
657+
If signing used `--subject-name`, pass the same value during verification.
658+
596659
## `trestle tasks`
597660

598661
Open Shift Compliance Operator and Tanium are supported as 3rd party tools.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ dependencies = [
4848
"cmarkgfm>=2024.1,<2025.11",
4949
"orjson",
5050
"rfc8785>=0.1.4",
51+
"securesystemslib[crypto]>=1.3.1,<2.0",
5152
"requests>=2.32.2",
5253
"importlib_resources",
5354
]

0 commit comments

Comments
 (0)