-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added details about ion connect protocol
- Loading branch information
Showing
4 changed files
with
641 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
ICIP-1000 | ||
======= | ||
|
||
Multiple Public Key Types and Signature Algorithms for Event Signing | ||
----- | ||
|
||
`draft` `optional` | ||
|
||
This ICIP defines a way for clients and relays to allow other types of ECC Public Keys and Signature Algorithms to be used in Nostr in a seamless manner. | ||
|
||
### Motivation | ||
|
||
As mentioned in [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md): | ||
|
||
> Each user has a keypair. Signatures, public key, and encodings are done according to the [Schnorr signatures standard for the curve `secp256k1`](https://bips.xyz/340). | ||
This is a limitation for Nostr adoption, as many Blockchains and other Cryptographic Networks have already identities in place using different ECC Public Key curves, and may use different Signature Algorithms. Even Bitcoin pre Taproot uses `ECDSA/secp256k1` and not `Schnorr/secp256k1`. | ||
|
||
In this case it is just the signatures that differ, and the public key derivation is based out of the same `secp256k1` curve, so the public keys remain valid, but for other networks that use `ed25519` signatures, for instance, not even the public keys would be valid, as the curve used is `Curve25519` instead. | ||
|
||
This means that Nostr identities would have to be different than the ones used in the other networks, making it impossible to consider a direct match between one network identity and the other, for instance, for having a smart contract as a Nostr identity (public key). | ||
|
||
### References | ||
|
||
This proposal came together with inputs from many other proposals and discussions, but these are the main ones: | ||
|
||
[NIP-01: Basic protocol flow description](https://github.com/nostr-protocol/nips/blob/master/01.md)<br> | ||
[NIP-06: Basic key derivation from mnemonic seed phrase](https://github.com/nostr-protocol/nips/blob/master/06.md) | ||
|
||
### Public Key Types and Signature Algorithms | ||
|
||
A small list of networks and their ECC Key Derivation curves and Signature Algorithms: | ||
|
||
| Network | ECC Curve | Signature Algorithm | | ||
|-------------------|------------|---------------------| | ||
| Bitcoin (legacy) | secp256k1 | ECDSA | | ||
| Bitcoin (taproot) | secp256k1 | Schnorr | | ||
| Ethereum | secp256k1 | ECDSA | | ||
| Litecoin | secp256k1 | ECDSA | | ||
| Monero | curve25519 | EdDSA | | ||
| Cardano | curve25519 | EdDSA | | ||
| Ripple | secp256k1 | ECDSA | | ||
| TON (Telegram) | curve25519 | EdDSA | | ||
| Cardano | curve25519 | EdDSA | | ||
| Stellar | curve25519 | EdDSA | | ||
| Tezos | curve25519 | EdDSA | | ||
| Zcash | curve25519 | EdDSA | | ||
| Zcash (shielded) | secp256k1 | ECDSA | | ||
|
||
From this small list it is clear that more than half of the public keys from these selected networks wouldn't be compatible with Nostr, and only a Bitcoin taproot wallet would be able to generate compatible signatures for Nostr events. | ||
|
||
We want to eliminate this problem, and it is quite simple... | ||
|
||
### Signature Prefixes | ||
|
||
This ICIP introduces a prefix mechanism for the `.sig` field of Nostr events, that by default (without any prefix) falls back to `schnorr/secp256k1`, but when present defines the signature algorithm and public key derivation curve. | ||
|
||
#### Signature Algorithms | ||
|
||
| Prefix | Signature Algorithm | ECC Curve (default) | | ||
|---------|---------------------|---------------------| | ||
| schnorr | Schnorr | secp256k1 | | ||
| ecdsa | ECDSA | secp256k1 | | ||
| eddsa | EdDSA | curve25519 | | ||
|
||
#### Public Key Derivation Curves | ||
|
||
| Prefix | ECC Curve | | ||
|------------|------------| | ||
| secp256k1 | secp256k1 | | ||
| secp256r1 | secp256r1 | | ||
| curve25519 | Curve25519 | | ||
| curve448 | Curve448 | | ||
|
||
#### Signature Algorithm Prefix | ||
|
||
To use a different Signature Algorithm, for instance ECDSA for legacy Bitcoin wallets, an event would look like this: | ||
|
||
```json | ||
{ | ||
"id": "567b41fc9060c758c4216fe5f8d3df7c57daad7ae757fa4606f0c39d4dd220ef", | ||
"kind": "1", | ||
"pubkey": "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd", | ||
"tags": [], | ||
"content": "some note", | ||
... | ||
"sig": "ecdsa:3046022100a0e03de740d3a1136d443b0c24a252e08ae1ae4dd73f0f7dacfdc440c69ce45102210083b5ba4e0f34261b605848ad85ddf585637c7579e58e73058ab3c934a7ca05c2" | ||
} | ||
``` | ||
|
||
#### Signature Algorithm Prefix with a Different ECC Curve | ||
|
||
To use another Signature Algorithm and another ECC Curve, an event would look like this: | ||
|
||
```json | ||
{ | ||
"id": "567b41fc9060c758c4216fe5f8d3df7c57daad7ae757fa4606f0c39d4dd220ef", | ||
"kind": "1", | ||
"pubkey": "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd", | ||
"tags": [], | ||
"content": "some note", | ||
... | ||
"sig": "ecdsa/secp256r1:3046022100c04f4139d4d52aa516873a8a9fba77c54810ade51e7e1720b45934d51a9a1216022100a645e11aa3877f111caf486fbd199781dca85373da504f6eb3690439f7a1a222" | ||
} | ||
``` | ||
|
||
### Clients and Relays | ||
|
||
Clients and Relays are free to choose what combinations of Signatures Algorithms and ECC Curves they support, the only mandatory one is `schnorr/secp256k1`, which is the default for Nostr, but highly encouraged to support more, at least `ecdsa` and `eddsa` with their default curves. This way Nostr network will be increasingly more compatible and possible to interoperate with other networks. | ||
|
||
### Integration into NIP-01 | ||
|
||
We propose that this ICIP, when discussed and approved, should be integrated into NIP-01, as it represents a global improvement for event signing. We decided to keep it separated in a different file to be more concise for discussion for now. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
ICIP-2000 | ||
====== | ||
|
||
On-Behalf of - Simple Sub-Key Management | ||
----- | ||
|
||
`draft` `optional` | ||
|
||
This ICIP defines a simple way for an Identity Sub-Key management system, including active, inactive and revoked public keys, for publishing On-Behalf of a master identity. | ||
|
||
### Motivation | ||
|
||
The state of the art now has two methods for enabling sub-key management: | ||
- [NIP-26](https://github.com/nostr-protocol/nips/blob/master/26.md): Multiple key delegation and no revocation (just time bound) | ||
- [NIP-41](https://github.com/nostr-protocol/nips/pull/1032): More complete single key delegation and revocation (complex) | ||
|
||
Each of these methods has their own pros and cons, but there's a very common use case that is not covered by any of these methods completely, which is having a master identity that is secure (possibly in cold storage), that can whitelist and blacklist multiple public keys (one for each device or app, for example), that can be used individually (less common but interesting for media management companies) and can publish on-behalf of one or several master identities. | ||
|
||
Using [NIP-26](https://github.com/nostr-protocol/nips/blob/master/26.md) for this purpose doesn't allow for blacklisting (revocation), or alternatively requires time bound delegation, with new delegation signing at every expiry. On the other hand [NIP-41](https://github.com/nostr-protocol/nips/pull/1032) is a more complete and complex identity management solution, but only allows for one active sub-key at any point in time, and that sub-key's only purpose is bound to the main identity. | ||
|
||
### References | ||
|
||
This proposal came together with inputs from many other proposals and discussions, but these are the main ones: | ||
|
||
[NIP-26: Delegated Event Signing](https://github.com/nostr-protocol/nips/blob/master/26.md)<br> | ||
[NIP-41: Identity Management](https://github.com/nostr-protocol/nips/pull/1032)<br> | ||
[NIP-06: Basic Key Derivation from Mnemonic Seed Phrase](https://github.com/nostr-protocol/nips/blob/master/06.md)<br> | ||
[NIP-51: Lists](https://github.com/nostr-protocol/nips/blob/master/51.md) | ||
|
||
[Why I don’t like NIP-26 as a solution for key management](https://fiatjaf.com/4c79fd7b.html)<br> | ||
[Thoughts on Nostr key management](https://fiatjaf.com/72f5d1e4.html) | ||
|
||
[Stateless key rotation using a series of hidden commitments](https://github.com/nostr-protocol/nips/issues/103)<br> | ||
[Key distribution, rotation, and recovery](https://github.com/nostr-protocol/nostr/issues/45)<br> | ||
[Key rotation verified through root key attestation](https://github.com/nostr-protocol/nips/issues/116)<br> | ||
[Trusted public-key-bundle attestations for key rotation and group definition](https://github.com/nostr-protocol/nips/issues/123) | ||
|
||
### Identity types | ||
|
||
For clarity in this ICIP, we'll use the following identities to describe the actors that are involved in the examples and use cases: | ||
|
||
- **master**: the master account, the content owner or author | ||
- **active**: an active sub account, device account, media manager or publisher account | ||
- **inactive**: a sub account that has been inactivated (but not compromised) | ||
- **revoked**: a sub account that has been revoked (it may have been compromised, and all events posted on-behalf of master need to be invalidated) | ||
|
||
### On-Behalf of Attestations List | ||
|
||
This ICIP introduces a replaceable event with `kind 10100`, which is used to keep a [NIP-51](https://github.com/nostr-protocol/nips/blob/master/51.md) list of `active`, `inactive` or `revoked` public keys, for publishing events on-behalf of a master account. The only valid tag in this list is the `p` tag as defined below. | ||
|
||
`.content` fields is unused and can be ignored if present. | ||
|
||
This list is owned by the master account, and can only be updated by an event signed by the master account itself, so never using a `b` on-behalf tag (see below), neither by [NIP-41](https://github.com/nostr-protocol/nips/pull/1032) `p` tag in `kind 0`, nor using a [NIP-26](https://github.com/nostr-protocol/nips/blob/master/26.md) `delegation` tag. | ||
|
||
This list is ever-growing, so each update has to include all previous attestations unchanged, and add one or more attestations to the list, otherwise they should be considered invalid and ignored by clients and relays. | ||
|
||
### Tag `b` (on-Behalf) for events | ||
|
||
This ICIP introduces a new tag: `b`, which is indexable by relays, and can be present in active account events, if attested at the on-behalf list above, formatted as follows: | ||
|
||
```json | ||
[ "b", <pubkey of the master account> ] | ||
``` | ||
|
||
To prevent spam, only one `b` tag can be present in an event. | ||
|
||
If present and valid, the `b` tag will represent that clients and relays should consider that event as published by the master account specified in the `b` tag, instead of the one in the event `.pubkey` field. | ||
|
||
If an invalid `b` tag is present, clients and relays should disregard the event, as if it had an invalid signature. | ||
|
||
### Tag `p` (with attestation string) for `kind 10100` list | ||
|
||
This ICIP also introduces a new attestation string for `p` tag. The `p` tag can be present multiple times in master account's `kind 10100` On-Behalf Of attestations list, formatted as follows: | ||
|
||
```json | ||
[ | ||
"p", <pubkey>, <main relay URL>, <attestation string> | ||
] | ||
``` | ||
|
||
Field `main relay URL` can be omitted if not required or needed for accessing the sub account events, and in this case an empty string should be used in the second field of the `p` tag. | ||
|
||
#### Active Attestation String | ||
|
||
The **Active Attestation** should be a string in the following format: | ||
|
||
``` | ||
"active:<timestamp>:<kinds comma separated list, optional>" | ||
``` | ||
|
||
Last `:` is only required if an optional kinds list is present. Without a kinds list, the attestation is valid for all event kinds besides `kind 10100`. | ||
|
||
#### Inactive and Revoked Attestation String | ||
|
||
The **Inactive** or **Revoked Attestations** should be a string in the following formats: | ||
|
||
``` | ||
"inactive:<timestamp>" | ||
``` | ||
|
||
or | ||
|
||
``` | ||
"revoked:<timestamp>" | ||
``` | ||
|
||
To purposely limit the creative use cases, so that it doesn't become very demanding to compute the final state of an account, `inactive` and `revoked` attestations invalidate all previous `active` attestations, and subsequent `active` attestations are considered invalid as well. | ||
|
||
> This way the master account can decide, depending on the use case and criticality, if it makes sense to keep the published content valid, by adding an `inactive` attestation, or if it's preferable to invalidate all content published by that account, on its behalf, by adding a `revoked` attestation. | ||
##### Subsequent Attestations Resolution | ||
|
||
As the attestations are all timestamped, it is convention that a subsequent attestation overrides a prior one, but in the rare event of the same timestamp in attestations for the same public key, the latest in the tags array order should override the previous. | ||
|
||
### Examples | ||
|
||
- Considering: | ||
``` | ||
master account: | ||
8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd | ||
active account: | ||
477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396 | ||
``` | ||
|
||
- Allow active account to publish `kind 1` and `kind 7` events on-behalf of the master account: | ||
|
||
```json | ||
{ | ||
"id": "567b41fc9060c758c4216fe5f8d3df7c57daad7ae757fa4606f0c39d4dd220ef", | ||
"kind": "10100", | ||
"pubkey": "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd", | ||
"tags": [ | ||
[ | ||
"p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"active:1674834236:1,7" | ||
] | ||
], | ||
"content": "", | ||
... | ||
"sig": "a9a4e2192eede77e6c9d24ddfab95ba3ff7c03fbd07ad011fff245abea431fb4d3787c2d04aad001cb039cb8de91d83ce30e9a94f82ac3c5a2372aa1294a96bd" | ||
} | ||
``` | ||
|
||
- The active account, while the master account has a valid active attestation at its `kind 10100` list, can publish on-behalf of the master account, using the `b` tag on the event: | ||
|
||
```json | ||
{ | ||
"id": "e93c6095c3db1c31d15ac771f8fc5fb672f6e52cd25505099f62cd055523224f", | ||
"pubkey": "477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"created_at": 1677426298, | ||
"kind": 1, | ||
"tags": [ | ||
[ | ||
"b", | ||
"8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd" | ||
] | ||
], | ||
"content": "Hello, world!", | ||
"sig": "633db60e2e7082c13a47a6b19d663d45b2a2ebdeaf0b4c35ef83be2738030c54fc7fd56d139652937cdca875ee61b51904a1d0d0588a6acd6168d7be2909d693" | ||
} | ||
``` | ||
|
||
The event should be considered as published on-behalf of the master account, if at the timestamp `1677426298` the master account had a valid active attestation on its `kind 10100` list. If the `b` tag is not validated by an active attestation, that content is considered invalid and relays and clients can ignore it. | ||
|
||
- When master account decides to allow on-behalf active for all kinds: | ||
|
||
```json | ||
{ | ||
"id": "567b41fc9060c758c4216fe5f8d3df7c57daad7ae757fa4606f0c39d4dd220ef", | ||
"kind": "10100", | ||
"pubkey": "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd", | ||
"tags": [ | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"active:1674834236:1,7"], | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"active:1721934607"] | ||
], | ||
"content": "", | ||
... | ||
"sig": "a9a4e2192eede77e6c9d24ddfab95ba3ff7c03fbd07ad011fff245abea431fb4d3787c2d04aad001cb039cb8de91d83ce30e9a94f82ac3c5a2372aa1294a96bd" | ||
} | ||
``` | ||
|
||
- Or otherwise, when master account decides to not allow on-behalf for `kind 7`, but keep `kind 1` active: | ||
|
||
```json | ||
{ | ||
"id": "567b41fc9060c758c4216fe5f8d3df7c57daad7ae757fa4606f0c39d4dd220ef", | ||
"kind": "10100", | ||
"pubkey": "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd", | ||
"tags": [ | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"active:1674834236:1,7"], | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"active:1721934607:1"] | ||
], | ||
"content": "", | ||
... | ||
"sig": "a9a4e2192eede77e6c9d24ddfab95ba3ff7c03fbd07ad011fff245abea431fb4d3787c2d04aad001cb039cb8de91d83ce30e9a94f82ac3c5a2372aa1294a96bd" | ||
} | ||
``` | ||
|
||
- In the case that master decides to not permit on-behalf publishing for that active account anymore, but keep the already published events, for instance if the device that was using that active account is being substituted, and that key safely destroyed: | ||
|
||
```json | ||
{ | ||
"id": "567b41fc9060c758c4216fe5f8d3df7c57daad7ae757fa4606f0c39d4dd220ef", | ||
"kind": "10100", | ||
"pubkey": "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd", | ||
"tags": [ | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"active:1674834236:1,7"], | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"active:1721934607:1"], | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"inactive:1722343578"] | ||
], | ||
"content": "", | ||
... | ||
"sig": "a9a4e2192eede77e6c9d24ddfab95ba3ff7c03fbd07ad011fff245abea431fb4d3787c2d04aad001cb039cb8de91d83ce30e9a94f82ac3c5a2372aa1294a96bd" | ||
} | ||
``` | ||
|
||
- Or instead, if the active account got compromised, and it is best to consider all content published from that account,on-behalf of master account, to be compromised as well: | ||
|
||
```json | ||
{ | ||
"id": "567b41fc9060c758c4216fe5f8d3df7c57daad7ae757fa4606f0c39d4dd220ef", | ||
"kind": "10100", | ||
"pubkey": "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd", | ||
"tags": [ | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"active:1674834236:1,7"], | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"active:1721934607:1"], | ||
["p", | ||
"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", | ||
"", | ||
"revoked:1722343578"] | ||
], | ||
"content": "", | ||
... | ||
"sig": "a9a4e2192eede77e6c9d24ddfab95ba3ff7c03fbd07ad011fff245abea431fb4d3787c2d04aad001cb039cb8de91d83ce30e9a94f82ac3c5a2372aa1294a96bd" | ||
} | ||
``` | ||
|
||
|
||
### Relay & Client Support | ||
|
||
Relays should answer requests such as `["REQ", "", {"authors": ["A"]}]` by querying both the `pubkey` and on-behalf `#b` tags `[1]` value. | ||
|
||
Relays SHOULD allow the master account to delete the events published by the active, inactive or revoked accounts, whenever the events have the on-behalf `b` tag present. |
Oops, something went wrong.