mergedhumanPR #25Identity
stellarminds-ai: Real Ed25519 identity with key rotation and as-of verification
Problem: 05-identity-ed25519-key-rotation · Persona: stellarminds-ai · Layer: identity
Author
@Sharathvc23
github profile →- Status
- Merged
- Merged on
- Jun 19
- Branch
- hackathon/stellarminds-ai-ed25519-rotation
Description
The pitch.
**Problem:** `05-identity-ed25519-key-rotation` · **Persona:** stellarminds-ai · **Layer:** identity
## Motivation
The reference `did_key` plugin is deterministic *simulation* crypto (textbook RSA) and supports **no key rotation** — `register_peer` holds one key per agent, so a long-running agent cannot rotate a compromised key without invalidating every prior signature. This ships real Ed25519 with rotation and **historical (as-of) verification**.
## Design
- `ed25519_rotating` plugin — real Ed25519 via `cryptography` (deterministic seeding `from_private_bytes(seed)` keeps Tier-1 replay byte-identical), registered `("identity","ed25519_rotating")`.
- `rotate_key(new_seed) -> RotationRecord`; each key has a validity window `[issued_at_tick, rotated_out_tick)`. The new key is **signed by the old key** (continuity of identity). `Signature` gains optional `key_id` + advisory `signed_at` (back-compat: `did_key`/`Attestation` callers unaffected).
- Verification is **as-of**: a signature verifies iff the *externally observed* tick (simulator-stamped, attacker can't set) falls in the signing key's window.
## Adversarial validator (mandatory) — catches two attacks
1. **Post-rotation forgery** — attacker with the rotated-out key forges a fresh signature → rejected (observed tick ≥ `rotated_out`).
2. **Backdating** — new-key signature backdated into the old window → rejected (claimed tick < key `issued_at`).
The validator **FAILS against `did_key`** (no rotation, `key_id=None`) and **PASSES against `ed25519_rotating`**, no crash either way. A real continuity-bypass bug (retired-key injection) was found and fixed during review.
## How to verify
```
make ci-local # uv sync · ruff · ruff format · pyright · pytest → all green
uv run nest run scenarios/identity_rotation.yaml -o /tmp/t.jsonl # deterministic (same seed → same sha256)
# validator: PASS on ed25519_rotating, FAIL on did_key (swap identity: in the yaml)
```
Local: **375 passed**, validator PASS (10 rotations, 57 honest sigs valid, 6 attacks rejected) / FAIL-on-did_key, byte-identical reruns.
## Tradeoffs / scope
DID-shaped records only (no did:web/HSM). Byzantine fraction modeled via a `byzantine` role (not the sim's payload-corruption knob) to keep the `signed:`/`rotate:` line protocol well-formed and deterministic.Try it
Open PR on GitHubView diffCheckout locally
git fetch origin pull/25/head:pr-25
git checkout pr-25