> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parmanasystems.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Which key signed this? Key ids, expiry and revocation

> How Parmana names the key behind every signature so keys can be rotated without breaking old records, and how an expired or revoked key stops being accepted.

Here is an example. A payments team in Bengaluru has used one signing key for a year. Every refund an agent proposed and
a person approved, ₹40,000 here, ₹1,200 there, left a signed record. Then a laptop goes missing, and the team decides to
replace the key.

Two problems appear at once. If the verifier only knows "the" public key, then the day they switch, every record from
the past year stops verifying. And if they keep the old key around so old records still verify, what stops someone who
has the stolen key from signing something new with it?

A signature is only as useful as your answer to one question: which key made it, and was that key still good?

## One key forever is not a plan

The simplest design is a single key pair. The server signs with the private half; everyone verifies with the public
half. It works until the first rotation, and rotation is not optional. Keys leak, people leave, and some keys should
simply have a shelf life.

Parmana has its own reason to care. A default signing key used before 2026-07-05 was publicly exposed. It was rotated
that day, and it must still be treated as permanently compromised, whichever repository exposed it. That is written at the top of the
claims register, and it is why rotation had to work without breaking everything else.

## The idea: every signature names its key

Put a key id on every signature. A verifier then does not ask "does this verify against our key?" but "does this
verify against the key it names, and is that key acceptable right now?"

That splits the problem in two. Old records keep verifying, because they name the old key and the old public key is
kept. New signing moves to a new key id. And a separate list says which key ids have expired or been revoked, so the
old key can be refused for anything that must be current.

## How Parmana does it

**Execution authorizations.** The signed authorization that lets the gateway release an action carries its own key id.
The gateway resolves the public key by that id, through the same signer that made the signature, whether the key lives
in a local file or in AWS KMS. Signing and verification have to use the same source for a key, or a key that signs can fail to verify. The design
resolves both through one signer, so that mismatch cannot be configured.

**Expiry and revocation.** Before reading any key material, the gateway can check the key id against a small list kept
beside the keys. An entry can say the key is revoked, or give a time after which it expires. A revoked key, an expired
key, or a key that cannot be found makes key resolution fail, and the authorization fails verification. There is no
quiet fallback to some other key. A key id with no entry is treated as always valid, so a deployment that never writes
the list behaves exactly as before. A list that is malformed is an error, not "no expiry". This is claim 2.28.

**Durable records.** Trust Records, Refusal Records and audit events used to be signed under a fixed key id, so they
could not be rotated without breaking every earlier signature. Now the key id for new signatures is a setting, a script
creates a new key under a fresh id, and verification always uses the id stored on the record. The rule in the
production runbook is blunt: never delete the old key files, because old records name them.

**Public keys by id.** Anyone can fetch a public key by its id, or the list of keys the server publishes, without an API
key. The offline verifiers take a map from key id to public key, so an auditor checks each record against the key it
names.

**Other keys follow the same pattern.** A transaction for a tenant can be signed with that tenant's own key, and a
caller may only name tenants its API key allows. Keys trusted to sign human approvals are added and revoked through
maker checker, with no deploy, and the gateway re-checks that the approver's key is still trusted just before release.

## What it does not do

* **Expiry and revocation are checked for execution authorizations only.** The list is consulted at the gateway. The
  offline verifiers for Trust Records and other durable records check a signature against the key it names; they do not
  consult a revocation list. A record signed by a key that was later compromised still verifies mathematically. Knowing
  the key is compromised, as with the 2026 notice, is up to the reader.
* **A revoked key's past signatures are not undone.** Revocation stops a key being accepted from now on. It cannot tell
  you which of its earlier signatures were made by the rightful holder.
* **Rotation is manual.** It is a script an operator runs, not a schedule. Rotation under AWS KMS is not covered by a live test.
* **Per tenant keys have soft edges.** A tenant with no key provisioned falls back to the shared default key (`default`)
  rather than failing. Under KMS, the mapping of tenant key ids to KMS names is unit tested only, not run against real AWS.
* **It is one algorithm at a time.** Rotation means a new key under the same algorithm. Switching a live deployment from
  Ed25519 to ML-DSA-65 while old records stay verifiable is not built.

## The takeaway

A key you cannot rotate is a key you will one day be unable to stop trusting. Naming the key on every signature makes
rotation boring: new records under a new id, old records under the old one, and a short list that says which ids are no
longer good for anything new.

**Read more:** [Cryptography](/cryptography/overview),
[Public keys](/sdks/parmana-sign/public-keys),
[Rotating every key in production in one day](/essays/22-rotating-every-key).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.