Skip to content

Sigstore Interop — Exporting Diogenes Manifests for cosign

This guide is for publishers — people running CI pipelines or admin tooling who already maintain Diogenes attestations and need to hand them to downstream consumers running cosign, sigstore-policy-controller, or other in-toto / DSSE-aware tooling.

If you are a developer working on the in-toto/DSSE output layer itself (adapters, the serializer, the _diogenes_extensions envelope), see the developer reference at docs/developers/sigstore-interop.md.

When to use this

You should reach for the manifest-level export when:

  • Your CI pipeline produces a Diogenes Manifest carrying one or more signed Attestations (e.g., authorship + review + publication on a release artifact).
  • Your downstream consumer's policy verifier speaks cosign verify-blob-attestation (or cosign verify-attestation) and you do not want to change that.
  • You can afford to have the publisher's signing key online at export time. The DSSE export re-signs the in-toto Statement bytes with the publisher's key; it cannot be done by a third party who only has the manifest.

Use the single-artifact diogenes sign command when you have just one file to attest and emit (no pre-existing manifest). Use this guide's diogenes export-dsse command when you already have a manifest and want to fan out one DSSE envelope per attestation.

End-to-end example

Given a Diogenes Manifest JSON file manifest.json and a publisher key publisher.pem:

# 1. Export — one DSSE envelope per attestation in the manifest
diogenes export-dsse \
  --manifest ./manifest.json \
  --key-file ./publisher.pem \
  --out ./release.intoto.jsonl

# 2. Inspect — each line is a DSSE envelope
wc -l release.intoto.jsonl        # one line per attestation
head -n1 release.intoto.jsonl | jq '.payloadType'   # "application/vnd.in-toto+json"

# 3. Verify each envelope under cosign
PUB_KEY=./publisher-pub.pem            # extract via `openssl pkey -in publisher.pem -pubout`
ARTIFACT=./release.tar.gz
PREDICATE_TYPE=https://trustdiogenes.com/attestation/v1

while read envelope_line; do
  echo "$envelope_line" > /tmp/env.json
  cosign verify-blob-attestation \
    --key "$PUB_KEY" \
    --type "$PREDICATE_TYPE" \
    --payload "$ARTIFACT" \
    /tmp/env.json
done < release.intoto.jsonl

Each cosign verify-blob-attestation invocation prints a verification-success line and exits 0 when the envelope is valid.

The publisher-online caveat

Diogenes' native signature covers the deterministic JSON payload of the attestation. DSSE's signature covers the DSSE Pre-Authentication Encoding (PAE) of the in-toto Statement bytes. These are two different byte strings, so they require two distinct signatures.

diogenes export-dsse produces the DSSE signature at export time using the --key-file you supply. This means:

  • You can export your own attestations at any time.
  • You cannot export someone else's attestation as a Sigstore-verifiable bundle — you do not have their private key. The native Diogenes signature is still valid in their attestation, but it does not satisfy cosign on its own.
  • For "I want anyone to be able to convert this Diogenes attestation into a Sigstore-verifiable form" you need a different design — likely a transparency export where the verifier re-fetches the original Diogenes manifest and re-checks the native signature against the Diogenes Key Registry. That work is not in scope for this release (see issue #308 "Out of scope").

The native signature is preserved verbatim inside the DSSE envelope, under the predicate's _diogenes_extensions block. Diogenes-aware verifiers can recover it and check it against the Diogenes Key Registry; sigstore-aware verifiers ignore the extension and check the DSSE signature against the supplied --key.

What goes in the predicate

By default, the manifest-level export uses the Diogenes-native passthrough adapter (predicateType: https://trustdiogenes.com/attestation/v1) and parks the entire native attestation under _diogenes_extensions. The typed predicate body is empty {}.

If you need to emit a typed predicate — for example, SLSA Provenance v1 — call the SDK function directly with a custom resolver:

from diogenes.interop.sigstore.output import serialize_manifest_to_intoto_jsonl

result = serialize_manifest_to_intoto_jsonl(
    manifest,
    private_key=publisher_key,
    predicate_type_resolver=lambda att: "https://slsa.dev/provenance/v1",
    predicate_body_resolver=lambda manifest, att: {
        "buildType": "https://example.com/my-build-type/v1",
        # ...
    },
)
Path("release.intoto.jsonl").write_text(result.jsonl_text)

See the developer reference for the full adapter list.

Limitations vs. native Diogenes verification

Cosign / sigstore tooling cannot do everything a Diogenes verifier can:

Feature DSSE export (cosign) Native Diogenes verify
Cryptographic signature covering the content hash Yes (DSSE signs canonical Statement bytes, which embed the digest) Yes (deterministic payload)
Web-of-trust resolution No — single key check only Yes — full trust-config graph
Endorsement DAG traversal No Yes
OpenTimestamps / Bitcoin anchoring Not exposed via the DSSE envelope Yes — ots_proofs in the manifest
Per-attestation type semantics Surfaced as predicateType Surfaced as attestation.type + adapter logic
Verifier-side public key discovery Caller provides --key or uses certificate-identity Diogenes Key Registry transparency log

The export gives you "this artifact has a signature by this key" — the same answer Sigstore gives. It does not give you "this signature is trusted under the project's policy graph"; for that you still need the native Diogenes pipeline.

Output format details

release.intoto.jsonl is a newline-delimited JSON file. Each line is one DSSE envelope:

{"payloadType":"application/vnd.in-toto+json","payload":"<base64>","signatures":[{"sig":"<base64>","keyid":"<fingerprint>"}]}

The payload field is the base64-encoded canonical (JCS) bytes of an in-toto Statement. The Statement's predicate._diogenes_extensions sub-object carries the full native Diogenes attestation.

Reserved formats

--format sigstore-bundle is reserved for a future release. Today, selecting it exits non-zero with an "install extras" message. The Sigstore Bundle protobuf form (bundle.sigstore.json) is tracked as a follow-up to #308 and will ship when there is a real consumer asking for it.

Cosign installation

The export itself does not depend on cosign — you only need cosign to verify the output. Install per the cosign install guide:

# macOS / Linux
go install github.com/sigstore/cosign/v2/cmd/cosign@latest
# or download a release binary
curl -L https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o cosign
chmod +x cosign && sudo mv cosign /usr/local/bin/

See also