nips/41.md
2024-02-15 13:00:57 +00:00

18 KiB

NIP-41

Identity management

draft optional

This NIP introduces a reliable and verifiable solution for users to manage their identities, along with standard procedures for dealing with catastrophic cases. It also outlines the differences between simple and secure identities.

Basic concepts

  • Secured identities
    • These identities are composed of a master keypair and an active subkey.
    • The master key pair is used to derive, secure and back up subkeys, and acts as a trusted source of truth for announcements related to subkeys.
    • To derive a subkey it is recommended, but not mandatory, to use bip-32 as described in NIP-06 with the derivation path m/44'/1237'/<account>'/. This gives us HD addresses. Other derivation paths can be used if the user knows what its doing. No derivation scheme needs to be used, users can just generate random keypairs and use them, this gives users less control over subkeys.
    • The active subkey should be considered the current account in use for a master keypair, and there should only be one current subkey in use per master keypair.
    • Both the master keypair and active subkey should maintain a list of relays in common.
    • Users should follow the master keypair to stay up to date with announcements related to the active subkey or revocation certificates. However, it is not mandatory as the described conventions ensure backward compatibility. Subkeys can provide all necessary information to stay uptadate.
    • Secured identities have two possible catastrophe cases, a minor catastrophe case if a subkey is leaked, and a major catastrophe case if a master keypair is leaked.
    • Master keypairs can be stored in cold storage.
  • Simple identities
    • They are regular nostr identities that are not backed by a master keypair.
    • A simple identity can be transformed in a Secured identity by following the conventions described below.
  • Secured identities and simple identities differ from each other because secured identities master keypairs have a secure checkpoint created (event kind:1775) and a current subkey in use (event kind:1776). A subkey represents its role by adding a p tag to its kind-0, pointing to the public key of the master keypair.
    • Simple identities and master keypairs don't contain a p tag in their kind-0 to indicate that they don't belong to or are associated with other accounts.
    • Simple Identities doesn't have a published secure checkpoint event.
  • kind:1775 Secure checkpoint
    • The master key pair of Secured Identities publishes this event to provide a timestamped point at which the account can be trusted, ideally at its creation.
    • This event contains a hashed secret in its content.
    • With this secured checkpoint, and by revealing the preimage of the hash in the event of a future catastrophe case, we can establish a verifiable link between the entity that created the checkpoint and the revocation certificate.
      • This allows users to avoid having to define a new identity in advance.
    • Simple identities don't need these events, and if they create them, they can be considered as part of the transformation into a secured identity.
  • kind:1776 Key rotation announce/whitelist event.
    • Secured Identities uses these events to define the subkey it is rotating and the active subkey in use. This is considered a minor catastrophe case.
    • Simple identities uses these events to whitelist pubkeys.
    • If kind:1776, its published by a simple identity MUST be opentimestamped and SHOULD be accompanied by a kind:1777 event.
    • If kind:1776 is published by a secured identity, it needn't be opentimestamped, but it SHOULD be published by the master keypair and the subkey from which it is rotating, and the event published by the subkey SHOULD point to the event published by the master keypair using an e tag.
  • kind:1777 Key migration/Revocation certificate.
    • Revocation certificates or key migration are events that contain proofs that should be used to validate how trustworthy a new purpose identity is.
    • When a Simple Identity publishes this event, a 60-day period begins during which a user may publish a competing migration event pointing to an earlier kind:1776 event. After this period, clients SHOULD automatically update the user's follower list to the new pubkey.
    • When the master key pair of a secured identity publishes a revocation certificate, clients can check to validate the following proofs.
      • Checkpoint Proof: The client checks if a provided preimage and a secure checkpoint hash match.
      • Social proof(optional): the event contains a list of people that the master keypair attaches to the revocation certificate as p tags. These pubkeys are designated as trusted identities that can judge/signal if the new proposed identity is trustworthy or not.
        • If no social proof is required, clients can simply check the proofs provided, and if they are valid, they SHOULD automatically update the user's follower list to the new pubkey.
        • If social proof is required, a 30-day period begins during which designated users can signal whether the new identity announced in the revocation certificate is trustworthy by reacting to the revocation certificate event with a kind:7 reaction event.
        • After this period, clients SHOULD automatically update the user's follower list to the new pubkey if there is sufficient evidence to validate the trustworthiness of the new identity.
  • kind:1775 and kind:1777 MUST always be open timestamped. kind:1776 SHOULD only be timestamped if it is published by a simple identity.
  • Relays SHOULD NOT delete kind:1040, kind:1775, kind:1776, nor kind:1777 events from their database upon receiving a kind:5 event.

Flow

Creating a secured identity

Every secured identity starts as a simple identity. Then, if a simple identity wants to become a secured identity, it basically needs to publish a secure checkpoint event and then announce the subkey it's going to use.

  • Secure checkpoint event kind:1775:

    • This is an event, ideally created at the beginning when the account is created, and contains a hash of a secret that the user should define.
    • The hashing algorithm can be Argon2 or Bcrypt as they are the most used for hashing and storing passwords (TBD).
    • This event should be opentimestamped.
    • This hashed secret can be different things:
      • A user defined passphrase (best UX)
      • A user defined passphrase + salt (good UX and improved security)
      • A 12-word seed phrase (not best UX), as it can be confused with the account seed phrase.
      • Anything the user can remember or securely store to prove they were the creator of this event.
    • Checkpoint event example:
      {
      	"pubkey": "master-pubkey-A",
      	"kind": 1775,
      	"content": "hash of the secret",
      	//...
      	"tags": [
      		[ "proof", "<kind:1040-event-id>" ],
      		[ "alt", "secure checkpoint" ]
      	]
      }
      
      • pubkey is the pubkey of the master keypair is creating the checkpoint.
      • kind MUST be 1775
      • content MUST be the hashed secret.
      • proof tag MUST list the kind:1040 event that provides the Opentimestamp data.
  • Subkey announce kind:1776:

    • This event defines the subkey that will be in use.
    • Subkey announce event example
      {
      	"pubkey": "master-pubkey-A",
      	"kind": 1776,
      	"content": "",
      	"tags": [
      		[ "p", "new-subkey-pubkey" ],
      		[ "alt", "subkey announce/rotation event" ]
      	]
      }
      
      • pubkey is the pubkey of the master key pair that is announcing its active subkey.
      • kind MUST be 1776
      • content should be ignored
      • p tag is used to define the active subkey

Rotating/whitelisting a pubkey

Secured identity

The user's master keypair (e.g. master-pubkey A) and active subkey (e.g. subkey A) each publish a kind:1776 event, using a p tag to announce the subkey it's going to rotate to (e.g. subkey B).

The kind:1776 event published by the master keypair SHOULD be published first, and the event published by the active subkey SHOULD point to it using an e tag.

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

// Master keypair kind:1776 example
{
	"pubkey": "master-pubkey-A",
	"kind": 1776,
	"id" : "master-keypair-rotation-event-id",
	"content": "",
	"tags": [
		[ "p", "subkey-B" ],
		[ "alt", "subkey rotation event" ]
	]
}

// Active subkey kind:1776 example
{
	"pubkey": "subkey-A",
	"kind": 1776,
	"content": "",
	"tags": [
		[ "p", "subkey-B" ],
		[ "e", "master-keypair-rotation-event-id"]
		[ "alt", "subkey rotation event" ]
	]
}
  • .content SHOULD be ignored.
  • The events MUST have a single p tag listing the new subkey (subkey B) that the user is rotating to.
  • The event published by the old subkey (subkey A) MUST contain an e tag pointing to the event id of the master key pair rotation event.

Multiple kind:1776 events will eventually exist, and they will represent the historical record of a subkey used by a secured identity.

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

Simple identity

The user's active pubkey (e.g. pubkey A) publish an event kind:1776 whitelisting a pubkey (e.g pubkey B) 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.

{
    "pubkey": "pubkey-A",
    "kind": 1776,
    "content": "",
    "tags": [
        [ "p", "pubkey-B" ],
        [ "proof", "<kind:1040-event-id>" ],
        [ "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.

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

Migrating to a pubkey

Secured identity

If the user needs to rotate to a new subkey, they simply follow the conventions described in Rotating/whitelisting a pubkey above. This is considered a minor catastrophe case

By having a master keypair as the source of truth, users don't need to timestamp events, and clients can perform the switch to the new subkey as soon as they validate the kind:1776 events published by the master keypair and the active subkey.

Checks to validate the migration to a new subkey:

  • Verify that the kind:1776 event published by the active subkey correctly points to the master keypair, and the event can be found.
  • Verify the kind:1776 events published by the master keypair and the active subkey to validate that the new proposed subkey matches.

Purpose flow for clients:

  • Client discovers a new kind:1776 event published by a subkey.
  • Looks for the one published by the master keypair by using the e tag of the discovered event.
  • Checks if the new purposed subkey matches

Following the new subkey

Once all these checks have been validated, clients MAY choose to display a warning to the user that the identity is migrating to a new subkey. Then offer an option to replace the old subkey in the user's follower list with the new one. Or automatically update the user's follower list.

Simple identity

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

{
    "pubkey": "pubkey-B",
    "kind": 1777,
    "content": "I rolled my key using libbitcoin; moving to a new one just in case",
    "tags": [
        [ "p", "pubkey-A" ],
        [ "e", "<kind:1776-event-id>" ],
        [ "proof", "<kind:1040-event-id>" ],
        [ "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 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 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.

Migrating to a master keypair

This can only be done by secured identities, as simple identities doesn't use a master key pair.

If the user needs to migrate to a new master keypair, a new secure checkpoint must first be created with the new master keypair to be used (e.g. master-keypair B).

Then the user's active master keypair (e.g. master-keypair A) signs and timestamps a kind:1777 event containing a set of proofs as described above and announces the new master keypair (master-keypair B) to which it is migrating.

This should be done at the moment a user notices the attack, and the revocation certificate MUST contain the checkpoint proof and an i tag containing the new pubkey of the master keypair it will use (master-keypair B), and the eventid of the checkpoint event created by the new master keypair.

The active subkey SHOULD also publish a kind:1776 event without a p tag, pointing to this kind:1777 event using the e tag for backward compatibility.

Public revocation certificate event example:

{
	"pubkey": "master-pubkey-A",
	"kind": 1777,
	// Preimage for proof of checkpoint
	"content": "<preimage of the checkpoint event>",
	"tags": [
		// Checkpoint event id
		[ "e", "<master-pubkey-A-checkpoint-event-id>" ],
		// Declaring new master public key and id of checkpoint id
		[ "i", "nostr:master-pubkey-B", "<master-pubkey-B cpid>" ],
		// (optional) List of designated people to provide social proof
		["p", "witness1-pubkey"],
		["p", "witness2-pubkey"],
		["p", "witness3-pubkey"],
		// OTS
		["proof", "<kind:1040-event-id>"]
		// Relays where to look for checkpoints
		[ "relays", "relay1", "relay2" ],
		[ "alt", "revocation announce event" ]
	]
} 
  • .content MUST contain the preimage of the hash contained in the checkpoint event defined in the e tag
  • e tag MUST point to the kind:1775 checkpoint event that .content should match .
  • i tag MUST list the pubkey and event-id of the new master keypair's checkpoint.
  • p tags SHOULD list designated people who should be trusted to judge how trustworthy the new purposed identity is.
  • relays tag SHOULD list relays where both kind:1775 and kind:1040 events can be found.

At the moment the revocation certificate becomes public, clients can validate the proofs provided and, if social proof is required, a 30-day period will start during which the designated people can judge how trustworthy the new proposed identity is.

After this period, clients SHOULD prompt the user with the results or automatically update the user's follower list if the result is more than 51% of the designated people agree.

If no social proof was required and the provided proofs succeed, clients SHOULD prompt the user to switch and follow the new master key pair (master-keypair B).

Notes:

Secured identities relays:

Secured Identities Master Keypair and Subkeys SHOULD maintain the same list of relays. Subkeys can add relays, but should not delete those shared with their master keypair.

Paid relays/services:

Paid relays or services shouldn't care about master keypairs or subkeys (It is up to them if they take care of it). Active master keypairs or subkeys should subscribe to the relay/service indifferently if they want to use it.

Account search and discover-ability:

If a user searches for a master key pair, the search results will probably show the subkeys, as they have the master key pair's pubkey in their kind:0. And vice versa, if a user searches for a subkey, the search result will probably show the master keypair.

Leaked subkeys:

A leaked subkey can be any subkey that is not present in the last kind:1776 event of a master key pair. Or any subkey that has a published kind:1776 event.

Rational behind the 30/60 days delay

30 day delay

This gives designated users enough time to review and then signal/judge whether they think a revocation event kind:1777 should be considered trustworthy or not.

60 day delay

This allows enough time for a user to notice a migration request published by an attacker, and for the attacker 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. 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.