Status: Draft. Author: Nazareno Clemente (naza@helloastro.co). Discussion: github.com/ar-agents/ar-agents/discussions. License: CC-BY-4.0.
Companions: RFC-004 (v1 HMAC operational-log spec — the base this builds on), RFC-003 (envelope that benefits most from asymmetric).
/rfcs/{n} URL. The /cite page generates BibTeX, APA and Chicago citations anchored to a commit hash automatically.1 · Why upgrade
RFC-004 v1 specifies HMAC-SHA256 with a shared symmetric secret. Three audiences hit limits with that scheme:
- Regulators.They want to verify entries offline without trusting the operator's verify endpoint. With symmetric HMAC, the operator must either share the key (kills the security boundary) or provide a server-side verify endpoint the regulator trusts (a single point of control). Asymmetric flips this: the operator publishes a public key, anyone can verify, no secret leaves the operator.
- Cross-jurisdictional counterparts (RFC-003). A Wyoming DAO LLC verifying an AR sociedad-IA's envelope needs the AR public key, not the shared secret. RFC-003 v1 punts on this; RFC-005 closes it.
- Future-proofing key rotation.Today, rotating the HMAC secret invalidates every old entry's signature unless the operator carefully re-signs. With asymmetric + key-id, old entries stay verifiable under the old public key even after rotation.
2 · Algorithm choice
Ed25519 (RFC 8032). Reasons:
- Tiny keys (32 bytes) and signatures (64 bytes). Won't bloat the entry shape meaningfully.
- Universally available in Web Crypto, Node >= 12, every modern crypto library. Same as the HMAC story.
- Deterministic by construction — same input + same key always produces the same signature. Maps onto RFC-004 § 3 (canonical- JSON + HMAC is deterministic) without surprise.
- Battle-tested. Used by every cryptocurrency, every modern SSH server, every commit-signing flow.
Not P-256. Available everywhere but less determinism guarantees + larger sigs. Not RSA. Large keys, slower verify, no determinism. Not SLH-DSA (post-quantum). Too early for v2; revisit in v3 when post-quantum signatures stabilize.
3 · Additive entry shape
v2-conformant entries carry BOTH the v1 hmac field AND a new signature field. Verifiers check whichever they can:
interface OperationalLogEntry_v2 extends OperationalLogEntry_v1 {
// v1 field (unchanged): symmetric HMAC, computed as before.
hmac: string | null;
// v2 additive field: asymmetric signature.
// Format: { keyId, alg, value }
// - keyId: stable identifier for the public key (e.g. "ar-sociedad-key-2026-05")
// - alg: "ed25519"
// - value: base64url-encoded 64-byte signature
signature?: {
keyId: string;
alg: "ed25519";
value: string;
};
}Both fields are computed over the same canonical-JSON of the entry, with BOTH the hmac and signature fields stripped before signing. Stripping rule: remove the field if present, regardless of value.
Why additive.Migration is messy. Operators can't flip overnight. Verifiers running v1-only code shouldn't break. The additive shape lets v1 + v2 coexist for as long as needed.
4 · Key publication
Operators publish their public keys at:
GET /.well-known/sociedad-ia/keys
{
"keys": [
{
"keyId": "ar-sociedad-key-2026-05",
"alg": "ed25519",
"publicKey": "MCowBQYDK2VwAyEA...", // base64url, SubjectPublicKeyInfo DER
"validFrom": "2026-05-01T00:00:00Z",
"validUntil": null // null = currently active
},
{
"keyId": "ar-sociedad-key-2025-12",
"alg": "ed25519",
"publicKey": "MCowBQYDK2VwAyEA...",
"validFrom": "2025-12-01T00:00:00Z",
"validUntil": "2026-04-30T23:59:59Z" // rotated out
}
]
}Properties:
- Keys ROTATE; old keys stay published indefinitely so historical entries remain verifiable.
- Entries reference the
keyIdthey were signed under; verifiers look it up in the keys list. - The keys endpoint is public, cacheable (15 min TTL recommended), and SHOULD be served from a stable origin (the sociedad-IA's canonical domain, not a behind-auth path).
5 · Verification flow
- Fetch the entry (e.g. from
GET /api/audit/{sessionId}). - Strip
hmac+signaturefields. Canonical-JSON-stringify (RFC-004 § 3 algorithm). - If
signaturepresent: fetch the key from/.well-known/sociedad-ia/keys, find bykeyId, verify Ed25519 against the canonical form. - If
signatureabsent +hmacpresent: fall back to v1 HMAC verification (if the verifier has access to the shared secret, e.g. for self-audit). - If both absent: the entry is unsigned. v1 + v2 production: fatal misconfiguration.
6 · Migration timeline
A sociedad-IA upgrading from v1 to v2 follows this path:
- Day 0. Generate an Ed25519 keypair. Publish the public key at
/.well-known/sociedad-ia/keys. Keep the private key in the operator's secrets manager. - Day 0 → N. Library starts emitting entries with BOTH
hmacANDsignature. Verifier endpoint accepts both. - Day N (after audit retention period). Optional: drop
hmacfrom new entries. Old entries still verifiable via stored signatures + the rotated-out keys. Most operators will keep both fields indefinitely; the cost is 100 bytes per entry.
7 · Test vectors (published)
RFC-005 v1 conformance vectors are live at /test-vectors/rfc-005-v1.json. The dataset includes:
- A fixed Ed25519 keypair (private + public, base64url + SPKI/PKCS8 DER). The same keypair is published at
/.well-known/sociedad-ia/keys(public key only). - 3 sample entries with their canonical-JSON form +
signature.valuebase64url-exact expected output, cross-validated against Node'scrypto.sign(null, msg, privateKey). - Mutation-detection vector showing that changing
output.pongfrom 1 to 2 produces a different signature.
The reference implementation lives at apps/landing/src/lib/ed25519.ts in github.com/ar-agents/ar-agents; conformance proof at apps/landing/test/rfc-005-vectors.test.ts (7 vitest tests, all passing).
8 · Open questions
- Hardware key support.Should operators be encouraged to keep the Ed25519 private key in a hardware token (YubiKey, TPM)? Verification doesn't care, but key custody is a real risk surface. RFC-005 v1 doesn't mandate; v1.1 may add SHOULD.
- Key transparency.Append-only proof that the operator hasn't equivocated about their public key (Certificate Transparency-style). Probably out of scope for v1; RFC-007 candidate.
- Cross-jurisdictional key registry. Should the AR registry, Wyoming registry, etc. publish a federated index of public keys? Centralization risk vs. enforcement utility — same trade-off as RFC-004 § 11.
- Post-quantum readiness. Ed25519 is not post-quantum-safe. When NIST finalizes SLH-DSA + ML-DSA, RFC-005 v2 will add a second signature field for parallel PQ signing during the transition period.
9 · Compatibility summary
10 · Implementation status
As of 2026-05-11, the following have shipped:
- ✓ Reference implementation primitives in
apps/landing/src/lib/ed25519.ts:signEntryAsymmetric,verifyEntryAsymmetric,fetchPublicKey. BehindAUDIT_ED25519_PRIVATE_KEYenv var. - ✓
/.well-known/sociedad-ia/keysendpoint published with one demo Ed25519 key. - ✓ Test vectors published at
/test-vectors/rfc-005-v1.jsonwith byte-exact expected signatures cross-validated against Node's native Ed25519. 7 vitest tests passing. - ✓
/certifierextended with check #7a ("RFC-005 keys endpoint advertises Ed25519 public keys"). Weight 5. Pass if >=1 key advertised; skip if endpoint 404s (v1 HMAC-only is OK). - ✓ Integration into the live
appendAuditflow — SHIPPED, VERIFIED LIVE. Production entries on the reference deployment now carry bothhmac+signature(RFC-005 § 3 wire shape). WhenAUDIT_ED25519_PRIVATE_KEYis set in Vercel env, everyappendAuditcall computes both. Confirmed by a live/api/playsession: 3-of-3 entries reportedsignedAsymmetricVerified: 3alongsideverified: 3, tampered: 0. - ✓ HMAC strip rule fix (round 22 finding): the original
signEntrystripped onlyhmac; the dual-sign integration revealed thatsignaturealso needs to be stripped before canonical-JSON so HMAC-and-Ed25519 are computed over the same input space. Now: both strip both. 4 new regression tests inaudit.test.ts. - ◐ Public review period via GitHub Discussions — open, no fixed end date for v1 finalization.
Comments + counter-proposals welcome.