From b3920f76b4f8adde785de785153b49e92be75f35 Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Wed, 18 Oct 2023 14:57:30 +0300 Subject: [PATCH 01/10] wip --- 41.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 41.md diff --git a/41.md b/41.md new file mode 100644 index 0000000000..7ab54c794a --- /dev/null +++ b/41.md @@ -0,0 +1,88 @@ +# NIP-41 +## Identity rotation +`draft` `optional` `author:pablof7z` + +This NIP introduces a simple way in which a pubkey can migrate to by whitelisting a new pubkey ahead of time. + +# 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. +* 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", "" ], + [ "proof", "" ], + [ "alt", "pubkey migration event" ], + [ "relays", "relay1", "relay2" ] + ] +} +``` + +* `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. +* `.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. From 3b1d74e116230e7f37effd108536943557633472 Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Thu, 19 Oct 2023 11:04:46 +0300 Subject: [PATCH 02/10] update README --- 41.md | 10 +++++++--- README.md | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/41.md b/41.md index 7ab54c794a..5c6d8017d4 100644 --- a/41.md +++ b/41.md @@ -76,13 +76,17 @@ When users who follow the old pubkey see a `kind:1777` event they SHOULD: After validating all these checks clients SHOULD replace the old pubkey in the user's follow list with the new one. -### Notes +## Notes -#### Rational behind the 30 days delay +### 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 +### 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). \ No newline at end of file diff --git a/README.md b/README.md index e9f08bdba5..9d7f4fb8b7 100644 --- a/README.md +++ b/README.md @@ -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 rotation](41.md) - [NIP-42: Authentication of clients to relays](42.md) - [NIP-45: Counting results](45.md) - [NIP-46: Nostr Connect](46.md) @@ -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) | From 9e15edba1c3508cc89a54ce4b1f144c2e72b463b Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Thu, 19 Oct 2023 11:50:05 +0300 Subject: [PATCH 03/10] add optional mute tag --- 41.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/41.md b/41.md index 5c6d8017d4..a1815189b6 100644 --- a/41.md +++ b/41.md @@ -51,7 +51,8 @@ When the user needs to change keys they sign an event `kind:1777` with the new k [ "e", "" ], [ "proof", "" ], [ "alt", "pubkey migration event" ], - [ "relays", "relay1", "relay2" ] + [ "relays", "relay1", "relay2" ], + [ "mute" ] ] } ``` @@ -60,6 +61,7 @@ When the user needs to change keys they sign an event `kind:1777` with the new k * `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 From b483eb8b7b17ad16fb2e56942b8d4ce842a8ca6d Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Thu, 19 Oct 2023 18:40:52 +0700 Subject: [PATCH 04/10] Update 41.md Co-authored-by: fiatjaf_ --- 41.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/41.md b/41.md index a1815189b6..6d24b32f1d 100644 --- a/41.md +++ b/41.md @@ -1,5 +1,5 @@ # NIP-41 -## Identity rotation +## Identity recovery `draft` `optional` `author:pablof7z` This NIP introduces a simple way in which a pubkey can migrate to by whitelisting a new pubkey ahead of time. From 651be3778f63ef72eafb06c3ec843493e38fd603 Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Thu, 19 Oct 2023 18:41:41 +0700 Subject: [PATCH 05/10] Update 41.md Co-authored-by: fiatjaf_ --- 41.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/41.md b/41.md index 6d24b32f1d..ad50400f0e 100644 --- a/41.md +++ b/41.md @@ -2,7 +2,7 @@ ## Identity recovery `draft` `optional` `author:pablof7z` -This NIP introduces a simple way in which a pubkey can migrate to by whitelisting a new pubkey ahead of time. +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. From d6074050e65cbf6ae7bbf27a0e834a5c91abf8d0 Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Thu, 19 Oct 2023 14:44:45 +0300 Subject: [PATCH 06/10] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d7f4fb8b7..e8dc85b272 100644 --- a/README.md +++ b/README.md @@ -50,7 +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 rotation](41.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) From b86ad6f627114961f4c676edafc8194a449fbdab Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Thu, 19 Oct 2023 16:44:42 +0300 Subject: [PATCH 07/10] mute `mute` --- 41.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/41.md b/41.md index ad50400f0e..2783903fc6 100644 --- a/41.md +++ b/41.md @@ -51,8 +51,7 @@ When the user needs to change keys they sign an event `kind:1777` with the new k [ "e", "" ], [ "proof", "" ], [ "alt", "pubkey migration event" ], - [ "relays", "relay1", "relay2" ], - [ "mute" ] + [ "relays", "relay1", "relay2" ] ] } ``` @@ -61,7 +60,6 @@ When the user needs to change keys they sign an event `kind:1777` with the new k * `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 From 30dd53b51baf96cd257802e26ea8dfb97d7b086c Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Fri, 20 Oct 2023 14:13:31 +0700 Subject: [PATCH 08/10] Update 41.md Co-authored-by: fiatjaf_ --- 41.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/41.md b/41.md index 2783903fc6..0f00c22e5d 100644 --- a/41.md +++ b/41.md @@ -1,5 +1,5 @@ # NIP-41 -## Identity recovery +## Key migration `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. From 68b27f6574051fbe6ffbfb652bf3abfbb10b73c7 Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Fri, 20 Oct 2023 10:21:35 +0300 Subject: [PATCH 09/10] increase time delay to 60-days --- 41.md | 16 +++++++--------- README.md | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/41.md b/41.md index 0f00c22e5d..16425905b2 100644 --- a/41.md +++ b/41.md @@ -1,6 +1,6 @@ # NIP-41 ## Key migration -`draft` `optional` `author:pablof7z` +`draft` `optional` `author:pablof7z` `author:fiatjaf` 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. @@ -8,7 +8,7 @@ This NIP introduces a simple, best-effort, not guaranteed, way in which a user c * `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. +* When a migration event is published, a 60-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. * Relays SHOULD NOT delete `kind:1040` nor `kind:1776` events from their database upon receiving a `kind:5` event. # Flow @@ -45,7 +45,7 @@ When the user needs to change keys they sign an event `kind:1777` with the new k { "pubkey": "pubkey-B", "kind": 1777, - "content": "", + "content": "I rolled my key using libbitcoin; moving to a new one just in case", "tags": [ [ "p", "pubkey-A" ], [ "e", "" ], @@ -63,30 +63,28 @@ When the user needs to change keys they sign an event `kind:1777` with the new k * `.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: +After 60 days 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 `kind:1777` is more than 60 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 +### Rational behind the 60 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. +Clients should keep track of when a `kind:1777` event should take into effect, counting at least 60 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 60 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). \ No newline at end of file diff --git a/README.md b/README.md index e8dc85b272..e6894ac761 100644 --- a/README.md +++ b/README.md @@ -50,7 +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-41: Key migration](41.md) - [NIP-42: Authentication of clients to relays](42.md) - [NIP-45: Counting results](45.md) - [NIP-46: Nostr Connect](46.md) From b6a524db0e41e0d8f0452faee42eded51eea9a56 Mon Sep 17 00:00:00 2001 From: Pablo Fernandez Date: Thu, 16 Nov 2023 19:11:46 +0000 Subject: [PATCH 10/10] justice --- 41.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/41.md b/41.md index 16425905b2..9260e97a03 100644 --- a/41.md +++ b/41.md @@ -1,6 +1,6 @@ # NIP-41 ## Key migration -`draft` `optional` `author:pablof7z` `author:fiatjaf` +`draft` `optional` `author:pablof7z` `author:fiatjaf` `author:nvk` 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. @@ -87,4 +87,4 @@ Clients should keep track of when a `kind:1777` event should take into effect, c 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). \ No newline at end of file +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).