aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordhruv <856960+dhruv@users.noreply.github.com>2022-07-22 10:08:01 -0700
committerPieter Wuille <pieter@wuille.net>2023-06-23 14:22:39 -0400
commit2e5a8a437cf9ac78548891e61797b394571e27ae (patch)
tree55df95ff33270e561892b1b8385f16f3006a0b31
parentc3ac9f5cf413e263803aac668a90a4ddd7316924 (diff)
downloadbitcoin-2e5a8a437cf9ac78548891e61797b394571e27ae.tar.xz
Fuzz test for Ellswift ECDH
Co-authored-by: Pieter Wuille <bitcoin-dev@wuille.net>
-rw-r--r--src/pubkey.h10
-rw-r--r--src/test/fuzz/key.cpp59
2 files changed, 69 insertions, 0 deletions
diff --git a/src/pubkey.h b/src/pubkey.h
index 90b2204905..d8d5e3d85b 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -311,6 +311,16 @@ public:
static constexpr size_t size() { return SIZE; }
auto begin() const { return m_pubkey.cbegin(); }
auto end() const { return m_pubkey.cend(); }
+
+ bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
+ {
+ return a.m_pubkey == b.m_pubkey;
+ }
+
+ bool friend operator!=(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
+ {
+ return a.m_pubkey != b.m_pubkey;
+ }
};
struct CExtPubKey {
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
index 5599262836..25ea547435 100644
--- a/src/test/fuzz/key.cpp
+++ b/src/test/fuzz/key.cpp
@@ -22,8 +22,10 @@
#include <array>
#include <cassert>
+#include <cstddef>
#include <cstdint>
#include <numeric>
+#include <optional>
#include <string>
#include <vector>
@@ -324,3 +326,60 @@ FUZZ_TARGET_INIT(ellswift_roundtrip, initialize_key)
assert(key.VerifyPubKey(decoded_pubkey));
}
+
+FUZZ_TARGET_INIT(bip324_ecdh, initialize_key)
+{
+ FuzzedDataProvider fdp{buffer.data(), buffer.size()};
+
+ // We generate private key, k1.
+ auto rnd32 = fdp.ConsumeBytes<uint8_t>(32);
+ rnd32.resize(32);
+ CKey k1;
+ k1.Set(rnd32.begin(), rnd32.end(), true);
+ if (!k1.IsValid()) return;
+
+ // They generate private key, k2.
+ rnd32 = fdp.ConsumeBytes<uint8_t>(32);
+ rnd32.resize(32);
+ CKey k2;
+ k2.Set(rnd32.begin(), rnd32.end(), true);
+ if (!k2.IsValid()) return;
+
+ // We construct an ellswift encoding for our key, k1_ellswift.
+ auto ent32_1 = fdp.ConsumeBytes<std::byte>(32);
+ ent32_1.resize(32);
+ auto k1_ellswift = k1.EllSwiftCreate(ent32_1);
+
+ // They construct an ellswift encoding for their key, k2_ellswift.
+ auto ent32_2 = fdp.ConsumeBytes<std::byte>(32);
+ ent32_2.resize(32);
+ auto k2_ellswift = k2.EllSwiftCreate(ent32_2);
+
+ // They construct another (possibly distinct) ellswift encoding for their key, k2_ellswift_bad.
+ auto ent32_2_bad = fdp.ConsumeBytes<std::byte>(32);
+ ent32_2_bad.resize(32);
+ auto k2_ellswift_bad = k2.EllSwiftCreate(ent32_2_bad);
+ assert((ent32_2_bad == ent32_2) == (k2_ellswift_bad == k2_ellswift));
+
+ // Determine who is who.
+ bool initiating = fdp.ConsumeBool();
+
+ // We compute our shared secret using our key and their public key.
+ auto ecdh_secret_1 = k1.ComputeBIP324ECDHSecret(k2_ellswift, k1_ellswift, initiating);
+ // They compute their shared secret using their key and our public key.
+ auto ecdh_secret_2 = k2.ComputeBIP324ECDHSecret(k1_ellswift, k2_ellswift, !initiating);
+ // Those must match, as everyone is behaving correctly.
+ assert(ecdh_secret_1 == ecdh_secret_2);
+
+ if (k1_ellswift != k2_ellswift) {
+ // Unless the two keys are exactly identical, acting as the wrong party breaks things.
+ auto ecdh_secret_bad = k1.ComputeBIP324ECDHSecret(k2_ellswift, k1_ellswift, !initiating);
+ assert(ecdh_secret_bad != ecdh_secret_1);
+ }
+
+ if (k2_ellswift_bad != k2_ellswift) {
+ // Unless both encodings created by them are identical, using the second one breaks things.
+ auto ecdh_secret_bad = k1.ComputeBIP324ECDHSecret(k2_ellswift_bad, k1_ellswift, initiating);
+ assert(ecdh_secret_bad != ecdh_secret_1);
+ }
+}