From b1a5ad355a8b376170471a41817d8722ba7443b1 Mon Sep 17 00:00:00 2001 From: Marco Argentieri <3596602+tiero@users.noreply.github.com> Date: Mon, 20 Feb 2023 20:26:13 +0100 Subject: NIP-46: Nostr Connect 🔌 connect your Nostr app with remote signing devices (#153) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 46.md | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 46.md (limited to '46.md') diff --git a/46.md b/46.md new file mode 100644 index 0000000..a9f37c1 --- /dev/null +++ b/46.md @@ -0,0 +1,162 @@ +NIP-46 +====== + +Nostr Connect +------------------------ + +`draft` `optional` `author:tiero` `author:giowe` `author:vforvalerio87` + +## Rationale + +Private keys should be exposed to as few systems - apps, operating systems, devices - as possible as each system adds to the attack surface. + +Entering 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. + + +## Terms + +* **App**: Nostr app on any platform that *requires* to act on behalf of a nostr account. +* **Signer**: Nostr app that holds the private key of a nostr account and *can sign* on its behalf. + + +## `TL;DR` + + +**App** and **Signer** sends ephemeral encrypted messages to each other using kind `24133`, using a relay of choice. + +App prompts the Signer to do things such as fetching the public key or signing events. + +The `content` field must be an encrypted JSONRPC-ish **request** or **response**. + +## Signer Protocol + +### Messages + +#### Request + +```json +{ + "id": , + "method": , + "params": [, ] +} +``` + +#### Response + +```json +{ + "id": , + "result": , + "error": +} +``` + +### Methods + + +#### Mandatory + +These are mandatory methods the remote signer app MUST implement: + +- **describe** + - params [] + - result `{"get_public_key": { params: [], result: anything }}` +- **get_public_key** + - params [] + - result `pubkey` +- **sign_event** + - params [`event`] + - result `signature` + +#### optional + + +- **connect** + - params [`pubkey`] +- **disconnect** + - params [] +- **delegate** + - params [`pubkey`, `conditions query string`] + - result `nip26 delegation token` +- **get_relays** + - params [] + - result `{ [url: string]: {read: boolean, write: boolean} }` +- **nip04_encrypt** + - params [`pubkey`, `plaintext`] + - result `nip4 ciphertext` +- **nip04_decrypt** + - params [`pubkey`, `nip4 ciphertext`] + - result [`plaintext`] + + +NOTICE: `pubkey` and `signature` are hex-encoded strings. + + +### Nostr Connect URI + +**Signer** discovers **App** by scanning a QR code, clicking on a deep link or copy-pasting an URI. + +The **App** generates a special URI with prefix `nostrconnect://` and base path the hex-encoded `pubkey` with the following querystring parameters **URL encoded** + +- `relay` URL of the relay of choice where the **App** is connected and the **Signer** must send and listen for messages. +- `metadata` metadata JSON of the **App** + - `name` human-readable name of the **App** + - `url` (optional) URL of the website requesting the connection + - `description` (optional) description of the **App** + - `icons` (optional) array of URLs for icons of the **App**. + +#### JavaScript + +```js +const uri = `nostrconnect://?relay=${encodeURIComponent("wss://relay.damus.io")}&metadata=${encodeURIComponent(JSON.stringify({"name": "Example"}))}` +``` + +#### Example +```sh +nostrconnect://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&metadata=%7B%22name%22%3A%22Example%22%7D +``` + + + +## Flows + +The `content` field contains encrypted message as specified by [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). The `kind` chosen is `24133`. + +### Connect + +1. User clicks on **"Connect"** button on a website or scan it with a QR code +2. It will show an URI to open a "nostr connect" enabled **Signer** +3. In the URI there is a pubkey of the **App** ie. `nostrconnect://&relay=&metadata=` +4. The **Signer** will send a message to ACK the `connect` request, along with his public key + +### Disconnect (from App) + +1. User clicks on **"Disconnect"** button on the **App** +2. The **App** will send a message to the **Signer** with a `disconnect` request +3. The **Signer** will send a message to ACK the `disconnect` request + +### Disconnect (from Signer) + +1. User clicks on **"Disconnect"** button on the **Signer** +2. The **Signer** will send a message to the **App** with a `disconnect` request + + +### Get Public Key + +1. The **App** will send a message to the **Signer** with a `get_public_key` request +3. The **Signer** will send back a message with the public key as a response to the `get_public_key` request + +### Sign Event + +1. The **App** will send a message to the **Signer** with a `sign_event` request along with the **event** to be signed +2. The **Signer** will show a popup to the user to inspect the event and sign it +3. The **Signer** will send back a message with the schnorr `signature` of the event as a response to the `sign_event` request + +### Delegate + +1. 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. +2. The **Signer** will show a popup to the user to delegate the **App** to sign on his behalf +3. 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 + + -- cgit v1.2.3 From d70959aee6f8e6e2f2bff02898c0281a64c53a8d Mon Sep 17 00:00:00 2001 From: Marco Argentieri <3596602+tiero@users.noreply.github.com> Date: Mon, 27 Feb 2023 18:22:46 +0100 Subject: Amend nip46 describe and delegate methods (#304) --- 46.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to '46.md') diff --git a/46.md b/46.md index a9f37c1..6589fc0 100644 --- a/46.md +++ b/46.md @@ -61,7 +61,7 @@ These are mandatory methods the remote signer app MUST implement: - **describe** - params [] - - result `{"get_public_key": { params: [], result: anything }}` + - result `["describe", "get_public_key", "sign_event", "connect", "disconnect", "delegate", ...]` - **get_public_key** - params [] - result `pubkey` @@ -77,8 +77,8 @@ These are mandatory methods the remote signer app MUST implement: - **disconnect** - params [] - **delegate** - - params [`pubkey`, `conditions query string`] - - result `nip26 delegation token` + - params [`delegatee`, `{ kind: number, since: number, until: number }`] + - result `{ from: string, to: string, cond: string, sig: string }` - **get_relays** - params [] - result `{ [url: string]: {read: boolean, write: boolean} }` -- cgit v1.2.3 From 4bb393735ea501f0bac3e2cb255ae9a3caab6a68 Mon Sep 17 00:00:00 2001 From: Marco Argentieri <3596602+tiero@users.noreply.github.com> Date: Wed, 15 Mar 2023 20:17:44 +0100 Subject: Update 46.md --- 46.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to '46.md') diff --git a/46.md b/46.md index 6589fc0..90fa1a0 100644 --- a/46.md +++ b/46.md @@ -67,7 +67,7 @@ These are mandatory methods the remote signer app MUST implement: - result `pubkey` - **sign_event** - params [`event`] - - result `signature` + - result `event_with_signature` #### optional @@ -151,7 +151,7 @@ The `content` field contains encrypted message as specified by [NIP04](https://g 1. The **App** will send a message to the **Signer** with a `sign_event` request along with the **event** to be signed 2. The **Signer** will show a popup to the user to inspect the event and sign it -3. The **Signer** will send back a message with the schnorr `signature` of the event as a response to the `sign_event` request +3. 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 ### Delegate -- cgit v1.2.3