upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Fernandez <p@f7z.io>2023-12-18 10:22:17 +0000
committerGitHub <noreply@github.com>2023-12-18 10:22:17 +0000
commit09f8244e6fb5271a65a51cbbfe2b9503ee8783f3 (patch)
treecf48615359166c3c66f2967be177c3641e3d5cd3
parentef106ecccad2f764f80cae85f2bc666a419f9e20 (diff)
parentd0aef4c1581807a046b00396f67f3dd03cf599e8 (diff)
Merge pull request #831 from nostr-protocol/nostr-connect
rewrite NIP-46
-rw-r--r--46.md190
1 files changed, 63 insertions, 127 deletions
diff --git a/46.md b/46.md
index 5318541..3ab71e9 100644
--- a/46.md
+++ b/46.md
@@ -2,161 +2,97 @@ NIP-46
2====== 2======
3 3
4Nostr Connect 4Nostr Connect
5------------------------ 5-------------
6 6
7`draft` `optional` 7`draft` `optional`
8 8
9## Rationale 9This NIP describes a method for 2-way communication between a **remote signer** and a normal Nostr client. The remote signer could be, for example, a hardware device dedicated to signing Nostr events, while the client is a normal Nostr client.
10 10
11Private keys should be exposed to as few systems - apps, operating systems, devices - as possible as each system adds to the attack surface. 11## Signer Discovery
12 12
13Entering private keys can also be annoying and requires exposing them to even more systems such as the operating system's clipboard that might be monitored by malicious apps. 13The client always starts by generating a random key which is used to communicate with the signer, then it one of the methods below is used to allow the client to know what is the signer public key for the session and which relays to use.
14 14
15### Started by the signer (nsecBunker)
15 16
16## Terms 17The remote signer generates a connection token in the form
17
18* **App**: Nostr app on any platform that *requires* to act on behalf of a nostr account.
19* **Signer**: Nostr app that holds the private key of a nostr account and *can sign* on its behalf.
20 18
19```
20<npub1...>#<optional-secret>?relay=wss://...&relay=wss://...
21```
21 22
22## `TL;DR` 23The user copies that token and pastes it in the client UI somehow. Then the client can send events of kind `24133` to the specified relays and wait for responses from the remote signer.
23 24
25### Started by the client
24 26
25**App** and **Signer** sends ephemeral encrypted messages to each other using kind `24133`, using a relay of choice. 27The client generates a QR code in the following form (URL-encoded):
26 28
27App prompts the Signer to do things such as fetching the public key or signing events. 29```
30nostrconnect://<client-key-hex>?relay=wss://...&metadata={"name":"...", "url": "...", "description": "..."}
31```
28 32
29The `content` field must be an encrypted JSONRPC-ish **request** or **response**. 33The signer scans the QR code and sends a `connect` message to the client in the specified relays.
30 34
31## Signer Protocol 35## Event payloads
32 36
33### Messages 37Event payloads are [NIP-04](04.md)-encrypted JSON blobs that look like JSONRPC messages (their format is specified inside the `.content` of the event formats nelow).
34 38
35#### Request 39Events sent by the client to the remote signer have the following format:
36 40
37```json 41```js
38{ 42{
39 "id": <random_string>, 43 "pubkey": "<client-key-hex>"
40 "method": <one_of_the_methods>, 44 "kind": 24133,
41 "params": [<anything>, <else>] 45 "tags": [
46 ["p", "<signer-key-hex>"]
47 ],
48 "content": "nip04_encrypted_json({id: <random-string>, method: <see-below>, params: [array_of_strings]})",
49 ...
42} 50}
43``` 51```
44 52
45#### Response 53And the events the remote signer sends to the client have the following format:
46 54
47```json 55```js
48{ 56 "pubkey": "<signer-key-hex>"
49 "id": <request_id>, 57 "kind": 24133,
50 "result": <anything>, 58 "tags": [
51 "error": <reason> 59 ["p", "<client-key-hex>"]
52} 60 ],
61 "content": "nip04_encrypted_json({id: <request-id>, result: <string>, error: <reason-string>})",
62 ...
53``` 63```
54 64
55### Methods 65The signer key will always be the key of the user who controls the signer device.
56
57
58#### Mandatory
59 66
60These are mandatory methods the remote signer app MUST implement: 67### Methods
61 68
62- **describe** 69- **connect**
63 - params [] 70 - params: [`pubkey`, `secret`]
64 - result `["describe", "get_public_key", "sign_event", "connect", "disconnect", "delegate", ...]` 71 - result: `"ack"`
65- **get_public_key** 72- **get_public_key**
66 - params [] 73 - params: []
67 - result `pubkey` 74 - result: `pubkey-hex`
68- **sign_event** 75- **sign_event**
69 - params [`event`] 76 - params: [`event`]
70 - result `event_with_signature` 77 - result: `json_string(event_with_pubkey_id_and_signature)`
71
72#### optional
73
74
75- **connect**
76 - params [`pubkey`]
77- **disconnect**
78 - params []
79- **delegate**
80 - params [`delegatee`, `{ kind: number, since: number, until: number }`]
81 - result `{ from: string, to: string, cond: string, sig: string }`
82- **get_relays** 78- **get_relays**
83 - params [] 79 - params: []
84 - result `{ [url: string]: {read: boolean, write: boolean} }` 80 - result: `json_string({[url: string]: {read: boolean, write: boolean}})`
85- **nip04_encrypt** 81- **nip04_encrypt**
86 - params [`pubkey`, `plaintext`] 82 - params: [`third-party-pubkey`, `plaintext`]
87 - result `nip4 ciphertext` 83 - result: `nip04-ciphertext`
88- **nip04_decrypt** 84- **nip04_decrypt**
89 - params [`pubkey`, `nip4 ciphertext`] 85 - params: [`third-party-pubkey`, `nip04-ciphertext`]
90 - result [`plaintext`] 86 - result: `plaintext`
91 87- **nip44_get_key**
92 88 - params: [`third-party-pubkey`]
93NOTICE: `pubkey` and `signature` are hex-encoded strings. 89 - result: `nip44-conversation-key`
94 90- **nip44_encrypt**
95 91 - params: [`third-party-pubkey`, `plaintext`]
96### Nostr Connect URI 92 - result: `nip44-ciphertext`
97 93- **nip44_decrypt**
98**Signer** discovers **App** by scanning a QR code, clicking on a deep link or copy-pasting an URI. 94 - params: [`third-party-pubkey`, `nip44-ciphertext`]
99 95 - result: `plaintext`
100The **App** generates a special URI with prefix `nostrconnect://` and base path the hex-encoded `pubkey` with the following querystring parameters **URL encoded** 96- **ping**
101 97 - params: []
102- `relay` URL of the relay of choice where the **App** is connected and the **Signer** must send and listen for messages. 98 - result: `"pong"`
103- `metadata` metadata JSON of the **App**
104 - `name` human-readable name of the **App**
105 - `url` (optional) URL of the website requesting the connection
106 - `description` (optional) description of the **App**
107 - `icons` (optional) array of URLs for icons of the **App**.
108
109#### JavaScript
110
111```js
112const uri = `nostrconnect://<pubkey>?relay=${encodeURIComponent("wss://relay.damus.io")}&metadata=${encodeURIComponent(JSON.stringify({"name": "Example"}))}`
113```
114
115#### Example
116```sh
117nostrconnect://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&metadata=%7B%22name%22%3A%22Example%22%7D
118```
119
120
121
122## Flows
123
124The `content` field contains encrypted message as specified by [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). The `kind` chosen is `24133`.
125
126### Connect
127
1281. User clicks on **"Connect"** button on a website or scan it with a QR code
1292. It will show an URI to open a "nostr connect" enabled **Signer**
1303. In the URI there is a pubkey of the **App** ie. `nostrconnect://<pubkey>&relay=<relay>&metadata=<metadata>`
1314. The **Signer** will send a message to ACK the `connect` request, along with his public key
132
133### Disconnect (from App)
134
1351. User clicks on **"Disconnect"** button on the **App**
1362. The **App** will send a message to the **Signer** with a `disconnect` request
1373. The **Signer** will send a message to ACK the `disconnect` request
138
139### Disconnect (from Signer)
140
1411. User clicks on **"Disconnect"** button on the **Signer**
1422. The **Signer** will send a message to the **App** with a `disconnect` request
143
144
145### Get Public Key
146
1471. The **App** will send a message to the **Signer** with a `get_public_key` request
1483. The **Signer** will send back a message with the public key as a response to the `get_public_key` request
149
150### Sign Event
151
1521. The **App** will send a message to the **Signer** with a `sign_event` request along with the **event** to be signed
1532. The **Signer** will show a popup to the user to inspect the event and sign it
1543. The **Signer** will send back a message with the event including the `id` and the schnorr `signature` as a response to the `sign_event` request
155
156### Delegate
157
1581. The **App** will send a message with metadata to the **Signer** with a `delegate` request along with the **conditions** query string and the **pubkey** of the **App** to be delegated.
1592. The **Signer** will show a popup to the user to delegate the **App** to sign on his behalf
1603. The **Signer** will send back a message with the signed [NIP-26 delegation token](https://github.com/nostr-protocol/nips/blob/master/26.md) or reject it
161
162