Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Native library reference. Extended CLI examples use jacs-compat. This source reference can include unreleased changes; see the package guide for installation and MCP profiles for available tools.

Key Rotation

Key rotation is the process of replacing an agent's cryptographic keys while preserving the ability to verify documents signed with previous keys. JACS implements version-aware key management to support secure key lifecycle operations.

Why Key Rotation Matters

Key Compromise Recovery

When a private key is compromised, the agent must be able to:

  • Generate new keys and continue operating
  • Revoke trust in the compromised key
  • Maintain verifiability of documents signed before the compromise

Cryptographic Agility

Cryptographic algorithms evolve. Key rotation enables:

  • Migration from older algorithms to newer ones
  • Transition to post-quantum cryptography when needed
  • Algorithm upgrades without breaking existing signatures

Migrating Ed25519 Agents to pq2025

Native rotation without --algorithm preserves the current algorithm. Upgrade an Ed25519 identity explicitly:

jacs-compat agent rotate-keys --algorithm pq2025
  • An Ed25519 identity can replace its key with Ed25519 or explicitly upgrade to pq2025; the transition proof is signed by its previous key.
  • A pq2025 identity cannot downgrade to Ed25519.
  • Until it rotates, an Ed25519 agent keeps signing normally with Ed25519.
  • Documents signed by the old Ed25519 key remain verifiable after migration (see Cross-Algorithm Verification in the Algorithm Selection Guide).
  • Rotation supersedes the ES256 compatibility key binding: the binding is signed by the native root, so after rotation ecosystem exports fail with a "re-issue" error until jacs-compat agent issue-compat-binding runs under the new native root.
  • Rotation applies to the native root only — rotating the ES256 compatibility key itself is out of scope in P2.

Compliance Requirements

Many security standards require periodic key rotation:

  • PCI-DSS mandates regular key changes
  • SOC 2 requires key management policies
  • NIST guidelines recommend rotation schedules

Agent Versioning

JACS uses a versioned identity model where each key rotation creates a new agent version.

Version Format

Agent identifiers follow the format: {agent_id}:{version_uuid}

  • jacsId: The stable agent identity (UUID v4) - never changes
  • jacsVersion: Current version UUID - changes on each update
  • jacsPreviousVersion: Links to the prior version
  • jacsOriginalVersion: The first version ever created
{
  "jacsId": "550e8400-e29b-41d4-a716-446655440000",
  "jacsVersion": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "jacsPreviousVersion": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
  "jacsOriginalVersion": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
}

Version Chain

Each version forms a linked chain back to the original:

Original (v1) <-- Previous (v2) <-- Current (v3)
   |                 |                  |
 key-A             key-B              key-C

This chain provides an audit trail of all key changes and allows verification of any version.

Version-Aware Verification

The critical insight enabling key rotation is that signatures contain both the agent ID and the version that created them.

Signature Structure

{
  "jacsSignature": {
    "agentID": "550e8400-e29b-41d4-a716-446655440000",
    "agentVersion": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
    "publicKeyHash": "sha256-of-public-key-A",
    "signingAlgorithm": "ring-Ed25519",
    "signature": "base64-encoded-signature",
    "date": "2024-01-15T10:00:00Z"
  }
}

Key Resolution Process

When verifying a signature:

  1. Extract agentVersion and publicKeyHash from the signature
  2. Look up the public key that was active for that version
  3. Verify the signature using that historical key
#![allow(unused)]
fn main() {
// Pseudocode for version-aware verification
fn verify_signature(doc: &Document) -> Result<()> {
    let sig = &doc.jacs_signature;

    // Find the key that was active for this version
    let public_key = resolve_key_for_version(
        &sig.agent_id,
        &sig.agent_version,
        &sig.public_key_hash,
    )?;

    // Verify with the historical key
    verify_with_key(&doc, &sig, &public_key)
}
}

Key Lookup Priority

Native external-document verification uses the configured JACS_KEY_RESOLUTION sources (default local,registry). An opted-in dns source fetches the exact signed version's key over HTTPS and pins it to the raw-key DNS fingerprint, so old documents verify through DNS only while their fingerprint and exact-version key endpoint stay published.

Key Rotation Process

Step-by-Step Rotation

  1. Generate new key pair with the desired algorithm
  2. Create new agent version with updated key information
  3. Sign new version with old key (transition signature)
  4. Update DNS records to include new key fingerprint
  5. Store old public key for future verifications

CLI Commands

# Rotate keys with default algorithm
jacs-compat agent rotate-keys

# Rotate to post-quantum algorithm
jacs-compat agent rotate-keys --algorithm pq2025

# List key history (active and archived keys)
jacs-compat agent keys-list

# Repair config after a crash during rotation
jacs-compat agent repair

Transition Signature

During key rotation, JACS produces a cryptographic transition proof that binds the old key to the new key. This proof is embedded in the agent document as jacsKeyRotationProof:

{
  "jacsKeyRotationProof": {
    "transitionMessage": "JACS_KEY_ROTATION:{agent_id}:{old_key_hash}:{new_key_hash}:{timestamp}",
    "signature": "base64-encoded-signature-with-old-key",
    "signingAlgorithm": "ring-Ed25519",
    "oldPublicKeyHash": "sha256-of-old-key",
    "newPublicKeyHash": "sha256-of-new-key",
    "timestamp": "2026-04-07T10:00:00Z"
  }
}

The transition message is signed with the old private key before it is archived. This proves:

  • The rotation was authorized by the holder of the previous key
  • The old and new keys are cryptographically linked
  • An attacker cannot forge a rotation without the old private key

Agent::verify_transition_proof() validates the detached old-key signature. Registries and directories must use Agent::verify_transition_proof_for_rotation(proof, expected_agent_id, old_key, new_key) instead. That stricter API also binds the proof to the expected stable identity and exact candidate new key, preventing proof transplantation.

Crash Recovery

JACS uses a write-ahead journal to recover from crashes during key rotation. Before rotation begins, a journal file is written to {key_directory}/.jacs_rotation_journal.json. The journal tracks the rotation stage:

  1. started - Rotation initiated
  2. keys_rotated - New keys generated, old keys archived
  3. agent_saved - New agent version saved to disk
  4. config_signed - Config re-signed with new key (journal deleted on success)

If the process crashes mid-rotation, the next agent load detects the journal and automatically repairs the config by re-signing it with the current key. No manual intervention is required for the common case.

For manual recovery: jacs-compat agent repair

Cross-Algorithm Rotation

An Ed25519 root can explicitly upgrade to pq2025. Rotation without an override preserves the current algorithm; PQ-to-Ed25519 downgrade is rejected:

# Rotate from Ed25519 to post-quantum
jacs-compat agent rotate-keys --algorithm pq2025
#![allow(unused)]
fn main() {
// Rust API
let result = advanced::rotate(&agent, Some("pq2025"))?;
}
# Python
result = client.rotate_keys(algorithm="pq2025")
// Node.js
const result = await client.rotateKeys({ algorithm: 'pq2025' });

After cross-algorithm rotation, the config file's jacs_agent_key_algorithm field is updated atomically. Documents signed before the rotation remain verifiable using the archived old key.

Version transition

Rotation retains jacsId, assigns a new jacsVersion and jacsVersionDate, links jacsPreviousVersion, and embeds jacsKeyRotationProof. A document signed before rotation still identifies its original agent version and key hash. Retain that independently trusted public key to verify the older document; there is no on-document jacsKeyHistory revocation registry.

Trust Store with Version History

Retain independently trusted public keys for each exact agent_id:version. UUID versions are identifiers, not ordered ranges; do not infer key validity from UUID comparison.

DNS and key versions

Agent-specific native lookup accepts overlapping fingerprints for one agent and records for multiple agents. Each record uses the actual format:

v=jacs; jacs_agent_id=<agent-uuid>; alg=SHA-256; enc=hex; jac_public_key_hash=<raw-key-sha256>; uri=https://keys.example.com/jacs/v1/agents/<agent-uuid>/keys/<version-uuid>

A cross-origin URI requires an explicitly configured JACS_KEYS_BASE_URL. Publish distinct raw-key fingerprints and exact-version endpoints during an overlap. Conflicting URIs for the same agent and fingerprint are rejected. jacs-compat agent dns generates the configured identity's record; it does not publish changes or provide an --all-keys export. The DNS record does not implement ver, valid_until or revocation semantics. Keep historical keys available and enforce revocation in application policy. There is no universal rotation interval of twice the TTL: account for caches and retained documents. See DNS trust anchoring and the key discovery guide for signed-reference compatibility and verifier boundaries.

Security Considerations

Key Revocation

When a key is compromised:

  1. Revoke the key in the relying application's trust policy
  2. Update DNS to remove discovery records for the compromised key; DNS has no revocation-status field
  3. Reject revoked keys in verification policy; cryptographic signature validity alone does not enforce revocation
  4. Notify trusted peers if possible

Secure Deletion

After rotation:

  • Old private keys should be securely deleted
  • Only public keys are retained for verification
  • Key metadata must be protected from modification

Best Practices

Rotation Schedule

  • Regular rotation: Quarterly or annually for compliance
  • Algorithm upgrade: When transitioning to stronger cryptography
  • Incident response: Immediately after suspected compromise

Pre-Rotation Checklist

  • Backup current agent state
  • Verify all systems can handle new key format
  • Plan DNS propagation time
  • Notify dependent systems of upcoming change

Post-Rotation Checklist

  • Verify new key is active
  • Confirm old documents still verify
  • Update DNS records
  • Securely delete old private key
  • Test signing with new key
  • Re-issue the compatibility key binding (jacs-compat agent issue-compat-binding) if the agent has an ES256 compatibility key — ecosystem exports fail until the new native root signs a fresh binding

See Also