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'scacerts.digicert.comservice. 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.