Skip to content

Conversation

@staab
Copy link
Member

@staab staab commented Nov 25, 2025

This NIP was sketched out in a session at nostr.xxx. It's based on @pablof7z's original migration proposal with some elements from #2114.

Differences from prior art:

  • There is no holding period of 30-60 days. Migration events can be validated immediately.
  • Instead of migrating directly from the parent to the successor, an intermediate, single-use migration key is introduced. This can be stored however a user prefers, but it's recommended to use social key recovery with shamir secret sharding, which prevents single points of failure in the user's backup strategy.
  • Migration is only used to signal to clients that users should update their follow lists (and mutes, follow packs, etc), NOT establish a live link between an old key and a new key (or its successors). This means that migrations mean mentions etc are not maintained, messages are lost, etc., but implementation is much less onerous (and can be done manually by users as well).

Important downsides:

  • The worst case scenario occurs when an attacker gets key material and the user hasn't yet published a precommit, in which case the attacker can execute the migration flow himself. This is worse than the status quo, since currently users retain the ability to spam an identity. For this reason, migration should always be presented to a user with context, not automatically implemented. Additional affordances, like migration attestations (where web of trust is used to validate the authenticity of a migration) might be added to buttress user certainty.
  • There is no recourse for all key material being lost. Social key recovery on its own compromises the integrity of keys as a root identity, which I think is a bridge too far. However, informal migration is still possible on the social layer.
  • This NIP relies on a central group of trusted relays to guarantee precommit availability and event validation (ordering is guaranteed by OTS, but not completeness). I would be interested in a proposal to put precommits on a blockchain directly in order to remove this flaw. An OP_RETURN in the form of <40 bytes of pubkey 1><40 bytes of pubkey 2> might suffice.

@fiatjaf
Copy link
Member

fiatjaf commented Nov 26, 2025

Can't we soften the need for the central group of trusted relays by enforcing a migration period during which the legitimate owner who just got his keys stolen can find his older timestamped event (which might be stored somewhere or published on niche relays no one remembered to check) and republish it (to the new relays people are checking)?

@staab
Copy link
Member Author

staab commented Nov 26, 2025

I think that only makes things less clear. Having the requirement that the event is immediately available forces us to solve the problem of where to put the events. Anyway, where would they publish the event to once they find it? It's the same problem.

@fiatjaf
Copy link
Member

fiatjaf commented Nov 26, 2025

In the current situation what is the set of relays that everybody has to agree upon?
relay.damus.io, nos.lol, relay.primal.net? Will that remain the canonical set forever? We can't know. Maybe these 3 become unresponsive or delete the events overtime, how are we going to agree on the new set of canonical relays? And if we change, what happens with people that had published their events to these?


Now if we have the period clients can choose the set of relays where to look for these events much more flexibly. And the waiting period is large enough so people who lost their keys can get notified (for example, by their clients that will display some notice, or by their friends who have clients that will display something). And in these notices there will be the name of the relays where the migration event was seen (say, relay.facebook.com and relay.google.com, because 20 years have passed and Nostr is very big and these big companies are the ones running the biggest relays). Then people can go find their events and publish them to relay.facebook.com and relay.google.com, then the situation automatically fixes itself.


Of course this kind of a shitty solution, and maybe it's broken, but I think it's less bad than picking a set of relays now and trusting them forever.

@staab
Copy link
Member Author

staab commented Nov 26, 2025

relay.damus.io, nos.lol, relay.primal.net

We need something similar to promenade coordinators/signers, or indexer relays like purplepag.es. These are relays whose owners are trusted, and which can be relied upon to have a complete record of migration events. Change can happen over time because we should really have like 10+ of these relays, so if one goes offline events are available elsewhere, and people who are hard-coding these urls (or maintaining lists) can migrate. The relays should replicate content using negentropy, so if someone doesn't publish to all relays, the event gets propagated anyhow.

The waiting period creates poor UX, where someone's account is in limbo for a pretty long time. This is at least annoying to users who want to migrate and forget about it, but especially bad if an attacker has their key and they can't dissociate themselves immediately.

@staab staab mentioned this pull request Nov 26, 2025

For each `migration` key committed to in a `kind 360` event, use the [codex32 standard](https://secretcodex32.com/) for Shamir secret sharing to split the key into `n` shards.

For each shard, create a `kind 362` event with a `p` tag indicating the original user's pubkey, and a `shard` tag containing the shard. This event MUST NOT be signed, but MUST be wrapped following [NIP 59](59.md).
Copy link
Member

Choose a reason for hiding this comment

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

This is missing the symmetric encryption; shard-holders shouldn't be trusted to not collude with key material.

This sounds harder than it is; all this means is that the payload should be encrypted symmetrically before sharding.

Copy link
Member Author

Choose a reason for hiding this comment

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

I remember you mentioning that, can you elaborate? Encrypted with what key? If the original user private key, then this doesn't work for recovering lost key material. If another key, it's another thing to save. Also, this bit is just a recommendation for a sane default, it does rely on holders not colluding, but other strategies for key storage can be used for advanced users.

Copy link
Member

Choose a reason for hiding this comment

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

Just a password; not a key. Everybody and their mother have some shitty password that adds an extra layer of (optional?) protection.


These risks can be mitigated (but not solved) in classically nostr fashion by spreading trust across a large number of `migration` relays. These relays MUST be independently run, and their owners MUST have an incentive to prevent account theft, which can only be assessed manually. All of these relays would have to collude in order to prevent a correct migration from occurring.

However these relays are chosen, the entire network MUST use the same set. Network partitioning is unacceptable in this case. Selection of actual relays is left to the nostr community.
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is necessary; all we need is that relays that signal support for this NIP:

  • don't allow backdated events
  • don't allow NIP-9 deleting 36x events

Copy link
Member Author

Choose a reason for hiding this comment

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

But subjectivity breaks the whole thing. If I publish my precommit to relay A, and an attacker publishes to relay B, anyone who asks relay B and not relay A will get the attacker's precommit instead of my own. This allows an attacker to potentially MITM migration by running a migration relay. You could select relays based on wot, maybe with some whitelisted trusted pubkeys, but that's just more steps to introduce a similar level of centralization.

@pablof7z
Copy link
Member

Hadn't we softly reserved NIP-41 to be used for this identity migration thing?

@pablof7z
Copy link
Member

I don't think the "only use the first 360 event is a good idea (nor possible without centralizing on X relays).

What if the user changes their mind about opting out or lose the key to the migration pubkey?

Also, why the need for an in-between migration pubkey? Not sure what's the benefit of that; why not just whitelist the next pubkey instead of a migration event pubkey?

@pablof7z
Copy link
Member

Is this missing attestation? How do followers attest to "I verified out-of-band the person really changed pubkeys"? I think it'd be valuable to
Have this as an explicit action; not just a change in the kind:3 of people. Like if my key is compromised and I roll onto the new one I would call @dergigi and @fiatjaf and others that I'm close with to get them to attest and give a clear social weight to that migration event. They could publish it, even as a kind:1 with some tags, confirming the OOB check.

@staab
Copy link
Member Author

staab commented Dec 2, 2025

Hadn't we softly reserved NIP-41 to be used for this identity migration thing?

Renamed

What if the user changes their mind about opting out or lose the key to the migration pubkey?

Then they're out of luck. It's a little bit of a bummer, but only brings us back to the status quo for that key, and keeps complexity down. Sharding should make it difficult to lose the migration key.

Also, why the need for an in-between migration pubkey? Not sure what's the benefit of that; why not just whitelist the next pubkey instead of a migration event pubkey?

This allows the user to migrate even if he loses his primary pubkey. It also follows the principle of least privilege. Plus NVK said it was a good idea, and if there's one thing I've learned it's to always follow his advice (unless it's related to beards or bare feet, or most other things).

Is this missing attestation?

What do you think about recommending kind 1111 comments and/or 1984 reports on precommits and migration events? That would allow for free form context, as well as explicit flagging of events published by an attacker. This would be similar to #2139

@fiatjaf
Copy link
Member

fiatjaf commented Dec 2, 2025

This allows the user to migrate even if he loses his primary pubkey. It also follows the principle of least privilege. Plus NVK said it was a good idea, and if there's one thing I've learned it's to always follow his advice (unless it's related to beards or bare feet, or most other things).

This is a bad argument as NVK's advice is always bad, but also if the user has the next secret key why not use that?

The migration key adds unnecessary complication.

Why can't we just presign the migration event with the old key pointing to the next key, OTS it, then take that signed event, encrypt it with the next key and store it on relays. Then if in the future you lose your old key but you still have the next key you decrypt that old presigned event and publish it.

@fiatjaf
Copy link
Member

fiatjaf commented Dec 2, 2025

If the act this presigned event (and reposting somehow so it doesn't get buried because of the old created_at) creates a discussion thread that allows people to add other attestations and comment, but also immediately click a button to update their follow lists.

The discussion gives people some (undefined) time to recover older events and republish them to expected relays to overrule attackers and so on.

@staab
Copy link
Member Author

staab commented Dec 2, 2025

Why can't we just pre-sign the migration event with the old key pointing to the next key

This means that the user has to generate the next key eagerly and store it securely, which exposes the successor key to the same failure case as the primary key. The migration key allows for generating a successor key on demand without naming it in advance, allowing people to mess up and still recover. We could shard the successor key and share it, but then we're exposing a general-purpose key to whatever risks the backup solution has forever, instead of just the migration key which becomes obsolete once used.

The discussion gives people some (undefined) time to recover older events and republish them to expected relays to overrule attackers and so on.

Yeah, a time delay as a heuristic is probably fine. I just didn't want to enforce some arbitrary time window. I would put comments on the migration event, rather than the precommit for the reason you mentioned. The precommit is the necessary condition for migration, the migration event is the actual trigger.

@fiatjaf
Copy link
Member

fiatjaf commented Dec 2, 2025

Why can't we just pre-sign the migration event with the old key pointing to the next key

This means that the user has to generate the next key eagerly and store it securely, which exposes the successor key to the same failure case as the primary key. The migration key allows for generating a successor key on demand without naming it in advance, allowing people to mess up and still recover. We could shard the successor key and share it, but then we're exposing a general-purpose key to whatever risks the backup solution has forever, instead of just the migration key which becomes obsolete once used.

That's a good argument.

@pablof7z
Copy link
Member

pablof7z commented Dec 2, 2025

Why can't we just pre-sign the migration event with the old key pointing to the next key

This means that the user has to generate the next key eagerly and store it securely, which exposes the successor key to the same failure case as the primary key. The migration key allows for generating a successor key on demand without naming it in advance, allowing people to mess up and still recover. We could shard the successor key and share it, but then we're exposing a general-purpose key to whatever risks the backup solution has forever, instead of just the migration key which becomes obsolete once used.

That's a good argument.

Yeah, that's a good point.

@vitorpamplona
Copy link
Collaborator

Can we design this NIP from the standpoint of having a vault-like type of client? Just like we have Signer Apps today, we could have a separate category of clients that only do the key migration itself, storing things properly, and keeping the user's main rotation information safe.

So, instead of being something every client needs to eventually code, make it in such a way that users need to pick a Vault client. This would ease the pressure on keeping things simple for clients and allow you to take key safety to the next level.

Basically, nobody but Vault clients should code this. Then they can become hyper-specialized in it and minimize coding errors.

@pablof7z
Copy link
Member

pablof7z commented Dec 2, 2025

Can we design this NIP from the standpoint of having a vault-like type of client? Just like we have Signer Apps today, we could have a separate category of clients that only do the key migration itself, storing things properly, and keeping the user's main rotation information safe.

So, instead of being something every client needs to eventually code, make it in such a way that users need to pick a Vault client. This would ease the pressure on keeping things simple for clients and allow you to take key safety to the next level.

Basically, nobody but Vault clients should code this. Then they can become hyper-specialized in it and minimize coding errors.

Yes, but, social clients would need to code the part where they see the migration signaling events for all this to work; that said, the could just show a warning or something and prompt the user to go to some other app to take care of it.

@vitorpamplona
Copy link
Collaborator

social clients would need to code the part where they see the migration signaling events for all this to work

If that is a requirement, this PR is doomed from the start. We have to figure out a way of doing this that doesn't require regular clients to participate because, most of the time, they won't have the time for this.

@staab
Copy link
Member Author

staab commented Dec 2, 2025

Can we design this NIP from the standpoint of having a vault-like type of client?

This is an implementation detail. Nothing in this NIP requires any client to do anything at all, since doing nothing is no worse than the status quo. Clients can implement as much or as little of this as they want, and special-purpose clients which advertise themselves via 31990 will probably end up existing.

@vitorpamplona
Copy link
Collaborator

This is an implementation detail.

NIPs only contain implementation details. Several NIPs declare types of clients to make things semantically easier for users to understand which app is supposed to do what, lining up expectations for everybody. I particularly don't want to see users asking their preferred clients to implement this because I know that implementation will have more bugs than the status quo, and we will have a security nightmare to deal with, which can affect not only that client but Nostr itself as unsecured.

@vitorpamplona
Copy link
Collaborator

To emphasize this, I think in the same way that we tell people to never put their nsecs in any client, we should tell users to never do any migration function in a regular client.

@staab
Copy link
Member Author

staab commented Dec 2, 2025

You're being too prescriptive. If it helps though, I could put the following in the NIP: "clients that implement this NIP SHOULD NOT screw it up."

@staab
Copy link
Member Author

staab commented Dec 2, 2025

we will have a security nightmare to deal with

Do you have a particular scenario in mind?

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Dec 2, 2025

Do you have a particular scenario in mind?

So many things can go wrong here:

  • Clients not checking OTS or checking incorrectly.
  • Clients not storing migration information correctly and leaking access to the other keys.
  • Clients trying to migrate all the account info from one key to another, establishing a link in some other way
  • Clients developing trusted server-side components like watch-towers that can be new avenues of attack
  • Sharding incorrectly and revealing more information about the migration than what it is supposed to.

Remember, lots of clients don't even verify events coming from relays. The bar is REALLY low on Nostr.

If too many bugs get prominent, people might associate Nostr with insecure payloads and give up on the protocol entirely.

And now that most clients are made with AI, things need to be as prescriptive as possible. Especially when talking about fundamental features that can affect the fabric of Nostr.

@vitorpamplona
Copy link
Collaborator

This development is similar to NIP-44, IMO. We should get a real audit at some point.

@staab
Copy link
Member Author

staab commented Dec 2, 2025

We should get a real audit at some point.

That would be helpful, but you're talking about implementation bugs, which would require an audit of all implementations in a permissionless protocol. The signature validation stuff is a good analogy. There's nothing we can do to make people follow directions, which is not a failure of the protocol, it's a failure of people. If nostr can't cope with people screwing up, we should just shut this whole thing down and go back to platforms.

@pablof7z
Copy link
Member

pablof7z commented Dec 2, 2025

Do you have a particular scenario in mind?

So many things can go wrong here:

  • Clients not checking OTS or checking incorrectly.
  • Clients not storing migration information correctly and leaking access to the other keys.
  • Clients trying to migrate all the account info from one key to another, establishing a link in some other way
  • Clients developing trusted server-side components like watch-towers that can be new avenues of attack
  • Sharding incorrectly and revealing more information about the migration than what it is supposed to.

Remember, lots of clients don't even verify events coming from relays. The bar is REALLY low on Nostr.

If too many bugs get prominent, people might associate Nostr with insecure payloads and give up on the protocol entirely.

And now that most clients are made with AI, things need to be as prescriptive as possible. Especially when talking about fundamental features that can affect the fabric of Nostr.

Social clients don't need to do any of this.

if a migration event is published something bad is happening (only someone with the nsec can publish it).

Verifying that a migration event is real is trivial -- social clients can simply do that check and send users to an specialized app that implements the OTS checks and all that.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Dec 2, 2025

There's nothing we can do to make people follow directions, which is not a failure of the protocol, it's a failure of people.

That's why I mentioned specific Vault clients. Then we just need to make sure those clients work well in the same way we do with signers today. There is no need to verify every client out there. The audit only needs to be done in one client, like we did with NIP-44.

@dadofsambonzuki
Copy link

Is this missing attestation? How do followers attest to "I verified out-of-band the person really changed pubkeys"? I think it'd be valuable to
Have this as an explicit action; not just a change in the kind:3 of people. Like if my key is compromised and I roll onto the new one I would call @dergigi and @fiatjaf and others that I'm close with to get them to attest and give a clear social weight to that migration event. They could publish it, even as a kind:1 with some tags, confirming the OOB check.

They can use the Attestation NIP:

https://nostrhub.io/naddr1qvzqqqrcvypzp384u7n44r8rdq74988lqcmggww998jjg0rtzfd6dpufrxy9djk8qyt8wumn8ghj7un9d3shjtnswf5k6ctv9ehx2aqqp3shgar9wd6xzarfdah8xp48yjp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants