Skip to content

Commit fb9dbf7

Browse files
authored
docs: add the proposal for Notation blob signing and verification (#1180)
Add the proposal for #741 Signed-off-by: Yi Zha <yizha1@microsoft.com> --------- Signed-off-by: Yi Zha (from Dev Box) <yizha1@microsoft.com>
1 parent 18018da commit fb9dbf7

File tree

1 file changed

+333
-0
lines changed

1 file changed

+333
-0
lines changed

specs/proposals/blob-signing.md

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
# Proposal for Supporting Blob Signing and Verification in Notation
2+
3+
## Overview
4+
5+
A **blob**, short for [Binary Large Object](https://wikipedia.org/wiki/Binary_large_object) is a collection of binary data stored as a single entity. In this proposal, a blob refers to any binary data or file content, including SBOM (Software Bill of Materials) files, release assets, AI model files (such as model files on [Hugging Face](https://huggingface.co/)), WebAssembly files or other forms of unstructured data. While Notation currently supports signing and verifying OCI (Open Container Initiative) artifacts such as container images, this document outlines a proposal to extend the Notation tool's capabilities to include blob signing and verification.
6+
7+
## Problem Statement & Motivation
8+
9+
Signing container images alone is not enough to secure the software supply chain for containers. In addtion to images, SBOMs, configuration files, release binaries or other artifacts must also be signed and verified to ensure their integrity and authenticity. With the increasing use of AI model files and WebAssembly files, securing these artifacts is equally critical. By adding blob signing, Notation can extend its capabilities to handle a broader range of artifacts across various scenarios, enhancing its versatility while leveraging its existing key management and trust policy framework.
10+
11+
## Scenarios
12+
13+
The following describes how blob signing and verification can be used for various scenarios:
14+
15+
### Scenario 1: Blob signing and verification with file-based distribution
16+
17+
Sarah, a software engineer, creates binaries for applications that are distributed via her company's website. In CI/CD pipelines, she creates tasks that generates an SBOM for each binary and signs the SBOM to ensure the authenticity and integrity of the SBOM. The pipeline automatically generates a digital signature for each SBOM, which is stored alongside the SBOM on the filesystem. With SBOM and signatures created, the pipeline tasks automatically upload the binaries, SBOMs, and SBOM signatures to the company website as separate downloadable artifacts. The compliance team downloads the SBOM and signature to check whether the corresponding binary is compliant with both company and governance rules. Before analyzing the SBOM, they verify its integrity against the corresponding signature, ensuring the SBOM hasn't been tampered with since being signed in the pipeline and that it originates from the Sarah's company.
18+
19+
David, a release manager, has set up signing task in CI/CD pipelines to sign release artifacts, such as binaries, deployment scripts, and configuration files before they are publicly distributed to ensure that they haven't been tampered with during distribution. After the artifacts pass verification, they are signed and published on the release website. Users download both release artifacts and corresponding signatures, and verify the signatures to ensure that the artifacts are untampered and trustworthy before using them.
20+
21+
### Scenario 2: Blob signing and verification with registry-based distribution
22+
23+
The platform team at Sarah’s company leverages their existing OCI-compliant registry to distribute SBOMs while preserving the current generation process. The CI/CD pipeline continues to build binaries, generate SBOMs, and sign them as usual. However, instead of uploading these artifacts to the company website, the pipeline pushes the SBOM and its signature as separate OCI artifacts. To facilitate easy discovery, each signature references its corresponding SBOM in the registry. The compliance team then downloads both SBOMs and their associated signatures to the filesystem, verifies the signatures, and proceeds with SBOM analysis.
24+
25+
## Proposal
26+
27+
This section outlines the proposed solution for signing and verifying blobs using Notation CLI commands. The following topics are outside the scope of this document:
28+
29+
- **Detailed command usage**, which is covered in the individual command specifications at [Notation CLI specs](https://github.com/notaryproject/notation/tree/main/specs/commandline).
30+
- **Distribution of certificates** for verification in different scenarios.
31+
- **Blob signature definitions**, as outlined in the [Notary Project specification](https://github.com/notaryproject/specifications/blob/main/specs/signature-specification.md#blob-payload).
32+
- **CI/CD integration**, as this document specifically focuses on using Notation CLI commands.
33+
34+
In general, all blob-related commands are grouped under the `notation blob` command per the [blob command spec](https://github.com/notaryproject/notation/blob/main/specs/commandline/blob.md).
35+
36+
### Blob sign and verify with file-based distribution
37+
38+
For file-based distribution, such as SBOMs or release artifacts shared via a website or file transfer system, the process of signing and verifying blobs follows a similar flow. The steps below outline the user experience for signing and verifying a file, using an SBOM file named `sbom.json` as an example.
39+
40+
**Prerequisites:**
41+
- SBOMs, release artifacts or other files are created and ready for publishing
42+
43+
**Steps:**
44+
45+
1. Sign a file on filesystem with a specified signature envelope:
46+
47+
```shell
48+
notation blob sign --id myKeyId --signature-format "cose" --media-type "application/spdx+json" sbom.json
49+
```
50+
This command generates a signature file named `sbom.json.cose.sig` in the same directory as `sbom.json` by default. The file name follows the [Notary Project specification](https://github.com/notaryproject/specifications/blob/main/specs/signature-specification.md#blob-signatures). The signature format is **COSE**, as specified by the `--signature-format` flag. The default format is **JWS**. The `--media-type` flag specifies the **media type** of the blob. In this example, the content of `sbom.json` is in the format `application/spdx+json`. This flag is **optional**. If omitted, the default media type **`application/octet-stream`** is used.
51+
52+
2. Publish both the file and corresponding signature using any file transfering mechanism. Both the file and its signature can be packaged into one file (e.g., a tarball) for transferring.
53+
54+
3. Download or fetch both the file and signature. If they are packaged into one file, for example, a tarball, unpackage the file to get separate file and signature.
55+
56+
4. Verify the file against the signature:
57+
58+
- Add the root CA certificate and set up the trust store (The same experience for verifying container images):
59+
60+
```shell
61+
notation cert add --type ca --store myCACerts root.crt
62+
```
63+
64+
Confirm the certificate is added.
65+
66+
```shell
67+
notation cert ls
68+
```
69+
70+
> **Note:** Learn more options using `notation cert ls --help`.
71+
72+
- Set up trust policy for blobs with a new command `notation blob policy init`. This command streamlines the process, eliminating the need for users to consult documentation for the correct trust policy format and preventing the accidental use of policies intended for OCI artifact verification.
73+
74+
```shell
75+
notation blob policy init --name "myBlobPolicy" --trust-store "ca:myCACerts" --trust-identity "x509.subject:C=US,ST=WA,O=wabbit-network.io"
76+
```
77+
78+
Show the policies configured for verifying blobs:
79+
80+
```shell
81+
notation blob policy show
82+
```
83+
84+
> [!NOTE]
85+
> See the [section](#manage-blob-policies) for more commands for `notation blob policy`.
86+
87+
- Verify the signature:
88+
89+
```shell
90+
notation blob verify --policy-name myBlobPolicy --signature sbom.json.cose.sig sbom.json
91+
```
92+
93+
If a [global policy](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#blob-trust-policy) is set, you can skip the `--policy-name` flag.
94+
95+
### Blob Sign and verify with registry-based distribution
96+
97+
For registry-based distribution, such as using an OCI-compliant container registry, the process is similar but includes additional steps for pushing blobs and sigantures to the registry.
98+
99+
**Prerequisites:**
100+
- SBOMs, release artifacts or other files are created and ready for publishing.
101+
102+
**Steps:**
103+
104+
1. Sign a file on filesystem with a specified signature envelope:
105+
106+
```shell
107+
notation blob sign --id myKeyId --signature-format "cose" --media-type "application/spdx+json" sbom.json
108+
```
109+
110+
This generates a signature named `sbom.json.cose.sig` in the same directory as `sbom.json` by default.
111+
112+
2. Publish the file and signature to the OCI-compliant registry:
113+
114+
Use [ORAS tool](https://oras.land/) to push the blob file:
115+
116+
```shell
117+
oras push --artifact-type "application/spdx+json" sbom.json:application/json myregistry/myapp/sbom:v1
118+
```
119+
120+
This command stores `sbom.json` as an OCI artifact referenced by `myregistry/mypath/mysboms:v1` in the registry, which has the artifact type `application/spdx+json` and `sbom.json` data stored as a layer with the media type `application/json`. Below is an example of the manifest for the reference `myregistry/mypath/mysboms:v1`:
121+
122+
```json
123+
{
124+
"schemaVersion": 2,
125+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
126+
"artifactType": "application/spdx+json",
127+
"config": {
128+
"mediaType": "application/vnd.oci.empty.v1+json",
129+
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
130+
"size": 2,
131+
"data": "e30="
132+
},
133+
"layers": [
134+
{
135+
"mediaType": "application/json",
136+
"digest": "sha256:3154705eb5fc92bc3f91deec6008e6dd4a02b3e53ac18bdb7ea3ff03e62971a8",
137+
"size": 845,
138+
"annotations": {
139+
"org.opencontainers.image.title": "sbom.json"
140+
}
141+
}
142+
],
143+
"annotations": {
144+
"org.opencontainers.image.created": "2025-02-18T06:00:00Z"
145+
}
146+
}
147+
```
148+
149+
Use ORAS tool to attach the signature to the blob file:
150+
151+
```shell
152+
oras attach myregistry/myapp/sbom:v1 --artifact-type 'application/vnd.cncf.notary.signature' sbom.json.cose.sig:application/cose -a "io.cncf.notary.blob.signature=true"
153+
```
154+
155+
This command stores the signature file `sbom.json.cose.sig` as another OCI artifact with the artifact type `application/vnd.cncf.notary.signature` as Notary Project signature, and the signature data as a layer with media type `application/cose` as a COSE signature. The layer media type can be detected according to the file name, which is either `application/cose` or `application/jws`. The signature manifest's `subject` property is set to `myregistry/myapp/sbom:v1` to refer to the blob in the registry.
156+
157+
To distinguish these signatures from those generated during signing an existing artifact in the OCI registry, the specific annotation `io.cncf.notary.blob.signature=true` is added for the blob signature manifest. For example, users can push the SBOM file to the OCI registry first and then use `notation sign myregistry/myapp/sbom:v1`, which generates a signature attached to the SBOM in the registry, but this signature is for OCI artifact, which is not in the same format as the blob signature.
158+
159+
> **Note:** While users can push both the blob and the signature file as a single OCI artifact, this is not recommended. Since there may already be existing blob stored in the registry, you only need to attach the signature to it . Additionally, this approach is not practical if you need to sign the blob with multiple signatures, for example, using different keys at a later stage.
160+
161+
Below is an example of the manifest for the blob signature in the registry:
162+
163+
```json
164+
{
165+
"schemaVersion": 2,
166+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
167+
"artifactType": "application/vnd.cncf.notary.signature",
168+
"config": {
169+
"mediaType": "application/vnd.oci.empty.v1+json",
170+
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
171+
"size": 2,
172+
"data": "e30="
173+
},
174+
"layers": [
175+
{
176+
"mediaType": "application/cose",
177+
"digest": "sha256:6dc2a336b124d625f87deb3f539fa1465414ddad300a898adf4682e530d6f144",
178+
"size": 1479,
179+
"annotations": {
180+
"org.opencontainers.image.title": "sbom.json.cose.sig"
181+
}
182+
}
183+
],
184+
"subject": {
185+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
186+
"digest": "sha256:57eed31a09556933bddd4e164e1e085a220cf00489477eb98d89feac902eb42b",
187+
"size": 553
188+
},
189+
"annotations": {
190+
"io.cncf.notary.blob.signature": "true",
191+
"org.opencontainers.image.created": "2025-02-18T06:08:45Z"
192+
}
193+
}
194+
```
195+
196+
3. Discover signatures in OCI registries
197+
198+
Use the `notation ls` command to discover the blob signature attached to a blob in the OCI registry. Since there may be OCI signatures generated for an OCI artifact, the `notation ls` command need to display the annotation `io.cncf.notary.blob.signature=true`, if present, to indicate that it is a blob signature. For example,
199+
200+
```shell
201+
notation ls myregistry/myapp/sbom:v1
202+
```
203+
204+
Sample output:
205+
206+
```text
207+
myregistry/myapp/sbom@sha256:3472cf1b816e5615a5f1883bbdb8c5b91e3a11cd7a566d323bd429d72c667f2b
208+
└── application/vnd.cncf.notary.signature
209+
└── sha256:e8c3567e1f679dfd372ab97635329e404c5182864e29abd96acf852b1ac1ef6b
210+
└── io.cncf.notary.blob.signature: "true"
211+
```
212+
213+
Similarly, users can use the `oras discover` with additional `-v` flag to show annotations. Unlike `notation ls`, the `oras discover -v` command lists all annotations present in the manifest. For example,
214+
215+
```shell
216+
oras discover myregistry/myapp/sbom:v1
217+
```
218+
219+
Sample output:
220+
221+
```text
222+
myregistry/myapp/sbom@sha256:3472cf1b816e5615a5f1883bbdb8c5b91e3a11cd7a566d323bd429d72c667f2b
223+
└── application/vnd.cncf.notary.signature
224+
└── sha256:e8c3567e1f679dfd372ab97635329e404c5182864e29abd96acf852b1ac1ef6b
225+
└── io.cncf.notary.blob.signature: "true"
226+
└── org.opencontainers.image.created: "2025-02-28T18:06:08Z"
227+
```
228+
229+
4. Verify the signature from the registry:
230+
231+
- Add the root CA certificate and set up the trust store:
232+
233+
```shell
234+
notation cert add --type ca --store myCACerts root.crt
235+
```
236+
237+
Confirm that the cert is added.
238+
239+
```shell
240+
notation cert ls
241+
```
242+
243+
- Set up the trust policy:
244+
245+
```shell
246+
notation blob policy init --name "myBlobPolicy" --trust-store "ca:myCACerts" --trust-identity "x509.subject:C=US,ST=WA,O=wabbit-network.io"
247+
```
248+
249+
- Download the blob and signature using ORAS tool:
250+
251+
Follow the previous section to discover blog signatures, and get the digest of the siganture that you want to pull, and use the following command to pull the signature and the blob:
252+
253+
```shell
254+
oras pull --include-subject myregistry/myapp/sbom@sha256:e8c3567e1f679dfd372ab97635329e404c5182864e29abd96acf852b1ac1ef6b
255+
```
256+
257+
This command pulls both the `sbom.json` and `sbom.json.cose.sig` to your filesystem.
258+
259+
- Verify the signature:
260+
261+
```shell
262+
notation blob verify --policy-name myBlobPolicy --signature sbom.json.cose.sig sbom.json
263+
```
264+
265+
If users run the `notation verify` command to verify blob signatures, the verification will fail. However, the output should inform users to download the blob and its signature and use the `notation blob verify` command instead.
266+
267+
Sample output:
268+
269+
```text
270+
Error: Signature verification failed: unsupported signature format for the OCI artifact myregistry/myapp/sbom@sha256:e8c3567e1f679dfd372ab97635329e404c5182864e29abd96acf852b1ac1ef6b.
271+
272+
If you are verifying a blob signature, try downloading the blob and its signature, then use `notation blob verify` instead.
273+
```
274+
275+
### Manage blob policies
276+
277+
The following commands are available for managing blob trust poliies:
278+
279+
- Initialize blob trust policy configuration:
280+
281+
```shell
282+
notation blob policy init --name "myBlobPolicy" --trust-store "ca:myCACerts" --trust-identity "x509.subject:C=US,ST=WA,O=wabbit-network.io"
283+
```
284+
285+
- Initialize the blob trust policy configuration and set the policy specified by the `--name` flag as the global policy.
286+
287+
```shell
288+
notation blob policy init --global --name "myBlobPolicy" --trust-store "ca:myCACerts" --trust-identity "x509.subject:C=US,ST=WA,O=wabbit-network.io"
289+
```
290+
291+
- Overwrite an existing policy with a prompt:
292+
293+
```shell
294+
notation blob policy init --name "myBlobPolicy" --trust-store "ca:myCACerts" --trust-identity "x509.subject:C=US,ST=WA,O=wabbit-network.io"
295+
```
296+
297+
If the blob policy named `myBlobPolicy` has already been initialized before, running this command will prompt the user to confirm whether they want to overwrite the existing blob policy.
298+
299+
- Overwrite an existing policy with a prompt using the flag `--force`:
300+
301+
```shell
302+
notation blob policy init --force --name "myBlobPolicy" --trust-store "ca:myCACerts" --trust-identity "x509.subject:C=US,ST=WA,O=wabbit-network.io"
303+
```
304+
305+
- Show the blob policy:
306+
307+
```shell
308+
notation blob policy show
309+
```
310+
311+
- Modify the blob policy:
312+
313+
- Export the existing blob policy configuration to a JSON file:
314+
315+
```shell
316+
notation blob policy show > myBlobPolicy.json
317+
```
318+
319+
- Update and save the JSON file `myBlobPolicy.json`
320+
321+
- Import the updated policies:
322+
323+
```shell
324+
notation blob policy import myBlobPolicy.json
325+
```
326+
327+
### Inspect blob signatures
328+
329+
The `notation blob inspect` command allows users to inspect blob signatures, providing output similar to the `notation inspect` command.
330+
331+
```shell
332+
notation blob inspect sbom.json.cose.sig
333+
```

0 commit comments

Comments
 (0)