Signing qualification evidence
This page is part of the operator guide. The commands are in the CLI reference. Etalon can sign an evidence bundle with Ed25519. The signature is evidence that the hash manifest was produced by the holder of a seed. It does not determine that a regulation, contract, or internal control has been met. The runner version is0.0.1. Unsigned bundles from earlier runs still
verify.
What is signed
etalon sign signs the raw bytes of hashes.json as they are stored on disk.
That file lists every evidence file and its SHA-256 digest. The pack summary
is one of those files, and it records the pack content hash, so the signature
binds the pack identity that the run evaluated. The verifier does not
re-serialize hashes.json before checking.
signature.json is written next to the bundle. It is not listed in
hashes.json. A signature cannot cover a file that contains the signature.
Any other extra file in the run directory still fails verification.
The signature document records version 1, algorithm ed25519, the payload
name hashes.json, the SHA-256 of those bytes, the public key, and the
64-byte signature as hex.
Keys
The algorithm is Ed25519 (RFC 8032). A private key is a 32-byte seed. A public key is 32 bytes. Implementation is the Python standard library inetalon/evidence/ed25519.py. It is not a general-purpose cryptography library.
The arithmetic is not written to resist side channels. Use it to sign
evidence on the operator machine.
Generate a pair:
etalon keygen refuses to overwrite an existing file. The private file is
created with mode 0600. Both files are JSON.
Private file, purpose etalon-evidence-sign:
etalon-evidence-verify:
- The seed is not encrypted. Protect the private file with filesystem permissions and by keeping it off shared machines.
- Do not commit the private file. Do not put it in a bundle, a log, or a CI secret that the job prints.
- Do not pass the private file to
etalon verifyor to the GitHub Action. Those commands reject a file that contains a seed. - The public file is what auditors and the deployment gate receive. It can live in the deploy repository.
- There is no key server, registry, or rotation service. To change keys, generate a new pair and sign new bundles. Older bundles keep verifying with the public key that signed them.
- A signature check that uses only the public key embedded in
signature.jsondetects edits that were not re-signed. It does not identify the holder of the seed. Pass the public key from your own files when the signer matters.
Sign and verify with the runner
Signing refuses a bundle that fails hash, fingerprint, or manifest checks.etalon verify without a public key still checks hashes. If signature.json
is present, it must verify under the embedded key. --public-key requires a
signature and requires that key. --require-signature fails closed when the
signature file is absent.
Exit 0 means the check passed. Exit 1 means it did not.
These edits fail a signed bundle:
- a hashed file changes and
hashes.jsonis left as it was - a hashed file changes and
hashes.jsonis rewritten to the new digest without a new signature signature.jsonis replaced by a signature from a different seed while verification uses the original public key
Verify without installing Etalon
examples/verify_bundle.py checks the file set, the SHA-256 digests, manifest
decision agreement, and the Ed25519 signature. It loads
etalon/evidence/ed25519.py by path. It does not import the Etalon package, so
it does not need the runner’s dependencies and it does not use the network.
Keep this layout, or an equivalent checkout:
etalon verify also checks the fingerprint against the fingerprint schema.
etalon sign refuses to sign a bundle that fails that check. The air-gapped
script then checks that those signed bytes are unchanged. It does not
re-implement the fingerprint schema.
Deployment gate
.github/actions/etalon-verify runs the air-gapped script. The step fails when
the bundle path is missing, the public key path is missing, or verification
exits non-zero. Later deploy steps do not run after that failure.
.github/workflows/etalon-evidence-gate.yml is the same check, triggered only
by workflow_dispatch or workflow_call. It is not part of this
repository’s pull-request test workflow.
The gate checks a qualification evidence bundle. It does not decide that a
deployment meets a regulation or a contract.
Auditor export
auditor-report.html— decision, fingerprint, coverage statement, judge and calibration summary when a judge ran, hashes, and signature statusmanifest.json— the same record, plus the SHA-256 of the HTML file