Skip to content

Conversation

@robwoodgate
Copy link
Contributor

@robwoodgate robwoodgate commented Apr 24, 2025

The PR clarifies and improves Nostr <---> Cashu interoperability by adding an optional signer signature for NUT-10 well-known secrets to NIP-60, NIP-07 and NIP-46

@fiatjaf
Copy link
Member

fiatjaf commented Apr 24, 2025

I didn't look into the specifics but in general this sounds like a good idea.

@robwoodgate

This comment was marked as off-topic.

@pablof7z
Copy link
Member

Thank you sir - happy to make any tweaks if required. The only thing I haven't addressed, which could perhaps be improved, is a way to rotate keys in NIP-60 kind 17375 and NIP-61 kind 10019 events.

The goal would be to retain older privkeys, so a wallet can still unlock any older proofs after rotating a key.

This could be accomplished in a number of backwards compatible ways:

OPTION A: allow multiple privkey entries in a Nostr tag-like way (latest first):

{
    "kind": 17375,
    "content": nip44_encrypt([
        [ "privkey", "hexkey", "olderhexkey", "oldesthexkey" ],
        [ "mint", "https://mint1" ],
        [ "mint", "https://mint2" ]
    ]),
    "tags": []
}

OPTION B: add xprivkey tags for older keys:

{
    "kind": 17375,
    "content": nip44_encrypt([
        [ "privkey", "hexkey"],
        [ "mint", "https://mint1" ],
        [ "mint", "https://mint2" ]
        [ "xprivkey", "olderhexkey"],
        [ "xprivkey", "oldesthexkey"],
    ]),
    "tags": []
}

OPTION C: add a single xprivkey with all older privkeys:

{
    "kind": 17375,
    "content": nip44_encrypt([
        [ "privkey", "hexkey"],
        [ "mint", "https://mint1" ],
        [ "mint", "https://mint2" ]
        [ "xprivkeys", "olderhexkey", "oldesthexkey" ],
    ]),
    "tags": []
}

In all cases, keys can be rotated, the current privkey for the kind 10019 pubkey is clear, but a wallet can still fall back to older keys if a Proof is still locked to them.

If you have a preference or alternative suggestion, am happy to include it in this PR

This is kinda already covered by the backup key event; what I do in my implementation is, in addition to the privkey in the 17375, I load all the non-replaceable backup wallet events -- main reason for creating these events is in case a wallet misbehaves and wipes the 17375 we want to have a way to find the old key.

I then put all the pubkeys of the privkeys I have in a map and if when I want to redeem a nutzap I check the map for the right privkey.

Functionally, this is like "rotating" but there's no

@robwoodgate
Copy link
Contributor Author

This is kinda already covered by the backup key event;

Thanks @pablof7z - Is that the 37375 addressable event I've seen floating around, or something else? Is there a PR or source I can see how this works?

I think, for now, I'll leave this PR as it is then. No sense trying to stuff too many changes in, though it's something that probably should be codified in the future.

@pablof7z
Copy link
Member

pablof7z commented Apr 27, 2025

This is kinda already covered by the backup key event;

Thanks @pablof7z - Is that the 37375 addressable event I've seen floating around, or something else? Is there a PR or source I can see how this works?

I think, for now, I'll leave this PR as it is then. No sense trying to stuff too many changes in, though it's something that probably should be codified in the future.

No, the 37375 was my overengineered-multi-wallet support, so basically its deprecated and replaced by 17375.

Wallet backup is kind:375: #1834

@robwoodgate
Copy link
Contributor Author

No, the 37375 was my overengineered-multi-wallet support, so basically its deprecated and replaced by 17375.

Wallet backup is kind:375: #1834

Great solution to the key rotation/backup issue... love it

@mikedilger
Copy link
Contributor

For nip46 I would just call it 'sign' and let it sign anything.

@robwoodgate
Copy link
Contributor Author

For nip46 I would just call it 'sign' and let it sign anything.

No, the goal is to complete Cashu<>Nostr integration in a protocol friendly way, not to open the doors to arbitrary string signing, which is discussed in depth here: #1842

@robwoodgate
Copy link
Contributor Author

Rebased to current master for easier merge

@robwoodgate
Copy link
Contributor Author

robwoodgate commented May 2, 2025

Implementations using nip60.signSecret():

@robwoodgate
Copy link
Contributor Author

Have rebased to master for easier merge. We have a fair range of apps supporting so far - can we please consider merging?

@robwoodgate
Copy link
Contributor Author

Rebased to master for easier merge.

@robwoodgate
Copy link
Contributor Author

robwoodgate commented Oct 31, 2025

Rebased to master for easier merge

@robwoodgate
Copy link
Contributor Author

robwoodgate commented Oct 31, 2025

@pablof7z - I understand from Calle that we should be using one proof per proof tag.

ie:

["proof", "serializedproof1"],
["proof", "serializedproof2"],

NOT:

["proof", "serializedproof1", "serializedproof2",...],

This is clarified in this PR too,

@robwoodgate robwoodgate changed the title Adds optional nip60.signSecret() and kind 10019 filter tag Adds optional nip60.signSecret() Oct 31, 2025
@robwoodgate
Copy link
Contributor Author

robwoodgate commented Oct 31, 2025

I have removed the NIP-61 tweaks from the PR, to make it less of an omnibus.

The related changes are covered by:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants