Damus
straycat profile picture
straycat

Key Rotation and Web of Trust: the Simplest Possible Solution to a Pressing Problem

Key rotation is an existential problem that cries out for an answer. This article outlines a simple, workable solution that uses personalized web of trust to keep track of key rotation events. We propose no new NIPs or event kinds, instead relying on the Decentralized Lists NIP to establish a simple protocol that can be expanded upon later. A Key Rotation Manager client would make an excellent entry into the upcoming web of trust hackathon!

#key rotation#nostr#wotathon#decentralized lists

I'm going to take a stab at one of the most difficult and important problems in freedom technology: key rotation. Can web of trust help? If so, how?

The canonical use case will be that of a compromised nostr nsec. Suppose Alice wakes up one morning to discover that her nsec has been compromised by a scammer who is sending DMs to all of her contacts asking for sats. She needs the community to know that this nsec is compromised, she needs to spin up a new nsec, she needs the community to know that this is her new replacement nsec, and she needs to do all of this ASAP. How does she proceed?

My guiding principle is something that deserves a name, but doesn't to my knowledge have one, so I'll just call it Occam's Design Principle:

A product should be made as simple as possible, but not simpler.

Our solution requires Alice to communicate this catastrophe to people who know her in the real world so that they can relay it to the community. So for starters, she will tell her friends Bob, Charlie, Dave, etc that her old nsec is compromised. Optionally, she will also provide them with a replacement pubkey corresponding to a new nsec, presuming she has created a new one and wishes the community to know it.

Obviously this is an imperfect solution, but there is no perfect solution, and we desire to keep things simple. Improvements will come later.

The Proposed Solution

We require no new event kinds or new NIPs, other than the Decentralized Lists Custom NIP.

Declaration of the Key Rotation Attestation List

Step 1 is to declare a new type of attestation that Bob, Charlie, Dave, etc. can use to effect the attestation described above. This only needs to be done once.

Following the Decentralized Lists NIP, this is achieved via a kind 9998 list declaration event, also called a list header:

{
  "kind": 9998,
  "tags": [
    ["names", "key rotation attestation", "key rotation attestations"],
    ["description", "This is an attestation whereby Bob, who knows Alice in the real world, can alert the community that her nsec has been compromised. There is only one required piece of data, which is the pubkey corresponding to her compromised nsec. For this, he uses the p tag. Optionally, he can also communicate a replacement pubkey, using the optional pubkey_replacement tag, presuming Alice has supplied him with one."],
    ["required", "p"],
    ["optional", "pubkey_replacement"]
  ],
  "id": "<id_key_rotation_attestation_header>"
}
Issue Key Rotation Attestations

Step 2 is for Bob to issue the attestation that Alice's old nsec has been compromised, and optionally to communicate the pubkey that she intends to replace the old one. This is accomplished via a kind 9999 event. It uses the z tag to point to the parent list header (above), the p tag to indicate the compromised account, and (optionally) the pubkey_replacement tag to indicate the new pubkey:

{
  "kind": 9999,
  "tags": [
    ["z", "<id_key_rotation_attestation_header>"],
    ["p", "<alice_pubkey_compromised>"],
    ["pubkey_replacement", "<alice_pubkey_replacement>"]
  ],
  "id": "<id_key_rotation_attestation_item>"
}
Attestation Support

Step 3 is for Charlie, Dave, etc to voice support (or rejection, as the case may be) for Bob's key rotation attestation using any one of several methods, with kind 7 reactions being the recommended method as described in the Decentralized Lists NIP:

{
  "kind": 7,
  "content": "+", // or "-" to downvote
  "tags": [
    ["e", "<id_key_rotation_attestation_item>"]
  ]
}

Alternatively, Charlie, Dave, etc could simply publish duplicate attestations using their own kind 9999 events, identical to Bob's.

Consumption

How are these attestations processed? If the end user wants to check whether alice_pubkey is valid (to the best of the community's knowledge), use this filter:

{
  "kinds": [9999],
  "#z": ["<id_key_rotation_attestation_header>"],
  "#p": ["alice_pubkey"]
}

Reactions to events returned by this filter would also be obtained with the appropriate kind 7 filter and gathered together. All of these results (kind 9999 and kind 7 events) would then be filtered or weighted based upon the end user's personalized trust metric of the event author. For starters, standard personalized PageRank or personalized GrapeRank metrics would do, easily obtained via Trusted Assertions. More sophisticated metrics might use a proximity score between Alice and the event author; authors whom Alice (previously) followed, for example, could be given the highest weighting. Perhaps Alice could even designate, ahead of time, a NIP-51 list of pubkeys that she would trust to make these attestations. But that would be work for the future; no need to support it in the initial rollout.

Future Expansions of the Protocol

Decentralized Lists provides multiple methods for future expansion of the basic Key Rotation protocol as described above. One might, for example, propose adding one or more tags alongside the p and pubkey_replacement tags. Perhaps a tag that indicates the reason for the rotation: lost, compromised, routine rotation, etc. Perhaps a tag to communicate the timestamp that the rotation is intended to take effect. The list of tags is just that: a list, that can be curated by your web of trust! In the event that multiple incompatible expansions are proposed, the community would hopefully (and probably) settle upon one or the other.

Conclusion

A client that implements the above protocol would be providing a great service to the nostr community and would lay a foundation upon which more complex protocols could evolve. In the event that a friend tells you that her account is compromised, this is the client where you would run so you could shout her predicament from the mountaintops. Such a client would therefore need a well designed interface to issue the relevant attestations and reactions. Any WoT Service Providers worth their salt would, in turn, want to listen to the output of this client and work them into their trust metrics. Therefore, such a client would want to use one or more standard methods to communicate the status of any given pubkey: Trusted Assertions, API, and/or some other method.

This would be a great contribution to the upcoming web of trust hackathon. It could be vibe coded, but ideally a team would form around an idea such as this and ensure excellent execution. And of course, I welcome ideas on how to improve this proposal. LFG!

nostr:nevent1qvzqqqqqqypzp0nm7h0qdrqasshdxjnuyuzs0my5pa0229n3elgx9227n5y5yrg2qqsgf43appp78lajjpr5fqk8fswvx87ffw97svqc6rgagzt2pw0hnrc6l7e7w