Owned by No One: Solving Nostr's Key Rotation Problem

Owned by No One: Solving Nostr's Key Rotation Problem

In Nostr, you are your key. This is beautiful in its simplicity - no company controls your identity, no support desk can lock you out, no algorithm can shadowban you. But this radical ownership comes with radical responsibility: lose your private key, and you lose everything. Get it compromised, and an attacker becomes you.

The protocol desperately needs key rotation, but previous proposals have struggled with complexity. They require pre-generated key chains, cryptographic commitments, or trusted hardware - things that most users will never set up until it's too late.

What if we could solve this with the social layer instead of the cryptographic layer?

The Problem Space

There are two distinct scenarios we need to handle:

  1. Key Compromise with Access: You discover your key is compromised, but you still have it
  2. Lost Keys: Your key is gone - device destroyed, forgotten, or otherwise inaccessible

Traditional cryptographic solutions fail the second case entirely. If you didn't pre-commit to a recovery key, you're out of luck. But Nostr already has a powerful social graph. What if we used it?

Solution 1: The Compromise Declaration

When you discover your key is compromised but still have access, you can publish a special "compromise declaration" event. This is a loud, permanent, irreversible signal that your key should no longer be trusted.

The brilliance is in what happens next: you update your profile name to [COMPROMISED] YourName. If an attacker tries to remove it, you add it back. This creates a spam war that actually helps - the very chaos of competing updates signals to everyone that something is wrong with this account.

Even if the attacker "wins" and controls the account, they're controlling an account that's been permanently marked as compromised. They've essentially vandalized their own prize.

Solution 2: Social Key Rotation

The second solution is more radical: anyone can propose that a key should rotate to a new key, and the community decides if it's legitimate through attestations.

Here's how it works:

  1. Proposal: Anyone (including you with a different key) publishes a rotation proposal
  2. Attestation: Your friends verify out-of-band (Signal, in-person, video call) and publish attestations
  3. Confidence: Clients calculate confidence based on who's attesting and how many
  4. Manual Action: Users see the attestations and manually decide whether to follow the new key

The key insight: if both the old AND new keys sign the proposal, that's strong evidence. But even without the old key (lost scenario), sufficient attestations from your social graph can establish legitimacy.

Why This Works

These solutions embrace what Nostr does well - social signaling and community verification - rather than trying to bolt on complex cryptographic schemes. They're:

  • Simple: No pre-planning or complex setup required
  • Social: Leverages existing trust relationships
  • Permanent: Creates undeletable audit trails
  • Backward Compatible: The profile name trick works on every client today
  • Antifragile: Attacks make the compromise more visible, not less

The Non-Deletable Event Range

These proposals introduce events in kinds 65533-65535, which we're proposing as permanently non-deletable. Once you declare a key compromised or propose a rotation, that record stays forever. This prevents attackers from hiding their tracks and gives the community a permanent audit trail.

Moving Forward

Perfect security doesn't exist, but perfect can be the enemy of good. These proposals offer practical, implementable solutions that work with human behavior rather than against it. They turn Nostr's social layer into a security feature.

Key rotation doesn't need to be complex. Sometimes the best solution is to admit that humans are social creatures and build systems that embrace that reality.


NIP-101: Key Compromise Declaration

draft optional

This NIP defines a method for users to permanently declare that their private key has been compromised.

Abstract

When a Nostr user's private key (nsec) is compromised but they still have access to it, they can publish a special event to warn others that the key should no longer be trusted.

Specification

Compromise Declaration Event

A compromise declaration uses event kind 65535:

{
  "id": "<32-bytes lowercase hex of the id>",
  "pubkey": "<32-bytes lowercase hex of the compromised public key>",
  "created_at": <unix timestamp>,
  "kind": 65535,
  "tags": [
    ["nonce", "<unique random value>"]
  ],
  "content": "KEY COMPROMISED - DO NOT TRUST SIGNATURES AFTER THIS TIMESTAMP",
  "sig": "<64-bytes lowercase hex of the signature>"
}

Users MAY include a Bitcoin block reference for proof-of-absence:

["block", "<bitcoin block hash>", "<block height>"]

Requirements

  1. Non-replaceable: Kind 65535 is a regular event (not replaceable)
  2. Non-deletable: Relays SHOULD ignore kind 5 deletion requests for kind 65535 events
  3. Unique nonce: Prevents replay attacks

OpenTimestamps Attestation

Users MAY publish a NIP-03 OpenTimestamps attestation (kind 1040) referencing the compromise declaration for cryptographic time proof.

Profile Update Convention

After publishing a compromise declaration, users SHOULD update their kind 0 metadata event to prepend [COMPROMISED] to their display name:

{
  "id": "<32-bytes lowercase hex of the id>",
  "pubkey": "<32-bytes lowercase hex of the public key>",
  "created_at": <unix timestamp>,
  "kind": 0,
  "tags": [],
  "content": "{\"name\":\"[COMPROMISED] Alice\",\"about\":\"Key compromised at block 850000\",\"picture\":\" https://example.com/pic.jpg\"}",
  "sig": "<64-bytes lowercase hex of the signature>"
}

This creates a visible warning even on clients that don't support this NIP.

Client Implementation

Clients supporting this NIP:

  • MUST check for kind 65535 events when displaying any user profile or content
  • MUST show a prominent warning if a compromise declaration exists
  • SHOULD display the compromise timestamp
  • SHOULD NOT automatically unfollow compromised keys

Security Considerations

  1. Attackers self-sabotage by publishing compromise declarations
  2. The spam war over kind 0 updates alerts all users
  3. Services may run bots to maintain [COMPROMISED] profile names

NIP-102: Social Key Rotation

draft optional

This NIP defines a method for rotating Nostr keys through social attestation, enabling recovery from both compromised and lost keys.

Abstract

Users can rotate from an old key to a new key through community verification. Anyone can propose a rotation, and the community provides attestations to validate it. This works even when the original private key is lost.

Specification

Event Kinds

  • 65534: Key rotation proposal (non-deletable)
  • 65533: Key rotation attestation (non-deletable)

Rotation Proposal Event

Anyone can publish a rotation proposal:

{
  "id": "<32-bytes lowercase hex of the id>",
  "pubkey": "<32-bytes lowercase hex of the proposer>",
  "created_at": <unix timestamp>,
  "kind": 65534,
  "tags": [
    ["p", "<old pubkey>"],
    ["p", "<new pubkey>"],
    ["old", "<old pubkey>"],
    ["new", "<new pubkey>"]
  ],
  "content": "Proposing key rotation for [reason]",
  "sig": "<64-bytes lowercase hex of the signature>"
}

The proposer can be the old key, new key, or any third party.

Attestation Event

Community members publish attestations:

{
  "id": "<32-bytes lowercase hex of the id>",
  "pubkey": "<32-bytes lowercase hex of the attester>",
  "created_at": <unix timestamp>,
  "kind": 65533,
  "tags": [
    ["e", "<rotation proposal event id>"],
    ["attestation", "confirm"]  // or "reject"
  ],
  "content": "Verified via [details]",
  "sig": "<64-bytes lowercase hex of the signature>"
}

MAY include: ["method", "in-person|video-call|signal|telegram|other"]

The old and new keys can also publish attestations to strengthen the signal.

Client Implementation

Clients query for kind 65534 events and fetch associated kind 65533 attestations. Calculate weight based on:

  • Both old+new keys attesting = highest confidence
  • Attestations from follows > follows-of-follows > unknown
  • More attestations = higher confidence

Never auto-follow rotated keys. Require explicit user confirmation.

Example Flow

Lost Key: Alice loses her key → creates proposal with any key → shares event ID via Signal → friends attest → others manually update follows

Compromised Key: Alice publishes proposal from old key → signs from new key → dual signature creates high confidence

Security Considerations

  • No automatic actions prevent false rotations
  • Social verification leverages existing trust
  • Sybil resistance through web-of-trust weighting
  • Non-deletable events create permanent audit trail

Relays SHOULD store kinds 65533-65535 permanently and ignore deletion requests.