Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 07.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ async window.nostr.nip04.encrypt(pubkey, plaintext): string // returns ciphertex
async window.nostr.nip04.decrypt(pubkey, ciphertext): string // takes ciphertext and iv as specified in nip-04 (deprecated)
async window.nostr.nip44.encrypt(pubkey, plaintext): string // returns ciphertext as specified in nip-44
async window.nostr.nip44.decrypt(pubkey, ciphertext): string // takes ciphertext as specified in nip-44
async window.nostr.nip60.signSecret(proof_secret): { hash: string, sig: string, pubkey: string } // as specified in nip-60
```

### Recommendation to Extension Authors
Expand Down
1 change: 1 addition & 0 deletions 46.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ Each of the following are methods that the _client_ sends to the _remote-signer_
| `nip04_decrypt` | `[<third_party_pubkey>, <nip04_ciphertext_to_decrypt>]` | `<plaintext>` |
| `nip44_encrypt` | `[<third_party_pubkey>, <plaintext_to_encrypt>]` | `<nip44_ciphertext>` |
| `nip44_decrypt` | `[<third_party_pubkey>, <nip44_ciphertext_to_decrypt>]` | `<plaintext>` |
| `nip60_sign_secret` | `[<nip60_proof_secret>]` | `<nip60_result_string>` |

### Requested permissions

Expand Down
46 changes: 45 additions & 1 deletion 60.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The wallet event is an replaceable event `kind:17375`.

Tags:
* `mint` - Mint(s) this wallet uses -- there MUST be one or more mint tags.
* `privkey` - Private key used to unlock P2PK ecash. MUST be stored encrypted in the `.content` field. **This is a different private key exclusively used for the wallet, not associated in any way to the user's Nostr private key** -- This is only used for receiving [NIP-61](61.md) nutzaps.
* `privkey` - Private key used to unlock P2PK ecash. MUST be stored encrypted in the `.content` field. **This is a different private key exclusively used for the wallet, not associated in any way to the user's Nostr private key** -- This is used for receiving [NIP-61](61.md) nutzaps and other P2PK-locked tokens.

### Token Event
Token events are used to record unspent proofs.
Expand Down Expand Up @@ -191,3 +191,47 @@ However, application developers SHOULD use local state when possible and only pu

## Appendix 1: Validating proofs
Clients can optionally validate proofs to make sure they are not working from an old state; this logic is left up to particular implementations to decide when and why to do it, but if some proofs are checked and deemed to have been spent, the client should delete the token and roll over any unspent proof.

## Appendix 2: Signing P2PK-locked Proofs
[NIP-61](61.md) provides a mechanism for users to receive P2PK-locked Cashu Proofs using a separate `pubkey` to their main Nostr identity, and this NIP provides a way for users to sign (unlock) these Proofs using regular [NIP-07](07.md) and [NIP-46](46.md) signers to `nip44_decrypt()` the wallet `kind:17375` event to obtain the unlock private key.

Clients SHOULD use this mechanism if a user has published a `kind:10019` event with a `pubkey` tag.

However, it is accepted that as a Nostr public key is a user's most recognizable cryptographic public identity, Proofs MAY be P2PK-locked to a user's main public key.

To allow users to unlock P2PK-locked tokens without compromising their main Nostr private key, signers may OPTIONALLY support the signing of a stringified NUT-10 well-known Secret as below.


### Secret Format

The format for a [NUT-10](https://github.com/cashubtc/nuts/blob/main/10.md) well-known `Secret` is:

```jsonc
[
kind <str>,
{
"nonce": <str>,
"data": <str>,
"tags": [[ "key", "value1", "value2", ...], ... ], // (optional)
}
]
```

It is packaged into the `Proof.secret` field as string-encoded json, which will be passed to the signer as the `proof_secret` to sign.

Signers MUST verify the `proof_secret` is a NUT-10 well-known `Secret` to ensure arbitrary strings are not signed.<br>
Note: `tags` is an optional key and may or may not be present.

### Signature for NIP-07 signers
A NIP-07 signer takes a `proof_secret` string and returns the SHA256 `hash` of `proof_secret`, Schnorr `sig` of `hash`, `pubkey` of signer

```
async window.nostr.nip60.signSecret(proof_secret: string): { hash: string, sig: string, pubkey: string }
```

### Signature for NIP-46 signers
A NIP-46 signer takes an array containing a `proof_secret` string and returns a stringified JSON object containing SHA256 `hash` of `proof_secret`, Schnorr `sig` of `hash`, and `pubkey` of signer

***Command:*** `nip60_sign_secret`<br>
***Params:*** `[<proof_secret>]`<br>
***Result:*** `json_stringified({ hash: <sha256_of_proof_secret>, sig: <schnorr_of_hash>, pubkey: <pubkey> })`