Skip to content
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

Derive ETH address from existing pubkey #258

Closed

Conversation

kernel1983
Copy link

I find a smarter way after PR https://github.com/nostr-protocol/nips/pull/254/files

The solution is from the math.

@endaye
Copy link

endaye commented Feb 16, 2023

If the above formula is valid, can we also derive the Bitcoin address from npub?

@Egge21M
Copy link
Contributor

Egge21M commented Feb 16, 2023

NACK - Adding various crypto support on a protocol level is unnecessary bloat. Clients could give whatever addresses they want to their users by utilising NIP-06 for example and putting this stuff in kind-0 events if they really wanted to...

@kernel1983
Copy link
Author

I can borrow an account with NFT and publish a signature. However, I dont own that private key.

NACK - Adding various crypto support on a protocol level is unnecessary bloat. Clients could give whatever addresses they want to their users by utilising NIP-06 for example and putting this stuff in kind-0 events if they really wanted to...

OK, but it is not important any more.

I realized that nostr removed the 02/03 prefix before the 32bytes public key.
In the formula y^2 = x^3 + 7, the prefix indicates which y. (https://en.bitcoin.it/wiki/Secp256k1)
Waiting for nostr fixing this.

BTW, I see a relay hard code the '02' prefix: https://github.com/johnny423/pyrelay/blob/0cf683b1ea376c8ee69fd174a9699578bf2cfba6/pyrelay/nostr/event.py#L109
Sorry to realize that.

Now #254 is a better solution.

@Egge21M
Copy link
Contributor

Egge21M commented Feb 16, 2023

Waiting for nostr fixing this.

Not a pro on the cryptography behind it, but I think you are confusing ECDSA and Schnorr... Schnorr public keys are supposed to be 32-bytes. See BIP-340 for more information on this

@kernel1983
Copy link
Author

Waiting for nostr fixing this.

Not a pro on the cryptography behind it, but I think you are confusing ECDSA and Schnorr... Schnorr public keys are supposed to be 32-bytes. See BIP-340 for more information on this

Thanks for comment on this.
Now I know it is impossible unless we start with the private key.

@kernel1983
Copy link
Author

Wait, it is not over.

This NIP aims to display the user's eth address of the current 32bytes private key.
The problem is that we cannot directly derive the address from the 32bytes public key as the removed prefix can be either '02' or '03'.

However, if we place the eth address in the event, we can verify the correctness of the eth address by two calc: '02'+pubkey or '03'+pubkey. If one of the calculations is equal to the eth address in the event, the address is verified.

I'm going to make a new commit to update the PR.

@Egge21M
Copy link
Contributor

Egge21M commented Feb 17, 2023

If you publish the address inside an event, you sign it with your private key. Why would you need additional verification? Why does the address need to be derived from your pubkey? You can put any address you control in the event.

@kernel1983
Copy link
Author

kernel1983 commented Feb 17, 2023

If you publish the address inside an event, you sign it with your private key. Why would you need additional verification? Why does the address need to be derived from your pubkey? You can put any address you control in the event.

Yes, if we need to put any address we control in a event, a signature is required. To prove you own the address(not using other's signature), it requires to include the signature periodically.

If the eth address is from the private key you are using in nostr, every nostr event signature indicates you own the private key. However, you dont need to publish the eth addr in every event. User can choose to reveal their eth address when necessory. Just like we can choose to not upload the profile pic at the beginning.

They eth address can be useful, if a user accepts payment, or a relay checks the payment from a user through a eth addressed chain. User may also send their NFT to the eth addr by nostr private key, so the client can show the NFT badges when they are posting or DM or in a group chat.
Other chains may also use the similiar way to add their chain/wallet address if the crypto level supports.

@Egge21M
Copy link
Contributor

Egge21M commented Feb 17, 2023

I still see no reason to a) have a seperate NIP per shitcoin b) derive shitcoin keys from nostr keys.

As described earlier clients could use NIP-06 to derive different currency keys as well as a nostr key from a single root key and reveal payment addresses inside kind-0 events. See: #262

@kernel1983
Copy link
Author

a) have a seperate NIP per shitcoin

It depends on their key curve and others. I dont care.

b) derive shitcoin keys from nostr keys

Since the relay can not get the private key, it is hard to verify.

Let's make it clear, I'm not a fan of ETH. I love PoW.
I do this because more people can get benifit from both nostr and eth ecosystem.

@kernel1983
Copy link
Author

@barkyq Thanks for mention.

The goal of this proposal is not to derive new private key from existing key.
We want to make an address with existing nostr private key so that an nostr account can hold assets such as NFT or token from various chains.
BTC address can simplely derive from the 32bytes pubkey. However ETH address requires uncompressed 64bytes public key or 33bytes public key. It means we can find two possible ETH addresses by insert '02' or '03' before the pubkey.

Now, since the address cannot be calcuated, the current suggestion is let the private key owner write down the derived address. The verification of the address needs two round of calc, however it is still acceptable.

Waiting for more feedback before revising the markdown.

@0xc0de4c0ffee
Copy link

We want to make an address with existing nostr private key so that an nostr account can hold assets such as NFT or token from various chains.

Reusing same keys for multiple chain/purposes isn't good for privacy and security...

#268 author here 🙏 ,
We're also working on another bit-complicated ephemeral address generator for our HTLC based counterfactual-stealth payment channels over Nostr. It's similar to BIP47, and works for all secp256k1 chains..

tldr; version

  • Sender: ecmultiply Receiver's public key with a random number to generate new public key, encrypt and send that random number to receiver.
  • Receiver: ecmultiply their private key with Sender's random number to generate corresponding private key.

Bob is sending 0.1 $COIN to Alice

Bob Side

  • Bob generates a random number,
  • ec-multiply Alice's pubkey with that random number to generate new pubkey/address,
  • send 0.1 $COIN to new addr,
  • transmit random number to Alice over encrypted channel.

Alice side

  • Alice receives random number from Bob,
  • ec-multiply original private key with random number to derive corresponding private keys
  • withdraw 0.1 $coin from Bob using new private key.

For ref, there's docs/codes from umbra.js and half baked-half potato blog post from Vitalik Buterin, An incomplete guide to stealth addresses. One down side on ETH/EVM chains if you're sending tokens/nfts, as there's no gas fees in new addr to transfer that out. (*most tokens don't have permit/2 signature feature)

Example pseudo/js code based on umbra.js docs.

// ---- Bob side

// Alice's public key
// it's better to request fresh pub key and initialize as payment channel
const pubkey = alice.pubkey;

// Generate a random 32 bytes number, or increment last r value as nonce 
const randomNumber = new RandomNumber();
 
// EC Multiply Alice's public key with randomNumber
const newPubKey = pubkey.mulPublicKey(randomNumber);
 
// Send funds to that new address
console.log('Alice's new address: ', newPubKey.toAddr());

// Transmit `randomNumber` to Alice over encrypted  message
// Use ephemeral keys on both sides for privacy to transfer encrypted `randomNumber` value.
 
// ---- Alice Side 

// Received Bob's randomNumber over encrypted message
// Alice's original private key
const privKey = alice.privKey ;
 
// EC multiply private key with random number from Bob to generate corresponding private key 
const newPrivKey = PrivKey.mulPrivateKey(randomNumber);
 
// Access funds and confirm addresses match
console.log(newPubKey.toAddr() === newPrivKey.toAddr()); // true
console.log('Private key to access received funds: ', newPrivkey);

@kernel1983
Copy link
Author

Reusing same keys for multiple chain/purposes isn't good for privacy and security...

I get your point, but the eth address is only used for receiving NFTs. It only transfers OUT when the user decide to abandon the account.

Advance cryptography is fancy, but it is not KISS enough. Keep working on that!

@kernel1983
Copy link
Author

Hello all,

I updated the PR with a pubkey_prefix in the tags.
It should be simple enough and works with existing solution.

thanks

@fyookball
Copy link

You really should not do this. To echo what @0xc0de4c0ffee said, its bad for security, you can literally lose your crypto by re-using the same keys with different signature algorithms.

@staab
Copy link
Member

staab commented May 13, 2023

The consensus seems to be that this widens the scope of the protocol too much, and is a bad idea anyway. Maybe an external repository could be created with standards for deriving different kinds of addresses from one another?

@staab staab closed this May 13, 2023
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.

6 participants