-
Notifications
You must be signed in to change notification settings - Fork 602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NIP-111: Nostr-specific Private Keys from Deterministic Wallet Signatures (Sign-in-With-X) #268
base: master
Are you sure you want to change the base?
Conversation
Seems a bit risky that the web app would have the private key, unless this got implemented in, e.g., Metamask. But if we are going down that road, perhaps Metamask could just implement NIP-07, and use this method under the hood. In any case, do we really want to open the door to putting various key generation methods into their own NIPs? What about a NIP to turn a BTC private key into a nostr private key, and a NIP to turn a Monero private key into a nostr private key, and a NIP to turn a NANO private key into a nostr private key, etc... On a further thought, perhaps each app can just implement their own method of: |
See also #258 for the inverse problem. |
I agree the only way for this to work would be if this was done on Metamask directly, and Metamask implemented NIP-07. |
Thanks for feedback @barkyq @fiatjaf 🙏
It's less $ risker compared to reusing same ETH keys in Nostr clients. This is optional specs for web/mobile Nostr clients and
We can update this as Chain Agnostic Improvement Proposals (CAIP) approach to support ALL coins/chains compatible with RFC6979 like deterministic signature. Example using BIP44 (SLIP44) coin type and EIP155 chain ID. let info1 = `bip44:${coin_type}:${username}:${address}`;
let info2 = `eip155:${chain_id}:${username}:${address}`;
let info3 = `cosmos:${hub_id}:${username}:${address}`; // not sure about this, have to lookup
//...
let salt1 = await sha256(`bip44:${coin_type}:${username}:${password?password:""}:${last_32bytes_ofSignatureHex}`);
let salt2 = await sha256(`eip155:${chain_id}:${username}:${password?password:""}:${last_32bytes_ofSignatureHex}`);
//... |
We're working on different BIP47 "like" stealth address generation too, more details at #258 (comment)
There's "Metamask Flask" plugin for Nostr, Schnorr Snap. MM-Flask is experimental wallet not ready for average users, it will take more time for major coin-wallets to implement Nostr+schnorr feature. Can't wait for major wallet provider to implement that, & hope they don't reuse their coin-keys for Nostr again. This specification is for Updating chain and account identifiers to as defined in CAIP-02:Blockchain ID Specification and CAIP-10:Account ID Specification.
Example: CAIP-10, CAIP-02 with NIP02/NIP05 user identifiers.
Still WIP, Example let nostr = widow.nostr || nostrTools ;
let coinWallet = await connectEthers(window.ethereum);
let username = 'me@example.com';
let password = 'opt#password';
let pubkey = await nostr.nipxx.newIdentity(username, password="", chainType="eip155", coinWallet="");
// wrapped as nipxx.loginWithX(...) function.
// registration: set new nip02 and nip05 records for this pubkey.
// login: verify if there's matching nip02 and nip05 records. |
We would like to report major updates to our NIP-XX proposal and again seek your feedback on the following:
We'd love to hear back from you with your thoughts and comments on this PR! Thank you! |
Is this method of generating keys a standard among altcoins? |
No, I wouldn't say so. But it is standard and well-known in general Cryptography. I think @0xc0de4c0ffee might be more aware of previous implementations of it, if any, in cryptosphere. I hope he will comment here on it. |
It's fully chain agnostic There are few Ethereum dapps using straight Example from umbra.js stealth payment codes. We're signing stuffs from both ** err updated typo |
Hi @fiatjaf, Hope you are doing good. Dostr client is nearing its official launch (Mar 31). In reality, the client is already online at:
for earlybirds. There won't be any drastic changes to the client from now on other than cosmetic fine-tuning of the UI/UX. With respect to the NIP:
This NIP is in its final boss form from our side 😊 |
@sshmatrix are you still refactoring the signing message? I like this idea and I am implementing at digi-monkey/flycat-web#82, I will hope the message can be finalized and not changed again since I am going to merge the PR and rollout this feature |
- Connected Ethereum wallet Signer **MUST** be EIP-191 and RFC-6979 compatible. | ||
- The `message` **MUST** be string formatted as | ||
``` | ||
`Log into Nostr client as '${username}'\n\nIMPORTANT: Please verify the integrity and authenticity of connected Nostr client before signing this message\n\nSIGNED BY: ${caip10}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused, is this "inspired by" Sign-In With Ethereum/CAIP-122 or is it meant to be conformant to one or both of those two specs? If the latter was intended, the message should probably conform the CAIP-122/EIP-4361 ABNF, which could include the entire message
(with \n
s removed) in the statement
field, use the salt
value for nonce
, and info
as first entry in the resources
array (not really sure what to do with inputKey
, as I'm unclear on its exact function on a cursory read-through). If it's not too late to go in that direction, I think it might have some benefits, such as being displayed to metamask users in the familiar, locked-down "Sign-In With Ethereum" modal rather than as a generic "personal_sign" modal... which only displays when presented with a personal_sign message
matching the ABNF :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And apologies for not reading this sooner! Exciting work, in any case, supportive of the general direction and thankful to see CAIP-10 being used as the "export format" for addresses of signers 💪
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @bumblefudge! We intended to conform to CAIP-122 as much as possible but we had to strip all the variable quantities from the message
format to retain deterministic nature of key derivation. In some sense, this implementation is not really "Sign-In" but more of "Ephemeral KeyGen and then Sign-In", and hence the necessary deviation from the standard. Our implementation requires that the verifiable signature is static.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the problem with an ABNF-based syntax is that you can't deviate and still get interop with other SIWX libraries or take advantage of SIWX support built into Metamask! Can I suggest hard-coding conformant dummy values into the spec and template rather than removing the key/value pairs that you don't need, so that the message can still conform to the ABNF and get displayed to the users as a SIWX message? I would note that ephemeral keygen is already baked into the SIWX standard, and is being used for that exact usecase by most implementers (the generated ephemeral public key is usually included as a value in the Resources
array, although this isn't really mentioned explicitly in the specification itself!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused, is this "inspired by" Sign-In With Ethereum/CAIP-122 or is it meant to be conformant to one or both of those two specs? If the latter was intended, the message should probably conform the CAIP-122/EIP-4361 ABNF, which could include the entire message (with
\n
removed) in the statement field, use the salt value for nonce, and info as first entry in the resources array (not really sure what to do with inputKey, as I'm unclear on its exact function on a cursory read-through).
@bumblefudge 🙏
Should we remove CAIP122 ref as we can't pass full strict ABNF? or req all as new CAIP?
We actually started as basic signature request before upgrading to full CAIP122/ERC4361 format but had to remove all extradata for deterministic keys as they are too strict to fit in all.. So it's now back to generic "personal_sign" modal for chain agnostic "sign-in-with-x" in Nostr context, internally it's using deterministic signature from wallet to generate "app specific deterministic keys" across all Nostr clients.
We could fill in all ABNF required formats with deterministic/fixed values but we can't pass URI
validation in wallets, and "${service} wants you to sign in with <chain> account: \n<addr>\n...must:have
" text message for ALL web2+3 D/Apps is too strict for our deterministic keygen, web3+dapps are not supposed to have single URLs/apps as entry point..
"Important: .....\n\n" is supposed to be "Warning! ..." statement, it's not key: value. All other extradata is wrapped in SIGNED BY : ${CAIP10}
, & our msg is simple 3 blocks <title>\n\n<statement>\n\n<key:value>...
I would note that ephemeral keygen is already baked into the SIWX standard, and is being used for that exact usecase by most implementers (the generated ephemeral public key is usually included as a value in the Resources array, although this isn't really mentioned explicitly in the specification itself!)
Can you add some ref codes/links for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could fill in all ABNF required formats with deterministic/fixed values but we can't pass
URI
validation in wallets, and "${service} wants you to sign in with <chain> account: \n<addr>\n...must:have
" text message for ALL web2+3 D/Apps is too strict for our deterministic keygen, web3+dapps are not supposed to have single URLs/apps as entry point..
URI
is definitely a bigger issue and it hadn't come to my mind before. While timestamp
and nonce
can be replaced with placeholders, URI
is used by Metamask for its community-audited safe dApp list. This is problematic for dApps or services without a unique entry point. CAIP122 is too strict for all use-cases and pretty much a death sentence for the deterministic use-case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't the uri be:
https://github.com/nostr-protocol/nips/blob/master/111.md
? It doesn't need to be on the domain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't the uri be: https://github.com/nostr-protocol/nips/blob/master/111.md ? It doesn't need to be on the
domain
That's not a bad idea honestly but it will make users highly suspicious and wary of a service with 1/1/1970 in timestamp and a GitHub link in URI. I personally won't sign and subscribe to such a service at first glance. I believe there is room for a new CAIP detailing a separate signature format standard for deterministic use-cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't the uri be: https://github.com/nostr-protocol/nips/blob/master/111.md ? It doesn't need to be on the
domain
When we connect MM at https://app.dostr.eth.limo
it'll check and add "WARNING" if connected domain isn't matching domain
URL. It's good feature for web2 & web3 apps with single point of entry but for our use case we're adding extra user info & pw with static signature request as basic security.
It all works as plaintext "sign in with xyz on Nostr" signature request so we're missing all SWIx interface/features.
- it's better if we explain why we're doing this, our keygen design is inspired by Umbra cash & old Whisper(ssh) newKeypair/ newIdentity function. We use
window.ethereum
to sign eth tx/permits then use deterministic keys inwindow.nostr
to send that over Nostr relays for off-chain features like stealth payments, DeFi, NFT markets, alt-mempool for AA, xyz services, bundlers/bots, games...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
personally I think if we don't need timestamp, adding a placeholder for it is not a good idea.
Hi @digi-monkey, the message contained in the present draft is "final". It won't be changed, we hope. We have adopted the same on Dostr client and frozen it. There was a typo in the draft however and we have fixed it. It didn't affect the implementation apart from a mislabeling of @bumblefudge Implementing CAIP-122 as is won't work in this case, since we need the final key output to be deterministic. Adding the |
apologies that I missed this notification and wasn't able to make these suggestions before final status! if SIWX conformance is of use, maybe it's worth a superceding spec or an extension spec that puts the same inputs into a conformant |
I was thinking precisely the same thing! Perhaps it is worth an extension spec that provides deterministic usage of SIWx. We have CAIP-111 in the works (pretty much ready) and will open a PR soon. I will have a discussion with my co-dev about message formatting and report back. Thanks for your comments! Much appreciated @digi-monkey You might want to hold your horses there 🤭 |
Oh! Actually I meant an extension NIP, but hey, maybe an extension-CAIP* might make just as much sense. I would also add that if the NIPs elaborate enough complexity and cohesion that there are nostr-enabled wallets, signing methods, etc, it might some day make sense to create a Nostr namespace, where you can define a profile for CAIP-10 (syntax of a URN scheme for CAIP-10 encodings of nostr accounts/pubkeys), CAIP-122 (if a Nostr app which held a private key wanted to "sign in with nostr" to another service), etc etc.
|
Hi @bumblefudge, linking the answer to your questions here: #268 (comment). GitHub notifications are unreliable on multiple threads |
NIP-111: Deterministic Private Key Generation from Ethereum Wallet Signature
Example code:
** updated url & example to latest specs under review