NIP-AB: Device Pairing#2328
Conversation
|
What is the problem with https://github.com/nostr-protocol/nips/blob/master/49.md? Encrypt the key, transfer it encrypted, decrypt on the other device? Actually if you're doing it with QR codes and you already trust the sender and receiver app I don't see why not just put the nsec directly in the QR code. |
This does not require a strong password, which is inconvenient to type on a mobile device. Also, the security model here is as strong as any other nostr message type (ie having the nsec in the message doesn't materially make this less secure than any other signed message). Putting the nsec directly into the QR code means anyone who can see your screen can steal your nsec permanently. Like, say, a camera at an airport or someone sitting behing you at a coffee shop. With NIP-AB, someone seeing your screen does not matter. Thanks for taking a look, @fiatjaf 👋 |
|
Also, NIP-49 specifically says not publish to relays. I agree with it. NIP-AB does not have the mass cracking issue because it does not have a password. |
|
I didn't suggest publishing to relays, just putting the encrypted nsec in the QR code directly (or putting the nsec without encrypting). Do you really think it makes sense to have a complex protocol for key transfer instead of just reusing normal QR codes or basic encryption that are already implemented in many apps just because someone might decide to migrate their data from one phone to the other in an airport and can't be bothered to find a safer spot or type a longer password? I feel like the existing solutions already give good enough security and UX, while this one is more likely to decrease UX because there will be less interoperability due to the complexity and people will resort to sending their nsecs through Telegram self-messages in the end. |
|
The UX for this is like the bluetooth pairing flows everyone is used to: Scan QR code. Confirm numbers match. Done! Sharing an encrypted nsec over QR code is fine as long as you have a sufficiently long (and inconvenient to type) password in your head (that you have to type twice, once on the source and once on the target). |
|
@fiatjaf, I think the main difference is the security/UX tradeoff, not whether NIP-49 can technically carry the key. With NIP-49, the transfer security ultimately depends on a user-chosen password. For this use case, that password has to be created on one mobile device and typed again on another. In practice, users will either choose something short, reuse an existing password, or abandon the flow. Scrypt helps, but it does not remove the offline guessing problem if the encrypted blob is captured. That capture risk is relevant because QR-based transfer is inherently screen-visible. NIP-AB has a different failure mode. A passive observer of the QR does not get the private key and does not get an offline password-cracking artifact. To attack the transfer, they have to actively participate during the short pairing window. The UX is also simpler:
I would also note that this protocol is well within the realm of established cryptographic patterns; there are other systems that use similar SAS-authenticated Diffie-Hellman flows. I collected a list:
|
|
@paulmillr this might be in your wheelhouse? |
|
I never said your proposed UX would be worse, I'm just saying that because this is more complex it will get implemented in less places, which may cause users to fall back to much less safe solutions. I also do not disagree that your solution is safer, I was just saying that the tradeoffs aren't the best because we are talking about a new complex protocol implementation for doing a thing that very few people will ever do and even those that will will do it only once -- and the protocol only improves the security/UX marginally (debatable how much improvement there is, but the fact is that the NIP-49 QR code works and is reasonably safe already). |
|
Nice. We need this sort of layer for normies since they never use NIP-46, unfortunately. It's still dangerous for rogue clients, but definitely much safer than copying and pasting nsec directly. Also, many clients simply don't accept ncryptsec in the first place, so this NIP doesn't seem to harm anything.
|
|
from a very brief glance, the cryptography seems fine, but a more deep dive would be useful |
@fiatjaf yeah, under the hood this is a little more complicated, but the NIP has a full set of test vectors to ensure the implementation is correct. It makes it much easier to get right. And the example implementation in Sprout should help, too. As far as handshake protocols, this one is pretty straighforward. And, yeah, I think the UX is hugely improved and is exactly what most people expect these days when getting their phone onto a new service. I'm thinking of bluetooth pairing, Discord sign in, Slack magic links. This is right in the same ballpark of convenience and intuitiveness.
@1l0 yeah, that would have to be a different NIP. This one counts on the out of band nature of the QR code scan to transmit the ephemeral crypto that is used during the handshake. There are other out of band information transimission options available, but the implementation is different enough for each that I'd want separate protocols to keep this one simple.
@paulmillr thanks for taking a look! Here's the PR for the original implementation in Sprout block/sprout#333 And the full spec (too long to fit in well in this repo) along with the formal proof is in https://github.com/block/sprout/blob/main/crates/sprout-core/src/pairing/NIP-AB.md |
|
If you go all the way back to when NIP-46 was proposed, the idea was to have a common remote communication channel where you could extend with whatever "commands" you needed, i.e. it wasn't meant to match only NIP-07 methods. By using NIP-46 this NIP would be much easier to review and implement. For example: On your setup, the "source" initiates the connection, so you'd use the Deviations from NIP-46:
|
Thanks for taking a look, @arthurfranca 👋 I did take a good look at NIP-46, but its semantics are fundamentally different and I didn't think it would be appropriate to change its core premise that "Private keys should be exposed to as few systems - apps, operating systems, devices - as possible as each system adds to the attack surface." I do talk about this in the Motivation section of NIP-AB in this PR, and go into more detail in the one in Sprout repo. Here's the line from the full spec in the Sprout repo:
NIP-46 doesn't need to be quite as concerned with security since it is an active session and can be revoed. NIP-AB is paranoid because it is a potentially permanent transfer. A working mitm would be catastrophic for nsec transfer. In NIP-AB, the SAS code is cryptographically bound to the ECDH handshake and session transcript. The code proves you're talking to the right peer, not just that someone showed you a number. Adding a SAS display onto an already-established NIP-46 channel doesn't give you the same property. The channel is already authenticated (weakly) by the time you'd show the code. You could theoretically add fresh ephemeral ECDH, transcript binding, and SAS verification inside a NIP-46 session, but at that point you've rebuilt NIP-AB's core under a different event kind. The security properties NIP-AB needs are the protocol. |
I wanted a simple way to move a Nostr key from one device to another without pasting nsecs around or depending on the old device staying online.
Scan a QR code on your new device, confirm the numbers match, and you're you on both devices.
The closest thing I found was @1l0's NIP-4B draft (#1768), which covers the same use case. That work and the discussion between @vitorpamplona and @mikedilger on it were really helpful in framing the problem. This draft makes a different set of tradeoffs: QR bootstrap, ephemeral ECDH, and a short code shown on both screens before the key is sent (same idea as Bluetooth pairing).
Scope is narrow: one-time transfer of a key between two devices controlled by the same user. Not trying to replace NIP-46 or define a general secure channel. I think it's worth standardizing this because it's a modern UX everyone is familiar with while also being provably secure.
Uses NIP-44 for encryption, NIP-49
ncryptsecfor the payload format. Standard NIP-01 event routing, no new relay commands or behavior. Ephemeral keys only, discarded after the session.There's a working implementation and a Tamarin model for the handshake in sprout if anyone wants to look at the code or poke at the crypto.
Did I miss something existing that already covers this?