Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIP-41: simple account migration #829

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions 41.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# NIP-41
## Identity recovery
pablof7z marked this conversation as resolved.
Show resolved Hide resolved
`draft` `optional` `author:pablof7z`

This NIP introduces a simple, best-effort, not guaranteed, way in which a user can notify their followers that they have migrated to a new public key in case the current one is compromised.

# Basic concepts
* `kind:1776` whitelists a pubkey.
* `kind:1777` migrates to a previously whitelisted pubkey.
* `kind:1776` and `kind:1777` MUST be opentimestamped [NIP-03](https://github.com/nostr-protocol/nips/blob/master/03.md).
* When a migration event is published, a 30-day period starts in which a user can publish a competing migration event pointing to an earlier `kind:1776` event. After this period, clients SHOULD automatically update the user's follow list to the new pubkey.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So does this mean events published with the new key aren't considered valid for 30 days? It seems like clients could eagerly respect the migration event and switch immediately to the new key, revoking that trust if a competing migration event gets published.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps 30-days is too long a time-window, but I think some delay is needed, otherwise an attacker publishing a revoking event would get exclusive control of the user's key and make things really difficult.

Adding the ability to have to rollback a migration opens a lot more complexity in my opinion, I think once a migration event is effective it should not be possible to roll it back.

But maybe 30-days is too long and this should be more like 2 weeks. Users can also use watchtowers to timestamp+publish kind:1777.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

30 days is not a long time window, in fact it is a short time window.

Clients that want to get fancy about it can follow both keys during that timeframe and add warnings to the users or something like that, as long as the result after 30 days is the same -- but these tricks don't have to be specified in the NIP.

* Relays SHOULD NOT delete `kind:1040` nor `kind:1776` events from their database upon receiving a `kind:5` event.

# Flow
## Whitelisting a pubkey
The user's active pubkey (e.g. *pubkey A*) signs an event `kind:1776` whitelisting a pubkey that can be used to migrate an identity to.

This should be done ahead of time, perhaps after a user has used Nostr enough for a few days. Clients can choose to prompt the user to "save a recovery kit" or different UXs when they see the user doesn't currently have a `kind:1776` published.

The implementation can be done directly on regular clients or microapps to handle this type of thing could be implemented as well.

```json
{
"pubkey": "pubkey-A",
"kind": 1776,
"content": "",
"tags": [
[ "p", "pubkey-B" ],
[ "alt", "pubkey whitelisting event" ]
]
}
```

* `.content` SHOULD be ignored. Users might choose to use it to leave a base64 symmetrically-encrypted message of where they left the new key or anything else.
* The event MUST have a single `p` tag listing the whitelisted pubkey.

Multiple `kind:1776` events can exist. All `kind:1776` MUST be opentimestamped following [NIP-3](https://github.com/nostr-protocol/nips/blob/master/03.md).

Relays SHOULD NOT delete `kind:1040` nor `kind:1776` events upon receiving a `kind:5` event.

## Migrating to a pubkey
When the user needs to change keys they sign an event `kind:1777` with the new key and creates a NIP-03 attestation.

```json
{
"pubkey": "pubkey-B",
"kind": 1777,
"content": "",
"tags": [
[ "p", "pubkey-A" ],
[ "e", "<kind:1776-event-id>" ],
[ "proof", "<kind:1040-event-id>" ],
[ "alt", "pubkey migration event" ],
[ "relays", "relay1", "relay2" ],
[ "mute" ]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this? I feel like this should be a client preference. or clients prompting the user when performing the migration: "also mute the old key?"

it doesn't hurt to have this here, of course, I'm just thinking that every line we can eliminate from the NIP makes is more likely to be read.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hahhaa, yeah, I debated whether to add it or not.

I'll take it out.

]
}
```

* `p` tag MUST list the previous pubkey
* `e` tag MUST list the `kind:1776` event that whitelisted the new pubkey.
* `proof` tag MUST list the `kind:1040` event that provides the Opentimestamp data of the `kind:1776` event.
* `relays` tag SHOULD list relays where both `kind:1776` and `kind:1040` events can be found.
* `mute` is optional If it's present, clients SHOULD mute the old pubkey. Users who are migrating because of a compromised key can use this to protect their followers.
* `.content` SHOULD be ignored; users can optionally write a message explaining the migration.

## Following the new pubkey

Upon seeing this event, the client MAY choose to display a warning to the user that the identity is migrating to a new key. The client should not take any automated action at this point since the migration could be an attack, but the user could communicate out of band with the user to confirm the migration.

After 30 days the client of seeing the `kind:1777` event, the client SHOULD automatically update the user's follow list to the new pubkey after some verifications:
When users who follow the old pubkey see a `kind:1777` event they SHOULD:

* check `kind:1776` and `kind:1777` event signatures
* check `kind:1777`'s `pubkey` matches `kind:1776`'s `p` tag
* check `kind:1777` is more than 30 days old
* check that no competing 1777 event exists pointing to an event with an older valid OTS proof

After validating all these checks clients SHOULD replace the old pubkey in the user's follow list with the new one.

## Notes

### Rational behind the 30 days delay
This gives enough time for a user to notice a migration request published by an attacker and gives the user enough time to publish a competing migration request pointing to an earlier `kind:1776` whitelisting event.

### Preventing unpublished evil `kind:1777` attack
Clients should keep track of when a `kind:1777` event should take into effect, counting at least 30 days from the time of seeing the event and not trusting the event timestamp. This is to prevent an attacker creating an evil `kind:1776`, its attestation, and a `kind:1777` event with its attestation and not publishing them until the 30 days of the attestation have elapsed.

#### Preventing poorly-distributed evil `kind:1777` attack
Additionally, clients SHOULD broadcast the `kind:1777` events to the relays it normally writes to. This is to prevent an attacker from creating a short-lived NIP-65 relay list where only a subset of users will see an evil `kind:1777` event but not widespread enough for the real owner to notice it.

### Future Work

Key migration can be done in multiple ways. This is an initial implementation that can work. This mechanism should be extended with other, alternative mechanisms, that can leverage different flows/tradeoffs (e.g. social recovery).
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-38: User Statuses](38.md)
- [NIP-39: External Identities in Profiles](39.md)
- [NIP-40: Expiration Timestamp](40.md)
- [NIP-41: Identity recovery](41.md)
- [NIP-42: Authentication of clients to relays](42.md)
- [NIP-45: Counting results](45.md)
- [NIP-46: Nostr Connect](46.md)
Expand Down Expand Up @@ -93,6 +94,8 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `1063` | File Metadata | [94](94.md) |
| `1311` | Live Chat Message | [53](53.md) |
| `1040` | OpenTimestamps | [03](03.md) |
| `1776` | Key Migration Whitelist | [41](41.md) |
| `1777` | Key Migration | [41](41.md) |
| `1984` | Reporting | [56](56.md) |
| `1985` | Label | [32](32.md) |
| `4550` | Community Post Approval | [72](72.md) |
Expand Down