mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-22 16:35:52 -05:00
rewrite NIP-46.
This commit is contained in:
parent
5dcfe85306
commit
cb37a9320e
178
46.md
178
46.md
|
@ -2,161 +2,83 @@ NIP-46
|
|||
======
|
||||
|
||||
Nostr Connect
|
||||
------------------------
|
||||
-------------
|
||||
|
||||
`draft` `optional`
|
||||
|
||||
## Rationale
|
||||
This 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.
|
||||
|
||||
Private keys should be exposed to as few systems - apps, operating systems, devices - as possible as each system adds to the attack surface.
|
||||
## Signer Discovery
|
||||
|
||||
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.
|
||||
The client must somehow be able to contact the signer through a common relay.
|
||||
|
||||
### Started by the signer
|
||||
|
||||
## Terms
|
||||
The remote signer generates a connection token in the form
|
||||
|
||||
* **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.
|
||||
```
|
||||
<npub1...>#<secret>?relay=wss://...&relay=wss://...
|
||||
```
|
||||
|
||||
The 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.
|
||||
|
||||
## `TL;DR`
|
||||
### Started by the client
|
||||
|
||||
The client generates a QR code in the following form (URL-encoded):
|
||||
|
||||
**App** and **Signer** sends ephemeral encrypted messages to each other using kind `24133`, using a relay of choice.
|
||||
```
|
||||
nostrconnect://<client-key-hex>?relay=wss://...&metadata={"name":"client-name"}
|
||||
```
|
||||
|
||||
App prompts the Signer to do things such as fetching the public key or signing events.
|
||||
The signer scans the QR code and sends a `connect` message to the client in the specified relays.
|
||||
|
||||
The `content` field must be an encrypted JSONRPC-ish **request** or **response**.
|
||||
## Event payloads
|
||||
|
||||
## Signer Protocol
|
||||
Event payloads are [NIP-04](04.md)-encrypted JSON blobs that look like JSONRPC.
|
||||
|
||||
### Messages
|
||||
Events sent by the client to the remote signer have the following format:
|
||||
|
||||
#### Request
|
||||
|
||||
```json
|
||||
```js
|
||||
{
|
||||
"id": <random_string>,
|
||||
"method": <one_of_the_methods>,
|
||||
"params": [<anything>, <else>]
|
||||
"pubkey": "<client-key-hex>"
|
||||
"kind": 24133,
|
||||
"tags": [
|
||||
["p", "<signer-key-hex>"]
|
||||
],
|
||||
"content": "nip04_encrypted_json({id: <random-string>, method: <see-below>, params: []})",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
#### Response
|
||||
And the events the remote signer sends to the client have the following format:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": <request_id>,
|
||||
"result": <anything>,
|
||||
"error": <reason>
|
||||
}
|
||||
```js
|
||||
"pubkey": "<signer-key-hex>"
|
||||
"kind": 24133,
|
||||
"tags": [
|
||||
["p", "<client-key-hex>"]
|
||||
],
|
||||
"content": "nip04_encrypted_json({id: <request-id>, result: <any>, error: <reason-string>})",
|
||||
...
|
||||
```
|
||||
|
||||
### Methods
|
||||
|
||||
|
||||
#### Mandatory
|
||||
|
||||
These are mandatory methods the remote signer app MUST implement:
|
||||
|
||||
- **describe**
|
||||
- params []
|
||||
- result `["describe", "get_public_key", "sign_event", "connect", "disconnect", "delegate", ...]`
|
||||
- **get_public_key**
|
||||
- params []
|
||||
- result `pubkey`
|
||||
- **sign_event**
|
||||
- params [`event`]
|
||||
- result `event_with_signature`
|
||||
|
||||
#### optional
|
||||
|
||||
|
||||
- **connect**
|
||||
- params [`pubkey`]
|
||||
- **disconnect**
|
||||
- params []
|
||||
- **delegate**
|
||||
- params [`delegatee`, `{ kind: number, since: number, until: number }`]
|
||||
- result `{ from: string, to: string, cond: string, sig: string }`
|
||||
- params: [`pubkey`, `secret`]
|
||||
- result: `null`
|
||||
- **get_public_key**
|
||||
- params: []
|
||||
- result: `pubkey`
|
||||
- **sign_event**
|
||||
- params: [`event`]
|
||||
- result: `event_with_pubkey_id_and_signature`
|
||||
- **get_relays**
|
||||
- params []
|
||||
- result `{ [url: string]: {read: boolean, write: boolean} }`
|
||||
- params: []
|
||||
- result: `{ [url: string]: {read: boolean, write: boolean} }`
|
||||
- **nip04_encrypt**
|
||||
- params [`pubkey`, `plaintext`]
|
||||
- result `nip4 ciphertext`
|
||||
- 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://<pubkey>?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://<pubkey>&relay=<relay>&metadata=<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 event including the `id` and the schnorr `signature` 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
|
||||
|
||||
|
||||
- params: [`pubkey`, `nip4 ciphertext`]
|
||||
- result: [`plaintext`]
|
||||
|
|
Loading…
Reference in New Issue
Block a user