-
Notifications
You must be signed in to change notification settings - Fork 1k
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
base: master
Are you sure you want to change the base?
Conversation
e18ff7c
to
090b20b
Compare
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 |
e5479c1
to
e7e86fe
Compare
@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. |
include/secp256k1.h
Outdated
# ifdef SECP256K1_BUILD | ||
# ifdef DLL_EXPORT | ||
# define SECP256K1_API __declspec (dllexport) | ||
# define SECP256K1_API_VAR extern __declspec (dllexport) | ||
# endif |
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.
What if defined(SECP256K1_BUILD) && !defined(DLL_EXPORT)
, then SECP256K1_API{,_VAR}
will be undefined?
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.
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.
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.) |
@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. |
@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. |
Yep, I'll take care of that! |
@real-or-random Ping?
|
Will do today or tomorrow! |
…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
e7e86fe
to
a732222
Compare
Never mind, rebased. |
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. :) |
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 |
@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. |
When naively performing ECDH with x-only keys, by just converting it to a compressed key that starts with
Or only if |
@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. |
Mmm, but when using Is that function based on any RFC or existing standard? |
@Sjors Not that I know of. What does Sv2 use? |
@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 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 |
@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. |
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. |
@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. |
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? |
@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. |
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 truly hope that it's constant time in the output (if hashfp is constant time).
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. |
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.