-
Notifications
You must be signed in to change notification settings - Fork 37.7k
BIP324: CKey encode/decode to elligator-swift #23432
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
Conversation
734c97e
to
3e562de
Compare
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
Wrt a failed Win64 cross-compiled build. I've managed to successfully link --- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -507,8 +507,6 @@ libbitcoin_consensus_a_SOURCES = \
primitives/transaction.h \
pubkey.cpp \
pubkey.h \
- random.cpp \
- random.h \
script/bitcoinconsensus.cpp \
script/interpreter.cpp \
script/interpreter.h \
@@ -743,7 +741,7 @@ include_HEADERS = script/bitcoinconsensus.h
libbitcoinconsensus_la_SOURCES = support/cleanse.cpp $(crypto_libbitcoin_crypto_base_a_SOURCES) $(libbitcoin_consensus_a_SOURCES)
libbitcoinconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS)
-libbitcoinconsensus_la_LIBADD = $(LIBSECP256K1)
+libbitcoinconsensus_la_LIBADD = $(LIBSECP256K1) $(LIBBITCOIN_UTIL) $(BOOST_LIBS)
libbitcoinconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL
libbitcoinconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
Obviously, this workaround is suboptimal:
For better approach, probably source code re-organization should be considered. |
Pushed again to fix a CI issue. I had forgotten to appropriately rollback my Makefile.am changes. Ready for review. |
Removed randomness used in a fuzz test that was not derived from the fuzz seed. Ready for further review. |
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.
Concept ACK.
Encoding | Decoding |
---|---|
This PR introduces 2 pubkey functions EllSqEncode()
for encoding 33 byte/65 byte pubkey to a 64 byte Elligator square encoding and a constructor CPubKey
to decode the 64 byte Elligator square encoding to a 33 byte pubkey.
- In the unit test, a 33 byte/65 byte public key
original_pubkey
is computed from the private key and is fed intoEllSqEncode()
along with 32 random bytes to obtain 64 bytesellsq_encoded_pubkey
- Then decoding is done on the 64 bytes
ellsq_encoded_pubkey
using the CPubKey constructor to obtain a 33 bytesdecoded_pubkey
. - Finally it is checked if
original_pubkey
anddecoded_pubkey
are the same. Whenoriginal_pubkey
is uncompressed, the 33 bytesdecoded_pubkey
needs to be uncompressed to 65 bytes before the comparison.
src/test/fuzz/key.cpp
Outdated
return; | ||
} | ||
|
||
auto ellsq_bytes = buffer.first(64); |
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.
You could do a stronger test here: start with a pubkey drawn from the fuzz data, and if it is valid, elligator encode it (with additional randomness drawn from the fuzz data), decode it, and see if it matches the original pubkey.
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. Done!
src/test/fuzz/key.cpp
Outdated
|
||
{ | ||
std::array<uint8_t, 32> rnd32; | ||
memcpy(rnd32.data(), &random_uint256, 32); |
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.
random_uint256 is uniformly distributed, making it harder for the fuzz engine to discover potential edge 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.
Makes sense. Fixed. I ended up combining the encode/decode fuzzing.
src/test/fuzz/key.cpp
Outdated
|
||
FUZZ_TARGET_INIT(ellsq, initialize_key) | ||
{ | ||
if(buffer.size() < 64) { |
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.
You may install clang-format
and run the https://github.com/bitcoin/bitcoin/tree/master/contrib/devtools#clang-format-diffpy script to preempt whitespace nitpicking.
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.
Done.
Addressed review comments from @sipa and @MarcoFalke. Ready for further review. |
Rebased and updated src/secp256k1 to be up to date with the rebase on bitcoin-core/secp256k1#982 Ready for further review. |
src/test/fuzz/key.cpp
Outdated
CKey key; | ||
key.Set(key_bytes.begin(), key_bytes.end(), fdp.ConsumeBool()); | ||
|
||
(void)key.EllSwiftEncode(); |
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 could also decode back, and test that the public keys correspond (if you move the EllSwiftDecode
function to CPubKey
, for example).
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.
Added this check, but I opted to decode locally in the fuzz test so as to not add code to CPubKey
that would be used only for tests.
Latest push:
|
Rebased. Brought in changes from bitcoin-core/secp256k1#1129. |
Rebased. Brought in changes from bitcoin-core/secp256k1#1129. |
8034c67a48 Add doc/ellswift.md with ElligatorSwift explanation e90aa4e62e Add ellswift testing to CI 131faedd8a Add ElligatorSwift ctime tests 198a04c058 Add tests for ElligatorSwift 9984bfe476 Add ElligatorSwift benchmarks f053da3ab7 Add ellswift module implementing ElligatorSwift 76c64be237 Add functions to test if X coordinate is valid aff948fca2 Add benchmark for key generation 5ed9314d6d Add exhaustive tests for ecmult_const_xonly b69fe88d5e Add x-only ecmult_const version for x=n/d 427bc3c Merge bitcoin-core/secp256k1#1236: Update comment for secp256k1_modinv32_inv256 647f0a5 Update comment for secp256k1_modinv32_inv256 5658209 Merge bitcoin-core/secp256k1#1228: release cleanup: bump version after 0.3.0 28e63f7 release cleanup: bump version after 0.3.0 git-subtree-dir: src/secp256k1 git-subtree-split: 8034c67a48dc1334bc74ee4ba239111a23d9789e
Rebased. |
🐙 This pull request conflicts with the target branch and needs rebase. |
Closing for now. See #27479. |
3168b08 Bench test for EllSwift ECDH (Pieter Wuille) 42d759f Bench tests for CKey->EllSwift (dhruv) 2e5a8a4 Fuzz test for Ellswift ECDH (dhruv) c3ac9f5 Fuzz test for CKey->EllSwift->CPubKey creation/decoding (dhruv) aae432a Unit test for ellswift creation/decoding roundtrip (dhruv) eff72a0 Add ElligatorSwift key creation and ECDH logic (Pieter Wuille) 42239f8 Enable ellswift module in libsecp256k1 (dhruv) 901336e Squashed 'src/secp256k1/' changes from 4258c54..705ce7e (Pieter Wuille) Pull request description: This replaces #23432 and part of #23561. This PR introduces all of the ElligatorSwift-related changes (libsecp256k1 updates, generation, decoding, ECDH, tests, fuzzing, benchmarks) needed for BIP324. ElligatorSwift is a special 64-byte encoding format for public keys introduced in libsecp256k1 in bitcoin-core/secp256k1#1129. It has the property that *every* 64-byte array is a valid encoding for some public key, and every key has approximately $2^{256}$ encodings. Furthermore, it is possible to efficiently generate a uniformly random encoding for a given public key or private key. This is used for the key exchange phase in BIP324, to achieve a byte stream that is entirely pseudorandom, even before the shared encryption key is established. ACKs for top commit: instagibbs: reACK 3168b08 achow101: ACK 3168b08 theStack: re-ACK 3168b08 Tree-SHA512: 308ac3d33e9a2deecb65826cbf0390480a38de201918429c35c796f3421cdf94c5501d027a043ae8f012cfaa0584656da1de6393bfba3532ab4c20f9533f06a6
This PR adds the ability to encode
CPubKey
objects to their pseudorandom elligator-swift representation. Depends on bitcoin-core/secp256k1#1129.The first 2 commits enable the availability of that upstream code and will be removed once bitcoin-core/secp256k1#1129 is merged. Only last 3 commits need review here.