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

Add x-only ECDH support to ecdh module #1198

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

sipa
Copy link
Contributor

@sipa sipa commented Jan 27, 2023

Built on top of #1118, this adds API calls to the ecdh module to support x-only ECDH. When pubkey decompression is included in the ECDH benchmark, it's roughly 10% faster to do x-only ECDH.

The default hash function included uses SHA256(shared_x_coordinate) as output function.

@real-or-random
Copy link
Contributor

real-or-random commented Jan 28, 2023

Tried to fix the MSVC issues... let's see what CI says.

See commit messages. I verified locally that static linking doesn't break and just outputs a warning.

@hebasto
Copy link
Member

hebasto commented Jan 28, 2023

Tried to fix the MSVC issues... let's see what CI says.

See commit messages. I verified locally that static linking doesn't break and just outputs a warning.

FWIW, the last commit fixes this branch build with MSVC when using CMake-based build system as well: https://cirrus-ci.com/build/6082649656131584

@sipa
Copy link
Contributor Author

sipa commented Jan 28, 2023

@real-or-random Thanks for the fixes. I've removed my earlier attempt from the commit history. If this works, I'll extract the non-ECDH-related parts from this PR and submit them separately.

# ifdef SECP256K1_BUILD
# ifdef DLL_EXPORT
# define SECP256K1_API __declspec (dllexport)
# define SECP256K1_API_VAR extern __declspec (dllexport)
# endif
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if defined(SECP256K1_BUILD) && !defined(DLL_EXPORT), then SECP256K1_API{,_VAR} will be undefined?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is handled in #ifndef block in line 163. Maybe the same logic can be written in a more readable structure, feel free to reorganize if you see a better method.

@real-or-random
Copy link
Contributor

real-or-random commented Jan 28, 2023

We should probably move my two build/ci commits in a separate commit. At least the build commit fixes a real build issue that we simply haven't encountered so far, because none of our "user" binaries (bench+examples) have used variables exported from the variable so far (but just functions).

(I can take care of that, and I still want to rethink one detail here.)

@sipa
Copy link
Contributor Author

sipa commented Jan 28, 2023

@real-or-random Yeah, I think both of your commits should be submitted as a separate PR. Perhaps the benchmark change here should also (as ECDH benchmarking without including pubkey decoding is misleading), so I was planning to do those 3. It won't be before tonight though, so if you want to, go ahead.

@sipa
Copy link
Contributor Author

sipa commented Jan 29, 2023

@real-or-random Actually since both of the commits are yours, and perhaps you want to make some changes, perhaps you should open a PR for them?

I'll rebase this and/or open the ECDH benchmark change as a follow-up then.

@real-or-random
Copy link
Contributor

@real-or-random Actually since both of the commits are yours, and perhaps you want to make some changes, perhaps you should open a PR for them?

Yep, I'll take care of that!

@sipa
Copy link
Contributor Author

sipa commented Feb 6, 2023

@real-or-random Ping?

Yep, I'll take care of that!

@real-or-random
Copy link
Contributor

@real-or-random Ping?

Yep, I'll take care of that!

Will do today or tomorrow!

real-or-random added a commit that referenced this pull request Feb 21, 2023
…from DLLs

e433034 ci: Shutdown wineserver whenever CI script exits (Tim Ruffing)
9a5a611 build: Suppress stupid MSVC linker warning (Tim Ruffing)
739c53b examples: Extend sig examples by call that uses static context (Tim Ruffing)
914276e build: Add SECP256K1_API_VAR to fix importing variables from DLLs (Tim Ruffing)

Pull request description:

  ... and more Windows fixes, please see the individual commits.

  The fixed issues were discovered in #1198.

ACKs for top commit:
  sipa:
    utACK e433034
  hebasto:
    ACK e433034, tested on Windows using [CMake](#1113) (which means that the 3rd commit is reviewed only, but not tested). FWIW, `LNK4217` warnings have been indeed observed.

Tree-SHA512: ce7845b106190cdc517988c30aaf2cc9f1d6da22904dfc5cb6bf4ee05f063929dc8b3038479e703b6cebac79d1c21d0c84560344d2478cb1c1740087383f40e3
@sipa
Copy link
Contributor Author

sipa commented Sep 19, 2023

@real-or-random

Will do today or tomorrow!

Never mind, rebased.

@jonasnick jonasnick added this to the 0.4.1 or 0.5.0 milestone Sep 20, 2023
@real-or-random
Copy link
Contributor

Concept ACK

Not entirely sure if there's demand for this, but we have it in the code base, and we have an ECDH module already, so I think it's pragmatic to expose this.

But this should hash both public keys into the shared secret. :)

@real-or-random real-or-random removed this from the 0.4.1 or 0.5.0 milestone Nov 20, 2023
@Sjors
Copy link
Member

Sjors commented Jan 5, 2024

Concept ACK.

Stratum v2 uses x-only ECDH (but not ElligatorSwift), so this would be quite useful.

I'll try if I can get this PR to work with bitcoin/bitcoin#28983

@sipa
Copy link
Contributor Author

sipa commented Jan 5, 2024

@Sjors This reminds me to pick this up again. We agreed that the interface needed a rewrite to use the safer approach the ellswift module uses (with a default hasher that includes the two pubkeys). I'm sure that whatever Sv2 uses can be adapted to fit in that model.

@Sjors
Copy link
Member

Sjors commented Jan 5, 2024

When naively performing ECDH with x-only keys, by just converting it to a compressed key that starts with 0x02, are the two sides supposed to get the same result?

ECDH(Alice_priv, Bob_pub_x) == ECDH(Bob_priv, Alice_pub_x)

Or only if Alice_priv and Bob_priv are chosen such that their public key has even Y, i.e. the compressed key starts with 0x02? Or is that not guaranteed at all?

@sipa
Copy link
Contributor Author

sipa commented Jan 5, 2024

@Sjors That will work. In other words, negating the private key of one of the sides (or of both sides) won't change the resulting shared X coordinate. It will change the Y coordinate of the resulting shared point, but in x-only ECDH you normally ignore that Y coordinate.

@Sjors
Copy link
Member

Sjors commented Jan 5, 2024

Mmm, but when using secp256k1_ecdh it does matter, doesn't it? Because the default ecdh_hash_function_sha256 uses the y-coordinate (version = (y32[31] & 0x01) | 0x02;).

Is that function based on any RFC or existing standard?

@sipa
Copy link
Contributor Author

sipa commented Jan 5, 2024

@Sjors Not that I know of. What does Sv2 use?

@Sjors
Copy link
Member

Sjors commented Jan 5, 2024

@sipa the spec is ambiguous on the ECDH details: https://github.com/stratum-mining/sv2-spec/blob/main/04-Protocol-Security.md#4311-ec-point-encoding-remarks

The Template Provider PR above uses ecdh_hash_function_sha256: bitcoin/bitcoin@27928db (link to commit since I'm about to refactor this)

When you call that with a private key that has an odd corresponding public key, then both sides of the connection will generate a different output for CKey::ECDH(). That in turns breaks the cypher.

@sipa
Copy link
Contributor Author

sipa commented Jan 5, 2024

@Sjors Heh, it's not specified how the shared point is serialized? That's worth addressing in the spec if possible (... or if it can still be changed, use ellswift?).

In any case, yes, if the full compressed point serialization of the shared point is used as secret, then you need to make sure the private key matches the (full) public key. That means it's not actually x-only ECDH, and this PR (or its envisioned successor) won't be usable, as it doesn't even compute the resulting shared Y coordinate.

@Sjors
Copy link
Member

Sjors commented Jan 5, 2024

I think the spec can still be modified / clarified. It should probably only use the x-component of the shared point. That seems more consistent with the use of x-only public keys in the rest of the sv2 spec.

@sipa
Copy link
Contributor Author

sipa commented Jan 5, 2024

@Sjors Is it an option to use ellswift negotiation instead? It's effectively a drop-in replacement for ECDH, except the public keys are 64 bytes instead of 32. Depending on how exactly Noise is being used to encode messages boundaries, that may actually be sufficient to make Sv2 have a pseudorandom bytestream.

@Sjors
Copy link
Member

Sjors commented Jan 6, 2024

On the Bitcoin Core side that would be trivial to add support for. The Stratum Reference Implementation is written in Rust, is there already a library for that? Or I guess it would use libsecp indirectly anyway?

@sipa
Copy link
Contributor Author

sipa commented Jan 7, 2024

@Sjors rust-secp256k1 appears to have ellswift bindings, but I don't know anything about Rust myself.

* data: arbitrary data pointer that is passed through to hashfp
* (can be NULL for secp256k1_ecdh_xonly_hash_function_sha256).
*
* The function is constant time in seckey. It is not constant time in xpubkey, hashfp, or the output.
Copy link
Contributor

@real-or-random real-or-random Feb 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I truly hope that it's constant time in the output (if hashfp is constant time).

@Sjors
Copy link
Member

Sjors commented Feb 7, 2024

There's pretty good progress in Stratum v2 on switching to EllSwift for both encoding the key on the wire and performing ECDH, so we probably won't need this.

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

Successfully merging this pull request may close these issues.

None yet

5 participants