Skip to content

Signing exported SBOMs ​

An organization that holds an SBOM signing key signs every merged CycloneDX JSON SBOM ReARM exports for its releases. A consumer can then check, with the organization's public keys, that the file came from that organization and was not changed after the export.

See also Exporting Compliance Artifacts and Scoring an SBOM for CISA 2026 and FDA Readiness.

What a signed export is ​

Every merged CycloneDX JSON export of a release is signed: the one the Export Release BOM dialog downloads, the one rearm exportreleasebom writes, and the document the release Score reads. The signature is a root signature object in the CycloneDX JSON Signature Format (JSF), over the whole document:

  • algorithm Ed25519;
  • the document is canonicalised with RFC 8785 (JCS: keys sorted, no whitespace, ECMAScript number form) with the signature in place and only its value left out, so indentation and key order do not matter;
  • the signature carries the key's keyId and its public key as a JWK (publicKey, kty OKP, crv Ed25519).

Every merged JSON export also says, at the end of metadata.properties, whether it is signed. The values are strings, as every CycloneDX property value is:

PropertyValueMeaning
reliza:export:signedtrueThe document carries a root signature made with the organization's current key
reliza:export:signedfalseThe document is not signed; reliza:export:unsignedReason says why
reliza:export:signatureKeyIdthe key idOn a signed document: the keyId of the key that signed it, as listed in the organization's public keys
reliza:export:unsignedReasonNO_KEYThe organization has no current SBOM signing key
reliza:export:unsignedReasonSIGNING_ERRORSigning failed on the server; the server log has the cause

These properties are inside the signed content, so they cannot be changed without breaking the signature. They stay in the document whatever the Include internal metadata switch says: they describe the file you hold.

The CISA 2026 check sbom-author-signature passes on a signed export.

Configure ​

An organization admin manages the key in Organization Settings, Admin Settings, SBOM export signing:

  1. Press Generate key. ReARM creates an Ed25519 key for the organization.
  2. The section shows the current key: its key id, algorithm, source (generated or imported), when it was created, and its public key as a JWK and as PEM, each with a copy button. Below it is the organization's public JWKS URL, and a table of earlier keys (retired and revoked) with their dates.

Exports are signed from the next request on. There is no per-export switch: while the organization has a current key, every merged JSON export is signed; without one, every export says reliza:export:unsignedReason NO_KEY.

The private key is stored encrypted at rest with this installation's encryption settings (the relizaprops.encryption password and salt, which every stored ReARM secret uses). An installation that still runs on the default values of those settings protects the key with values anyone can look up, so anyone who can read the database could recover it. Change them before you generate or import a key (with the Helm chart: useDefaultSecrets: false and the reliza-props secret's encryption-pass and encryption-salt).

A ReARM CE installation gains SBOM export signing at its next sync; until then the section says "This server does not offer SBOM export signing yet."

Rotate and revoke ​

Rotate. With a current key, the button reads Rotate key, and it asks first:

The current key is retired and new exports sign with the new key. Retired keys stay published in the JWKS so documents signed with them keep verifying.

Documents signed before the rotation keep verifying with the retired key, which stays in the organization's public keys with the status RETIRED.

Revoke. Revoke is offered on the current key and on every retired key, and asks first:

Verification of documents signed with this key will report KEY_REVOKED. If it is the current key, exports are unsigned until a new key exists.

A revoked key stays in the public keys with the status REVOKED, and a consumer verifying a document signed with it gets KEY_REVOKED. Revoking the current key leaves the organization without one: every export from then on says reliza:export:unsignedReason NO_KEY until you generate or import a new key.

The public keys are served with Cache-Control: max-age=300, so a consumer, or a proxy between you and the consumer, can keep reading the earlier key list for up to five minutes after a rotate or a revoke.

Import ​

Import key takes a private key you already hold: an Ed25519 private key as PKCS#8 PEM (a block that starts with -----BEGIN PRIVATE KEY-----). Any other form, such as an RSA, EC or OpenSSH key, is refused with:

SBOM signing key import expects an Ed25519 private key as PKCS#8 PEM (BEGIN PRIVATE KEY)

An imported key becomes the current key exactly as a generated one does: with a current key, the import rotates it, and the earlier key is retired. Its source reads IMPORTED.

To make such a key with OpenSSL:

bash
openssl genpkey -algorithm ed25519 -out org-sbom-signing.pem

How a consumer verifies ​

The organization's public keys, every key with its status, are a JWKS at:

https://<your ReARM>/api/public/v1/organization/<organization uuid>/sbom-signing-keys

It is public: no account and no API key are needed. The settings section shows the exact URL with a copy button. Each entry's kid is the key id, and rearm:status is CURRENT, RETIRED or REVOKED.

Save it to a file and verify with the ReARM CLI:

bash
curl -fsS https://<your ReARM>/api/public/v1/organization/<organization uuid>/sbom-signing-keys -o org-sbom-keys.jwks.json
rearm bomutils verify-signature -f release.cdx.json --key org-sbom-keys.jwks.json

The key whose kid equals the signature's keyId is used, and the publicKey embedded in the signature must equal it. A single public key works too, as PEM or JWK, for example the PEM the settings section shows:

bash
rearm exportreleasebom --releaseid <release uuid> | rearm bomutils verify-signature --key pub.pem

To make the signature part of an SBOM readiness gate:

bash
rearm bomutils score -f release.cdx.json --signature-key org-sbom-keys.jwks.json --fail-on-not-ready

With a key given, the signature check passes only on VERIFIED: a signature that does not verify, or that the CLI cannot verify, makes the cisa-2026 profile NOT READY.

The embedded key proves integrity, not authorship. Without --key, verify-signature checks the signature against the publicKey it embeds. That proves the document was not changed since it was signed under that key, but anyone can sign a document with a key of their own and embed it. Only a check against the organization's published keys says who signed it.

The outcome, input.signature.verification in the CLI's JSON output (from the rearm-cli bomutils documentation, "Signature verification"):

VerificationMeaning
NOT_REQUESTEDno key was given (score without --signature-key)
VERIFIEDthe signature verifies with the given key
FAILEDit does not verify (a changed document), the signature is malformed, or there is none
KEY_MISMATCHthe embedded publicKey is not the given key, or the key file holds no key for the signature's keyId
KEY_REVOKEDthe selected JWKS key is REVOKED
UNSUPPORTED_ALGORITHMan algorithm the CLI does not verify (it verifies Ed25519, ES256, ES384, ES512)
UNSUPPORTED_FORMsigners with two or more entries, chain, excludes, certificatePath, or an XML signature
NO_KEYverify-signature without --key on a signature that names only a keyId and embeds no key

A retired key still verifies; the detail says it is retired.

What the UI shows ​

Export Release BOM dialog. After an export, one line under the Export and Score buttons says what the file you just received says about itself:

  • Signed with organization key <key id>
  • Not signed: no organization SBOM signing key is configured (Organization settings, SBOM export signing)
  • Not signed: signing failed on the server (SIGNING_ERROR)

A CSV or Excel export shows Signing applies to CycloneDX JSON exports only; this file carries no signature. Before an export, and after an export from a server that does not stamp its exports, the dialog shows no line.

Score report. The report shows a signature line under the format line, read from the engine's input.signature. A score from ReARM is made without a key, so a signed export reads Signature: Ed25519, key <key id>, present, not verified (no key given); a report from the CLI made with --signature-key reads verified or the verification value with its detail.

CLI. rearm exportreleasebom prints the same sentences on stderr after a JSON export, starting with a lower-case letter (signed with organization key <key id>).

Limitations ​

  • CSV and Excel exports carry no signature.
  • Per-artifact downloads of uploaded SBOMs are served as uploaded and never re-signed.
  • VDR and VEX exports are not signed.
  • The merge drops the signatures of uploaded supplier SBOMs: the merged document carries only ReARM's signature.
  • SPDX documents are not signed.
  • The server scores without a key: in ReARM the score checks only that a signature is present and well-formed. Verify with the CLI and the organization's public keys.
  • The JWKS is public by design: public keys are meant to be handed out, and a consumer should not need a ReARM account to verify.