Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
1c9e785
add new how-tos and concept
morrison-sap Feb 24, 2026
a3b0fb1
adopt existing guides to how-to design and move to different folder
morrison-sap Feb 24, 2026
001e4d2
rework tutorial in diataxis format
morrison-sap Feb 24, 2026
f19bed5
add guide to configure crendentials for OCM controllers
morrison-sap Feb 25, 2026
70a82af
correct linter issues
morrison-sap Feb 25, 2026
b5a98ef
correct linter issues
morrison-sap Feb 25, 2026
8f92710
correct linter issues
morrison-sap Feb 25, 2026
4721578
correct spellcheck issues
morrison-sap Feb 26, 2026
b20b464
correct linter issues
morrison-sap Feb 26, 2026
fb37a0d
merge from upstream/main
morrison-sap Mar 9, 2026
51f5b25
adopt better to diataxis: move best practices from concept to tutoria…
morrison-sap Mar 9, 2026
7b303e6
rebase
morrison-sap Mar 9, 2026
1d5870b
correct broken links
morrison-sap Mar 9, 2026
3e276de
correct broken links
morrison-sap Mar 9, 2026
88d688c
update hugo
morrison-sap Mar 9, 2026
8bd0cf1
correct linter issues
morrison-sap Mar 9, 2026
08b3fed
correct linter issues
morrison-sap Mar 9, 2026
a0cd980
Merge branch 'main' into create-new-security-docs
matthiasbruns Mar 10, 2026
863a944
Merge remote-tracking branch 'upstream/main' into create-new-security…
morrison-sap Mar 11, 2026
4ef9aae
correct order of docs, now starting with weight=1 gor the first doc o…
morrison-sap Mar 11, 2026
0df5847
Merge branch 'create-new-security-docs' of github.com:morri-son/ocm-w…
morrison-sap Mar 11, 2026
294479d
restore key pair creation
morrison-sap Mar 11, 2026
a6bcfdc
add callout for sigstore support and change version for jsonNormalisa…
morrison-sap Mar 11, 2026
b80de4d
change order
morrison-sap Mar 11, 2026
0b28a10
Merge remote-tracking branch 'upstream/main' into create-new-security…
morrison-sap Mar 12, 2026
1ae9c35
remove hugo update from this PR
morrison-sap Mar 12, 2026
c2697e6
remove hugo update from this PR
morrison-sap Mar 12, 2026
494ce80
replace `~` with $HOME everwhere. Use example component from getting …
morrison-sap Mar 12, 2026
62d2ad2
correct docs and integrate feedback from reviewers.
morrison-sap Mar 12, 2026
0aca291
move tutorial to correct ocm cli v2 commands and test.
morrison-sap Mar 12, 2026
5b1ff09
add back link to json normalization in the ocm spec.
morrison-sap Mar 12, 2026
ae43a39
add reference for consumer identities and link it from the other docs.
morrison-sap Mar 13, 2026
465cd05
update with decriptor
morrison-sap Mar 13, 2026
9221dd9
add signatureEncodingPolicy section and explain Plain vs. PEM
morrison-sap Mar 13, 2026
51ca1eb
Apply suggestions from code review
morri-son Mar 13, 2026
27c7c6f
hide large decriptor example behind {{< details >}} section
morrison-sap Mar 13, 2026
b5b2ca6
Merge branch 'main' into create-new-security-docs
morri-son Mar 13, 2026
89b8d0c
Merge remote-tracking branch 'upstream/main' into create-new-security…
morrison-sap Mar 13, 2026
b596ea0
integrate commenbts from review
morrison-sap Mar 16, 2026
c923437
switch back to "~" for crdnetials that touch repositories
morrison-sap Mar 16, 2026
607f1db
Update content/docs/concepts/signing-and-verification-concept.md
morri-son Mar 16, 2026
3e5ee09
cleanup inconsistencies in paths for keys. Correct cleanup of tmp fol…
morrison-sap Mar 16, 2026
a33fdb9
correct inconsistencies in paths for ctf locations.
morrison-sap Mar 16, 2026
c30699d
Merge remote-tracking branch 'upstream/main' into create-new-security…
morrison-sap Mar 16, 2026
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
8 changes: 8 additions & 0 deletions .github/config/wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,14 @@ diataxis
callouts
shortcode
shortcodes
href
dockerconfigjson
rhel
misattributed
whitespace
hsms
helloworld
centos
wsl
auditable
hasmermaid
Expand Down
156 changes: 156 additions & 0 deletions content/docs/concepts/signing-and-verification-concept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
---
title: "Signing and Verification"
description: "Understanding how OCM ensures component integrity and authenticity through cryptographic signatures."
weight: 40
toc: true
---

OCM uses cryptographic signatures to guarantee that component versions are authentic (created by a trusted party) and have not been tampered with during storage or transfer.

## Why Sign Components?

Software supply chains involve multiple stages: development, build, packaging, distribution, and deployment. At each stage, components could potentially be:

- **Modified** — malicious actors could inject code or alter resources
- **Replaced** — components could be swapped for compromised versions
- **Misattributed** — components could falsely claim to come from a trusted source

Signing addresses these risks by creating a cryptographic proof that:

1. **Integrity**: The component has not changed since it was signed
2. **Authenticity**: The signature was created by someone with access to the private key
3. **Non-repudiation**: The signer cannot deny having signed the component

## How OCM Signing Works

```mermaid
flowchart TB
subgraph sign ["Sign (Producer)"]
direction TB
A[Component Version] --> B[Normalize & Hash]
B --> C[Sign with Private Key]
C --> D["Signature embedded in CV"]
end

sign --> T["Transfer Component Version"]

T --> verify

subgraph verify ["Verify (Consumer)"]
direction TB
E[Component Version] --> F[Extract Signature]
E --> G[Normalize & Hash]
F --> H[Verify with Public Key]
G --> H
H --> I{Valid?}
I -->|Yes| VALID["✓ Trusted"]
I -->|No| INVALID["✗ Rejected"]
end
```

### Normalization and Digest Calculation

OCM uses a two-layer approach to ensure consistent and reproducible digests:

#### Component Descriptor Normalization

Before hashing, the component descriptor is normalized to produce consistent digests regardless of:

- Field ordering in YAML/JSON
- Whitespace variations
- Optional fields with default values

The default algorithm (`jsonNormalisation/v2`) produces a canonical JSON representation that ensures identical component descriptors always yield the same digest.

#### Artifact Digest Normalization

Each artifact's digest is calculated using a type-specific normalization algorithm:

| Artifact Type | Algorithm | Description |
|---------------|-----------|-------------|
| Generic blob | `genericBlobDigest/v1` | Direct hash of blob content |
| OCI artifact | `ociArtifactDigest/v1` | Uses OCI manifest digest |

This allows OCM to use the most appropriate digest mechanism for each artifact type. For example, OCI artifacts use their manifest digest rather than re-hashing the blob, ensuring consistency with OCI registry behavior.

#### Recursive Component References

When a component references other components, their digests are calculated recursively and embedded:

```yaml
references:
- componentName: ocm.software/helper
name: helper
version: 1.0.0
digest:
hashAlgorithm: SHA-256
normalisationAlgorithm: jsonNormalisation/v2
value: 01c211f5c9cfd7c40e5b84d66a2fb7d19cb0...
```

This creates a **complete integrity chain** — verifying the root component automatically verifies all transitive dependencies.

### What Gets Signed?

OCM signs a **digest** of the component descriptor, which includes:

- Component metadata (name, version, provider)
- Resource declarations with their digests
- Source references
- Component references

The signature does **not** cover the raw resource content directly—instead, it covers the **digests** of those resources as recorded in the component descriptor. This means:

- Any change to resource content changes its digest, invalidating the signature
- Signature verification is fast (no need to re-hash large binaries)
- Resources can be stored separately while still being integrity-protected

### Signature Storage

Signatures are stored as part of the component version:

```yaml
signatures:
- name: acme-release-signing
digest:
hashAlgorithm: SHA-256
normalisationAlgorithm: jsonNormalisation/v1
value: abc123...
signature:
algorithm: RSASSA-PKCS1-V1_5
mediaType: application/vnd.ocm.signature.rsa
value: <base64-encoded-signature>
```

A component version can have **multiple signatures** from different parties, enabling:

- Separation of build and release signing
- Multiple approval workflows
- Cross-organizational trust chains

## Supported Algorithms

OCM supports RSA-based signature algorithms:

| Algorithm | Type | Use Case |
|-----------|------|----------|
| RSA-PKCS#1 v1.5 | Asymmetric | Traditional PKI, widely supported |
| RSASSA-PSS | Asymmetric | Modern RSA with better security properties |

For key management, OCM uses PEM-encoded key files:

- **Private keys**: Used by producers to sign component versions
- **Public keys**: Distributed to consumers for verification

See [How-to: Generate Signing Keys]({{< relref "docs/how-to/generate-signing-keys.md" >}}) for creating RSA key pairs.

## Next Steps

- [How-to: Generate Signing Keys]({{< relref "generate-signing-keys.md" >}}) - Step-by-step creating RSA key pairs.
- [How-to: Configure Signing Credentials]({{< relref "configure-signing-credentials.md" >}}) - Set up OCM to use your keys for signing and verification
- [How-to: Sign a Component Version]({{< relref "sign-component-version.md" >}}) - Step-by-step signing instructions
- [How-to: Verify a Component Version]({{< relref "verify-component-version.md" >}}) - Step-by-step verification instructions

## Related Documentation

- [Concept: Component Versions]({{< relref "components.md" >}}) - Understanding component structure
Loading
Loading