Skip to content

Apizr's managed release identity

Apizr uses a dedicated Ed25519 key for delivery receipts. This identity is separate from continuum-attest's own signing keys and from GitHub's keyless build provenance. The repository maintainer manages its provisioning and revocation.

  • Key identifier: ac3b0b1c565ef9e18f894c10f5ce1cdb.
  • Raw public key: 1d397e601c7efc4b8e372efa3d23bfbd819ecc02070d38a80335b1fd9a4e72e1.
  • Public key and trust policy: .attest/trust/ in the protected repository.
  • Timestamp authority: DigiCert's documented RFC 3161 service, http://timestamp.digicert.com. Only the signature's digest is submitted.
  • Pinned issuer: DigiCert Trusted G4 TimeStamping RSA4096 SHA256 2025 CA1, DER SHA-256 ca0b1554ecd901ea19dcad8749e9f2648c8d6dfcea1add9d2c2109415bb82ccd. Its certificate was obtained from DigiCert's cacerts.digicert.com service. Verification requires the pinned issuer and validates the token signature, message imprint, certificate purpose and validity at the timestamped time.

The identity setup proof under tests/fixtures/attest-identity/ is an explicitly labeled test message, not a release receipt. CI verifies its signature and real RFC 3161 token offline, then requires rejection of changed content, a missing timestamp, an invalid signature and an untrusted key. PRs never use the private release key or call the timestamp service.

Receipt before publication

The publication workflow first verifies the exact CI distributions and their GitHub provenance. A separate environment-protected job then installs the hash-pinned Attest 0.1.0 binary and signs a fresh delivery pipeline. It declares the wheel, sdist, CI/dependency evidence and a SHA-256 manifest with the source commit and CI run identifier as inputs and outputs. It does not rebuild them or claim that Attest supervised their original build. GitHub provenance remains the build evidence.

Private signing material is excluded from release artifacts. The PyPI publisher executes no checkout or repository code.

Publication requires the expected Apizr signer and all five verification checks to pass: schema, consistency, signature, timestamp and recomputed hashes. Missing or skipped checks, warnings and timestamp-service failures block; there is no unsigned fallback. The environment's existing reviewer and tag restrictions remain in place. Release 0.2.1 exercised this protected workflow and delivered the receipt with the exact PyPI distributions. Its signature, RFC 3161 timestamp and recomputed hashes were independently checked offline after extraction, using the repository trust store. Public PyPI bytes and all GitHub attachments matched the verified inputs. The release record contains the source, runs and receipt archive hash that satisfy the delivered- artifact criterion in #73.

Verify a delivered receipt

Use the pinned Attest version and download apizr-attest-receipt.tar.gz from the release. Extract it into a new directory. The archive includes the signed pipeline, receipt, manifest and exact files; it duplicates the delivered wheel and sdist so hash recomputation needs no network.

Obtain the trusted public key/policy and TSA issuer independently, for example from a previously reviewed repository revision. Do not establish trust solely from the archive's own trust/ directory. With the extracted directory as the current directory:

attest verify receipt.yaml --recompute --workspace . \
  --trust-store /path/to/independently-trusted-apizr-keys --offline --format json

Require signed_by to equal the public key above and each of the five named checks to be pass, with no warnings. A top-level pass alone is insufficient: Attest permits optional checks to be skipped, whereas Apizr's publication gate does not. Compare the archived distribution SHA-256 values with the files downloaded directly from PyPI/the release. For automated enforcement, the repository's scripts/attest_release.py contains the same strict verifier.

The pipeline mode is intentional: the published 0.1.0 CLI's --recompute needs attest.yaml; a wrap-mode receipt cannot satisfy this verification path.

Rotation and recovery

If a signing identity can no longer be used, create a new identity and update its public policy through a reviewed PR. Do not silently replace the private key under an existing key identifier. Revoke a compromised key with a recorded UTC revocation time, retain its public key and history, and review which timestamped receipts remain acceptable. Never use --trust-receipt-timestamp to bypass independent time evidence.

Key/TSA rotation requires updating the pinned policy and offline setup fixture, repeating the negative verification checks, and updating the signing configuration before publishing. Keep previous public keys and issuer certificates so older receipts can still be checked against their original trusted policy. No other project's signing identity is changed by this setup.