BIP324: Handshake prerequisites #23561

pull dhruv wants to merge 13 commits into bitcoin:master from dhruv:bip324-handshake changing 50 files +3272 −615
  1. dhruv commented at 10:50 pm on November 20, 2021: contributor

    Depends on #25361 for some constants, and on https://github.com/bitcoin-core/secp256k1/pull/1129 for ellswift integrated XDH but can be reviewed independently. Only the last 5 commits belong to this PR.

    This PR adds xonly ECDH and HKDF key derivation code for BIP324. Unit, bench and fuzz tests are included.

    The dependency tree for BIP324 PRs is here.

  2. DrahtBot added the label Build system on Nov 20, 2021
  3. DrahtBot added the label Utils/log/libs on Nov 20, 2021
  4. DrahtBot commented at 10:27 am on November 21, 2021: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK naumenkogs, PastaPastaPasta, theStack

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #27385 (net: extract Network and BIP155Network logic to node/network by jonatack)
    • #27294 (refactor: Move chain names to the util library by TheCharlatan)
    • #27254 (refactor: Extract util/fs from util/system by TheCharlatan)
    • #26684 (bench: add readblock benchmark by andrewtoth)
    • #25572 (refactor: Introduce EvictionManager and use it for the inbound eviction logic by dergoegge)
    • #25390 (sync: introduce a thread-safe generic container and use it to remove a bunch of “GlobalMutex"es by vasild)
    • #25268 (refactor: Introduce EvictionManager by dergoegge)
    • #23432 (BIP324: CKey encode/decode to elligator-swift by dhruv)
    • #23233 (BIP324: Add encrypted p2p transport {de}serializer by dhruv)

    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.

  5. naumenkogs commented at 7:14 am on November 22, 2021: member
    Concept ACK. Moving forward with BIP324 is a good idea, and this code seems to not have any negative/unexpected side-effects.
  6. dhruv renamed this:
    BIP324 handshake prerequisites
    BIP324: Handshake prerequisites
    on Nov 23, 2021
  7. in src/key.cpp:346 in 2d58b29346 outdated
    341+    }
    342+
    343+    ECDHSecret secret;
    344+    secret.resize(ECDH_SECRET_SIZE);
    345+
    346+    if (secp256k1_ecdh(secp256k1_context_sign, secret.data(), &pubkey_internal,
    


    sipa commented at 8:58 pm on November 23, 2021:
    The case of secp256k1_ecdh returning 0 corresponds to invalid input. That won’t happen here; I think you can assert instead and avoid the std::optional in the return type.

    dhruv commented at 8:24 pm on November 25, 2021:
    Done - still needed a boolean return value due to the other failure case above.
  8. in src/test/fuzz/key.cpp:310 in 042f771e16 outdated
    304@@ -305,4 +305,20 @@ FUZZ_TARGET_INIT(key, initialize_key)
    305             assert(key == loaded_key);
    306         }
    307     }
    308+
    309+    {
    310+        // Test ECDH computation with another key
    


    sipa commented at 9:01 pm on November 23, 2021:

    You could do a much stronger test: take two private keys as input fuzz data, compute the corresponding public keys, and compute the ecdh secrets from (sec1,pub2) and (sec2,pub1), and check that they match.

    It’s cryptographic data (hashes and EC operations), so this is very unlikely to actually uncover any bugs unless they’re very apparent, but this way the fuzz test actually verifies the full behavior we desire from these functions.


    dhruv commented at 8:24 pm on November 25, 2021:
    Done!
  9. in src/util/bip324.h:26 in 8d09fb5cc2 outdated
    21+    std::array<uint8_t, BIP324_KEY_LEN> responder_V; // k2b
    22+    std::array<uint8_t, BIP324_KEY_LEN> session_id;
    23+
    24+    // Takes ownership of the ECDH secret and wipes the ephemeral secret once
    25+    // the derivation is complete.
    26+    explicit BIP324Keys(ECDHSecret&& ecdh_secret, const Span<uint8_t>& initiator_hdata, const Span<uint8_t>& responder_hdata);
    


    sipa commented at 9:02 pm on November 23, 2021:
    Nit: pass Spans by value.

    dhruv commented at 8:24 pm on November 25, 2021:
    Done.
  10. in src/util/bip324.cpp:1 in 8d09fb5cc2 outdated
    0@@ -0,0 +1,36 @@
    1+// Copyright (c) 2021 The Bitcoin Core developers
    


    sipa commented at 9:10 pm on November 23, 2021:
    I’m not sure this belongs in util, it seems pretty specific to Bitcoin.

    dhruv commented at 8:24 pm on November 25, 2021:
    I moved this into net.{h|cpp} as that’s where it will be used. I didn’t particularly want to increase the length of those files, so please let me know if the right thing to do is to have it in src/bip324.{h|cpp}
  11. in src/util/bip324.h:15 in 8d09fb5cc2 outdated
    10+
    11+#include <array>
    12+
    13+constexpr size_t BIP324_KEY_LEN = 32;
    14+
    15+class BIP324Keys
    


    sipa commented at 9:19 pm on November 23, 2021:
    Not sure if a class for this is desirable in the first place. These keys shouldn’t be long-lived in any case (they’re only used to initialize the stream ciphers, and then destroyed). That can just as well be done with a simple function call?

    dhruv commented at 8:24 pm on November 25, 2021:
    Done.
  12. dhruv force-pushed on Nov 25, 2021
  13. dhruv commented at 8:25 pm on November 25, 2021: contributor
    Addressed review comments from @sipa. Ready for further review.
  14. in src/net.cpp:404 in 88185dc13b outdated
    400@@ -399,6 +401,38 @@ static CAddress GetBindAddress(SOCKET sock)
    401     return addr_bind;
    402 }
    403 
    404+bool derive_bip324_keys(ECDHSecret&& ecdh_secret, const Span<uint8_t> initiator_hdata, const Span<uint8_t> responder_hdata, BIP324Keys& derived_keys)
    


    naumenkogs commented at 8:31 am on December 6, 2021:
    Why snake case for function name derive_bip324_keys here?

    dhruv commented at 3:02 am on December 9, 2021:
    Oh oops. I don’t know why I did that. Updated.
  15. in src/net.cpp:442 in 88185dc13b outdated
    405+{
    406+    if (ecdh_secret.size() != ECDH_SECRET_SIZE) {
    407+        return false;
    408+    }
    409+
    410+    std::string salt{"bitcoin_v2_shared_secret"};
    


    naumenkogs commented at 8:35 am on December 6, 2021:
    The BIP currently refers to BitcoinSharedSecret. I guess to ack this, i’d have to see a new bip :)

    dhruv commented at 2:58 am on December 9, 2021:
    :) I am working on re-structuring it. It’s close. Will keep you updated here.
  16. alirezaayande referenced this in commit 0c85dc30e6 on Dec 7, 2021
  17. dhruv force-pushed on Dec 8, 2021
  18. dhruv commented at 3:02 am on December 9, 2021: contributor
    Addressed comments; Rebased with master to incorporate #23413. I am still investigating CI failures which seem like a timeout on Cirrus CI but re-running hasn’t helped (other recent open PRs seem to be seeing this error as well). Meanwhile, ready for further review.
  19. DrahtBot added the label Needs rebase on Dec 18, 2021
  20. dhruv force-pushed on Jan 21, 2022
  21. DrahtBot removed the label Needs rebase on Jan 21, 2022
  22. dhruv commented at 2:27 am on January 22, 2022: contributor
    Rebased against master. Ready for further review.
  23. in src/bench/ecdh.cpp:1 in 773cbc93b1 outdated
    0@@ -0,0 +1,30 @@
    1+// Copyright (c) 2021 The Bitcoin Core developers
    


    PastaPastaPasta commented at 9:34 am on February 7, 2022:
    nit: if you rebase this at some point, might as well update this

    dhruv commented at 1:09 am on April 15, 2022:
    Done.
  24. PastaPastaPasta commented at 9:38 am on February 7, 2022: contributor

    concept ACK / light utACK. I did a high level review, and everything makes sense to me.

    I do have 1 tiny nit

  25. DrahtBot added the label Needs rebase on Mar 3, 2022
  26. dhruv force-pushed on Mar 10, 2022
  27. DrahtBot removed the label Needs rebase on Mar 10, 2022
  28. dhruv commented at 1:30 am on March 11, 2022: contributor
    Rebased. Ready for further review.
  29. DrahtBot added the label Needs rebase on Apr 8, 2022
  30. dhruv force-pushed on Apr 9, 2022
  31. dhruv commented at 3:48 pm on April 9, 2022: contributor

    Rebased. git range-diff e0680bbce ea94adb 2a2cbfc1e

    Ready for further review.

  32. DrahtBot removed the label Needs rebase on Apr 9, 2022
  33. DrahtBot added the label Needs rebase on Apr 9, 2022
  34. dhruv force-pushed on Apr 13, 2022
  35. dhruv commented at 8:11 pm on April 13, 2022: contributor
    Rebased. Ready for further review.
  36. DrahtBot removed the label Needs rebase on Apr 13, 2022
  37. dhruv force-pushed on Apr 14, 2022
  38. dhruv commented at 4:10 pm on April 14, 2022: contributor
    Updated to use xonly ECDH as per changes being made to BIP324 before publication. Ready for further review.
  39. in configure.ac:1960 in f0b520b17c outdated
    1956@@ -1957,7 +1957,7 @@ LIBS_TEMP="$LIBS"
    1957 unset LIBS
    1958 LIBS="$LIBS_TEMP"
    1959 
    1960-ac_configure_args="${ac_configure_args} --disable-shared --with-pic --enable-benchmark=no --enable-module-recovery --enable-module-schnorrsig"
    1961+ac_configure_args="${ac_configure_args} --disable-shared --with-pic --enable-benchmark=no --enable-module-recovery --enable-module-schnorrsig --enable-module-ecdh -enable-experimental"
    


    fanquake commented at 4:17 pm on April 14, 2022:
    You can drop -enable-experimental. It should no-longer be required for --enable-module-ecdh, and note the missing - in any case.

    dhruv commented at 1:10 am on April 15, 2022:
    Thanks. Done.
  40. in src/key.cpp:367 in f0b520b17c outdated
    362+
    363+    hasher.Write(xonly_ecdh.data(), xonly_ecdh.size());
    364+
    365+    secret.resize(ECDH_SECRET_SIZE);
    366+    hasher.Finalize(secret.data());
    367+    memory_cleanse(xonly_ecdh.data(), ECDH_SECRET_SIZE);
    


    sipa commented at 5:07 pm on April 14, 2022:

    This is unnecessary, as it’s already using secure_allocator, which wipes memory on deallocation.

    That said, using a vector with secure_allocator is overkill here; you can just use an array (which doesn’t need allocation) - and then you do need the cleanse call.


    dhruv commented at 1:10 am on April 15, 2022:
    Done - simpler with array + cleanse.
  41. in src/test/net_tests.cpp:930 in f0b520b17c outdated
    925+    static const std::string strSecret2C = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g";
    926+    static const std::string initiator_hdata = "2deb41da6887640dda029ae41c9c9958881d0bb8e28f6bb9039ee9b7bb11091d62f4cbe65cc418df7aefd738f4d3e926c66365b4d38eefd0a883be64112f4495";
    927+    static const std::string responder_hdata = "4c469c70ba242ae0fc98d4eff6258cf19ecab96611c9c736356a4cf11d66edfa4d2970e56744a6d071861a4cbe2730eb7733a38b166e3df73450ef37112dd32f";
    928+
    929+    auto initiator_hdata_vec = ParseHex(initiator_hdata);
    930+    Span<uint8_t> initiator_hdata_span{initiator_hdata_vec.data(), initiator_hdata_vec.size()};
    


    sipa commented at 7:06 pm on April 14, 2022:
    These spans are unnecessary. You can just pass initiator_hdata_vec etc. whereever initiator_hdata_span is used (they get converted automatically).

    dhruv commented at 1:10 am on April 15, 2022:
    Done.
  42. in src/test/net_tests.cpp:980 in f0b520b17c outdated
    975+    BOOST_CHECK_EQUAL(0, memcmp(initiator_keys.responder_V.data(), responder_keys.responder_V.data(), initiator_keys.responder_V.size()));
    976+    BOOST_CHECK_EQUAL("94e374b822bc293b4eb3475aed2457e1b2fc9691df9ffb02afc462c36d513783", HexStr(Span{initiator_keys.responder_V}));
    977+
    978+    BOOST_CHECK_EQUAL(BIP324_KEY_LEN, initiator_keys.session_id.size());
    979+    BOOST_CHECK_EQUAL(initiator_keys.session_id.size(), responder_keys.session_id.size());
    980+    BOOST_CHECK_EQUAL(0, memcmp(initiator_keys.session_id.data(), responder_keys.session_id.data(), initiator_keys.session_id.size()));
    


    sipa commented at 7:07 pm on April 14, 2022:
    You can use BOOST_CHECK(initiator_keys.session_id == responder_keys.session_id) instead here.

    dhruv commented at 1:10 am on April 15, 2022:
    Done.
  43. in src/key.h:31 in f0b520b17c outdated
    24@@ -22,6 +25,14 @@
    25  */
    26 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
    27 
    28+constexpr static size_t ECDH_SECRET_SIZE = CSHA256::OUTPUT_SIZE;
    29+
    30+// SHA256("secp256k1_ellsq_xonly_ecdh") proven with a unit test (xonly_ecdh_tag)
    31+const static auto BIP324_ECDH_TAG = ParseHex("4dbebba5394890bf7370e9ca2ca6112941b974c56950e5c4fef7f00a2bbf3e55");
    


    sipa commented at 7:19 pm on April 14, 2022:
    You can also use const CHashWriter HASHER_BIP324_ECDH = TaggedHash("secp256k1_ellsq_xonly_ecdh");, and then do the rest of the hashing using (HashWriter(HASHER_BIP324_ECDH) << [rest of stuff] << [to hash]).GetSHA256(). That precomputes the entire midstate after the tag.

    dhruv commented at 1:11 am on April 15, 2022:
    Super nice change - much cleaner. Thanks for showing me that. Done.
  44. in src/key.cpp:344 in f0b520b17c outdated
    339+{
    340+    memcpy(output, x32, 32);
    341+    return 1;
    342+}
    343+
    344+bool CKey::ComputeBIP324ECDHSecret(const CPubKey& pubkey, const Span<uint8_t> initiator_hdata, const Span<uint8_t> responder_hdata,
    


    sipa commented at 7:23 pm on April 14, 2022:
    You can make the arguments here take Span<const uint8_t> - or even Span<const std::byte>. I don’t think this function needs to be able to mutate the passed in hdata.

    dhruv commented at 1:11 am on April 15, 2022:
    Done.
  45. dhruv force-pushed on Apr 15, 2022
  46. dhruv commented at 1:11 am on April 15, 2022: contributor
    Addressed review comments from @fanquake and @sipa. Ready for further review.
  47. in src/test/key_tests.cpp:354 in 2ec727ee61 outdated
    349+{
    350+    CKey initiator_key = DecodeSecret(strSecret1);
    351+    CKey responder_key = DecodeSecret(strSecret2C);
    352+
    353+    ECDHSecret initiator_secret, responder_secret;
    354+    auto initiator_hdata_vec = ParseHex("2deb41da6887640dda029ae41c9c9958881d0bb8e28f6bb9039ee9b7bb11091d62f4cbe65cc418df7aefd738f4d3e96c66365b4d38eefd0a883be64112f4495");
    


    stratospher commented at 6:36 am on May 7, 2022:

    to match the 64 bytes encoding in commit c9db50b.

    0    auto initiator_hdata_vec = ParseHex("2deb41da6887640dda029ae41c9c9958881d0bb8e28f6bb9039ee9b7bb11091d62f4cbe65cc418df7aefd738f4d3e926c66365b4d38eefd0a883be64112f4495");
    

    dhruv commented at 11:58 pm on July 12, 2022:
    Thanks! Done.
  48. DrahtBot added the label Needs rebase on May 13, 2022
  49. theStack commented at 11:23 am on June 2, 2022: contributor

    Concept ACK

    nit: Considering that ECDHSecret always has a fixed size, do we really need to use a std::vector? An alternative would be to use std::array and remove the .resize() calls. The following diff on the top-commit seems to work fine:

     0diff --git a/src/key.cpp b/src/key.cpp
     1index aab8bbda1..791c4c878 100644
     2--- a/src/key.cpp
     3+++ b/src/key.cpp
     4@@ -357,7 +357,6 @@ bool CKey::ComputeBIP324ECDHSecret(const CPubKey& pubkey, const Span<const uint8
     5     hasher << initiator_hdata << responder_hdata << xonly_ecdh;
     6     auto secret_uint256 = hasher.GetSHA256();
     7
     8-    secret.resize(ECDH_SECRET_SIZE);
     9     memcpy(secret.data(), &secret_uint256, CSHA256::OUTPUT_SIZE);
    10     memory_cleanse(xonly_ecdh, ECDH_SECRET_SIZE);
    11     return true;
    12diff --git a/src/key.h b/src/key.h
    13index 0fdaef1eb..60f6cce3f 100644
    14--- a/src/key.h
    15+++ b/src/key.h
    16@@ -29,7 +29,7 @@ constexpr static size_t ECDH_SECRET_SIZE = CSHA256::OUTPUT_SIZE;
    17 const CHashWriter HASHER_BIP324_ECDH = TaggedHash("secp256k1_ellsq_xonly_ecdh");
    18
    19 // Used to represent a ECDH secret (ECDH_SECRET_SIZE bytes)
    20-using ECDHSecret = std::vector<uint8_t, secure_allocator<uint8_t>>;
    21+using ECDHSecret = std::array<uint8_t, ECDH_SECRET_SIZE>;
    22
    23 /** An encapsulated private key. */
    24 class CKey
    25diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp
    26index 09dac0f17..2ca07b7d7 100644
    27--- a/src/test/fuzz/net.cpp
    28+++ b/src/test/fuzz/net.cpp
    29@@ -89,7 +89,6 @@ FUZZ_TARGET_INIT(bip324, initialize_chainparams)
    30     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
    31
    32     ECDHSecret ecdh_secret;
    33-    ecdh_secret.resize(ECDH_SECRET_SIZE);
    34     auto ecdh_secret_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(ECDH_SECRET_SIZE);
    35     ecdh_secret_bytes.resize(ECDH_SECRET_SIZE);
    

    Not sure though what security implications this has without the secure_allocator being involved.

  50. dhruv force-pushed on Jul 12, 2022
  51. dhruv commented at 0:01 am on July 13, 2022: contributor

    This push:

    • Rebased
    • Addressed comment from @theStack - there’s cleansing in the right place and tests for it so we can indeed use std::array instead of a secure vector.
    • Addressed comment from @stratospher
    • Added a couple more derived secrets per new spec in the working group

    Ready for further review.

  52. DrahtBot removed the label Needs rebase on Jul 13, 2022
  53. DrahtBot added the label Needs rebase on Jul 13, 2022
  54. in src/key.cpp:354 in 71e53c0682 outdated
    349+        return false;
    350+    }
    351+
    352+    uint8_t xonly_ecdh[ECDH_SECRET_SIZE];
    353+    assert(secp256k1_ecdh(secp256k1_context_sign, xonly_ecdh, &pubkey_internal,
    354+                          keydata.data(), bip324_ecdh_hash, nullptr));
    


    theStack commented at 10:40 am on July 14, 2022:

    According to our guidelines, assertions shouldn’t have side-effects (see https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#general-c).

    0    if (!secp256k1_ecdh(secp256k1_context_sign, xonly_ecdh, &pubkey_internal,
    1                        keydata.data(), bip324_ecdh_hash, nullptr)) {
    2        assert(false);
    3    }
    

    dhruv commented at 4:05 pm on July 18, 2022:
    Thanks for teaching me this. Done.
  55. in src/key.h:172 in 71e53c0682 outdated
    165@@ -156,6 +166,10 @@ class CKey
    166 
    167     //! Load private key and check that public key matches.
    168     bool Load(const CPrivKey& privkey, const CPubKey& vchPubKey, bool fSkipCheck);
    169+
    170+    // Returns false if an invalid public key is provided
    171+    bool ComputeBIP324ECDHSecret(const CPubKey& pubkey, const Span<const uint8_t> initiator_hdata, const Span<const uint8_t> responder_hdata,
    172+                                 ECDHSecret& secret) const;
    


    theStack commented at 10:47 am on July 14, 2022:

    nit: An alternative, probably more modern interface would be to return std::optional<ECDHSecret> instead of storing the result in an out-parameter.

    0    // Returns std::nullopt if an invalid public key is provided
    1    std::optional<ECDHSecret> ComputeBIP324ECDHSecret(const CPubKey& pubkey, const Span<const uint8_t> initiator_hdata, const Span<const uint8_t> responder_hdata) const;
    

    dhruv commented at 4:05 pm on July 18, 2022:
    Done.
  56. in src/test/key_tests.cpp:363 in 71e53c0682 outdated
    358+    Span<uint8_t> responder_hdata{responder_hdata_vec.data(), responder_hdata_vec.size()};
    359+
    360+    BOOST_CHECK(initiator_key.ComputeBIP324ECDHSecret(responder_key.GetPubKey(), initiator_hdata, responder_hdata, initiator_secret));
    361+    BOOST_CHECK(responder_key.ComputeBIP324ECDHSecret(initiator_key.GetPubKey(), initiator_hdata, responder_hdata, responder_secret));
    362+    BOOST_CHECK_EQUAL(initiator_secret.size(), ECDH_SECRET_SIZE);
    363+    BOOST_CHECK_EQUAL(responder_secret.size(), ECDH_SECRET_SIZE);
    


    theStack commented at 10:48 am on July 14, 2022:

    nit: These checks obviously don’t hurt, but now that ECDHSecret uses std::array and has it’s size fixed at compile-time, they are not that useful anymore.


    dhruv commented at 4:05 pm on July 18, 2022:
    Done.
  57. in src/test/key_tests.cpp:364 in 71e53c0682 outdated
    359+
    360+    BOOST_CHECK(initiator_key.ComputeBIP324ECDHSecret(responder_key.GetPubKey(), initiator_hdata, responder_hdata, initiator_secret));
    361+    BOOST_CHECK(responder_key.ComputeBIP324ECDHSecret(initiator_key.GetPubKey(), initiator_hdata, responder_hdata, responder_secret));
    362+    BOOST_CHECK_EQUAL(initiator_secret.size(), ECDH_SECRET_SIZE);
    363+    BOOST_CHECK_EQUAL(responder_secret.size(), ECDH_SECRET_SIZE);
    364+    BOOST_CHECK_EQUAL(0, memcmp(initiator_secret.data(), responder_secret.data(), ECDH_SECRET_SIZE));
    


    theStack commented at 10:51 am on July 14, 2022:

    nit: could simply use operator== of std::array here:

    0    BOOST_CHECK(initiator_secret == responder_secret);
    

    dhruv commented at 4:06 pm on July 18, 2022:
    Done.
  58. in src/test/fuzz/key.cpp:345 in b02d45c004 outdated
    340+    ECDHSecret ecdh_secret_1, ecdh_secret_2;
    341+    assert(k1.ComputeBIP324ECDHSecret(k2_pubkey, k1_ellsq, k2_ellsq, ecdh_secret_1));
    342+    assert(k2.ComputeBIP324ECDHSecret(k1_pubkey, k1_ellsq, k2_ellsq, ecdh_secret_2));
    343+    assert(ecdh_secret_1.size() == ECDH_SECRET_SIZE);
    344+    assert(ecdh_secret_2.size() == ECDH_SECRET_SIZE);
    345+    assert(memcmp(ecdh_secret_1.data(), ecdh_secret_2.data(), ECDH_SECRET_SIZE) == 0);
    


    theStack commented at 10:55 am on July 14, 2022:

    nit:

    0    assert(ecdh_secret_1 == ecdh_secret_2);
    

    dhruv commented at 4:06 pm on July 18, 2022:
    Done.
  59. in src/net.cpp:448 in 200c3b4787 outdated
    439@@ -438,6 +440,42 @@ static CAddress GetBindAddress(const Sock& sock)
    440     return addr_bind;
    441 }
    442 
    443+bool DeriveBIP324Keys(ECDHSecret&& ecdh_secret, const Span<uint8_t> initiator_hdata, const Span<uint8_t> responder_hdata, BIP324Keys& derived_keys)
    444+{
    445+    if (ecdh_secret.size() != ECDH_SECRET_SIZE) {
    446+        return false;
    447+    }
    448+
    


    theStack commented at 10:57 am on July 14, 2022:

    Since ECDHSecret has a fixed size (std::array<uint8_t, ECDH_SECRET_SIZE>), this is dead code now and can be removed.


    dhruv commented at 4:06 pm on July 18, 2022:
    Done. This also let me optimize the interface to the function as it always succeeds now.
  60. in src/test/net_tests.cpp:947 in 200c3b4787 outdated
    942+    BOOST_CHECK(initiator_key.ComputeBIP324ECDHSecret(responder_pubkey, initiator_hdata_vec, responder_hdata_vec, initiator_secret));
    943+    BOOST_CHECK(responder_key.ComputeBIP324ECDHSecret(initiator_pubkey, initiator_hdata_vec, responder_hdata_vec, responder_secret));
    944+
    945+    BOOST_CHECK_EQUAL(ECDH_SECRET_SIZE, initiator_secret.size());
    946+    BOOST_CHECK_EQUAL(ECDH_SECRET_SIZE, responder_secret.size());
    947+    BOOST_CHECK_EQUAL(0, memcmp(initiator_secret.data(), responder_secret.data(), ECDH_SECRET_SIZE));
    


    theStack commented at 11:00 am on July 14, 2022:

    nit:

    0    BOOST_CHECK(initiator_secret == responder_secret);
    

    dhruv commented at 4:06 pm on July 18, 2022:
    Done.
  61. dhruv force-pushed on Jul 18, 2022
  62. dhruv commented at 4:07 pm on July 18, 2022: contributor

    Latest push:

    • Rebased
    • Addressed comments form @theStack
    • The new HKDF derivation no longer needs the elligator swift bytes from the handshake as those are committed to in the initial ECDH.
    • This PR now depends on it’s anagram #25361 for some constants which simplify the downstream PR #24545. Only last 5 commits belong to this PR.

    Ready for further review.

  63. DrahtBot removed the label Needs rebase on Jul 18, 2022
  64. dhruv force-pushed on Jul 22, 2022
  65. dhruv commented at 7:53 pm on July 22, 2022: contributor

    Latest push:

    • This PR now depends on integrated XDH rather than the ECDH module in libsecp256k1

    Ready for further review. I don’t yet know what’s happening with the vs2022 tests on CI, but I will address that once https://github.com/bitcoin-core/secp256k1/pull/1129 is merged.

  66. in src/bench/bip324_ecdh.cpp:31 in 9f1b84c283 outdated
    26+        return;
    27+    }
    28+
    29+    std::array<unsigned char, 32> rnd32;
    30+    GetRandBytes(rnd32);
    31+    secp256k1_ellswift_encode(ctx, ell64, &pubkey_internal, rnd32.data());
    


    sipa commented at 1:14 pm on July 23, 2022:
    The new ellswift API has a function secp256k1_ellswift_create which goes directly from private key + randomness to ellswift encoding, bypassing the need for encoding the public key in the traditional form.

    dhruv commented at 7:54 pm on July 26, 2022:
    Much nicer. Thank you for the reminder. Done.
  67. dhruv force-pushed on Jul 26, 2022
  68. dhruv commented at 7:54 pm on July 26, 2022: contributor
    Addressed comments. Ready for further review.
  69. dhruv force-pushed on Aug 1, 2022
  70. dhruv commented at 5:22 pm on August 1, 2022: contributor
    Added rekeying salt to key derivation. Ready for further review.
  71. in src/test/key_tests.cpp:363 in 789d8bb80a outdated
    358+    BOOST_CHECK(initiator_secret.has_value());
    359+    auto responder_secret = responder_key.ComputeBIP324ECDHSecret(MakeByteSpan(initiator_ellswift), MakeByteSpan(responder_ellswift), false);
    360+    BOOST_CHECK(responder_secret.has_value());
    361+    BOOST_CHECK(initiator_secret.value() == responder_secret.value());
    362+    BOOST_CHECK_EQUAL("6cbb9cd446f28623979b16affc4b57c4af95db832cb1a4ff8bc41e3192a33bd8", HexStr(initiator_secret.value()));
    363+    BOOST_CHECK_EQUAL("6cbb9cd446f28623979b16affc4b57c4af95db832cb1a4ff8bc41e3192a33bd8", HexStr(responder_secret.value()));
    


    stratospher commented at 2:01 pm on August 30, 2022:
    in 789d8bb: this would be the ECDH secret - ae1b0c44c3c38aa5206899c0928ca51f637e3ec05771b4a6c0662b46b76049d8

    dhruv commented at 8:31 pm on September 11, 2022:
    Done
  72. in src/key.h:32 in 789d8bb80a outdated
    27@@ -22,6 +28,12 @@
    28  */
    29 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
    30 
    31+constexpr static size_t ECDH_SECRET_SIZE = CSHA256::OUTPUT_SIZE;
    32+const auto HASHER_BIP324_ECDH = TaggedHash("secp256k1_ellsq_xonly_ecdh");
    


    stratospher commented at 2:03 pm on August 30, 2022:
    in 789d8bb8: s/secp256k1_ellsq_xonly_ecdh/secp256k1_ellswift_xonly_ecdh

    stratospher commented at 2:13 pm on August 30, 2022:

    in 789d8bb: would it be useful to keep the TaggedHash() function call similar to other calls in the codebase?

    0const HashWriter HASHER_BIP324_ECDH{TaggedHash("secp256k1_ellswift_xonly_ecdh")};
    

    dhruv commented at 8:31 pm on September 11, 2022:
    Done
  73. in src/test/net_tests.cpp:933 in 4220009bc7 outdated
    928+    BOOST_CHECK(initiator_secret.has_value());
    929+    auto responder_secret = responder_key.ComputeBIP324ECDHSecret(MakeByteSpan(initiator_ellswift), MakeByteSpan(responder_ellswift), false);
    930+    BOOST_CHECK(responder_secret.has_value());
    931+    BOOST_CHECK(initiator_secret.value() == responder_secret.value());
    932+    BOOST_CHECK_EQUAL("6cbb9cd446f28623979b16affc4b57c4af95db832cb1a4ff8bc41e3192a33bd8", HexStr(initiator_secret.value()));
    933+    BOOST_CHECK_EQUAL("6cbb9cd446f28623979b16affc4b57c4af95db832cb1a4ff8bc41e3192a33bd8", HexStr(responder_secret.value()));
    


    stratospher commented at 3:53 pm on August 30, 2022:
    in 4220009b: ECDH secret is ae1b0c44c3c38aa5206899c0928ca51f637e3ec05771b4a6c0662b46b76049d8

    dhruv commented at 8:31 pm on September 11, 2022:
    Done
  74. in src/test/net_tests.cpp:946 in 4220009bc7 outdated
    941+    BOOST_CHECK_EQUAL("0000000000000000000000000000000000000000000000000000000000000000", HexStr(initiator_secret.value()));
    942+    BOOST_CHECK_EQUAL("0000000000000000000000000000000000000000000000000000000000000000", HexStr(responder_secret.value()));
    943+
    944+    BOOST_CHECK_EQUAL(BIP324_KEY_LEN, initiator_keys.initiator_L.size());
    945+    BOOST_CHECK(initiator_keys.initiator_L == responder_keys.initiator_L);
    946+    BOOST_CHECK_EQUAL("75fa71b052982a72ecb4a0e2a73697857121e4fca2f06e791a5d3c3383d4bb16", HexStr(initiator_keys.initiator_L));
    


    stratospher commented at 5:40 pm on August 30, 2022:
    in 4220009: 98b1a948d70374db8078475fd2b573789989a57d5394ecc229a3f2ec336c4d18

    dhruv commented at 8:30 pm on September 11, 2022:
    Done
  75. in src/test/net_tests.cpp:950 in 4220009bc7 outdated
    945+    BOOST_CHECK(initiator_keys.initiator_L == responder_keys.initiator_L);
    946+    BOOST_CHECK_EQUAL("75fa71b052982a72ecb4a0e2a73697857121e4fca2f06e791a5d3c3383d4bb16", HexStr(initiator_keys.initiator_L));
    947+
    948+    BOOST_CHECK_EQUAL(BIP324_KEY_LEN, initiator_keys.initiator_P.size());
    949+    BOOST_CHECK(initiator_keys.initiator_P == responder_keys.initiator_P);
    950+    BOOST_CHECK_EQUAL("bc6617bd1473017b1b40e927c0330b74d1bdd30594a1daa49d89c831f03775cd", HexStr(initiator_keys.initiator_P));
    


    stratospher commented at 5:42 pm on August 30, 2022:
    in 4220009: 95bdf50958c46ad24c7646cd7bf7579ffafb2f032d2c5356fc8341e198d0bb51

    dhruv commented at 8:30 pm on September 11, 2022:
    Done
  76. in src/test/net_tests.cpp:954 in 4220009bc7 outdated
    949+    BOOST_CHECK(initiator_keys.initiator_P == responder_keys.initiator_P);
    950+    BOOST_CHECK_EQUAL("bc6617bd1473017b1b40e927c0330b74d1bdd30594a1daa49d89c831f03775cd", HexStr(initiator_keys.initiator_P));
    951+
    952+    BOOST_CHECK_EQUAL(BIP324_KEY_LEN, initiator_keys.responder_L.size());
    953+    BOOST_CHECK(initiator_keys.responder_L == responder_keys.responder_L);
    954+    BOOST_CHECK_EQUAL("f31764965c22b792a5ac3f35573b01db27a8d479677c53c43d71bbc2141e8886", HexStr(initiator_keys.responder_L));
    


    stratospher commented at 5:44 pm on August 30, 2022:
    in 4220009: 0dec3e671918898ce5472b161ddfcc6f765bf459e8cdeb86825fa704a58546e5

    dhruv commented at 8:30 pm on September 11, 2022:
    Done
  77. in src/test/net_tests.cpp:958 in 4220009bc7 outdated
    953+    BOOST_CHECK(initiator_keys.responder_L == responder_keys.responder_L);
    954+    BOOST_CHECK_EQUAL("f31764965c22b792a5ac3f35573b01db27a8d479677c53c43d71bbc2141e8886", HexStr(initiator_keys.responder_L));
    955+
    956+    BOOST_CHECK_EQUAL(BIP324_KEY_LEN, initiator_keys.responder_P.size());
    957+    BOOST_CHECK(initiator_keys.responder_P == responder_keys.responder_P);
    958+    BOOST_CHECK_EQUAL("82c8d144f1dc7b86993c248db020aecfaed37a5c215bea5a7f1bf4399a85ecca", HexStr(initiator_keys.responder_P));
    


    stratospher commented at 5:45 pm on August 30, 2022:
    in 4220009: af8b74244dd43c5921e2449a125d669f6d82a23250fa040eafc3ba2373067de5

    dhruv commented at 8:30 pm on September 11, 2022:
    Done
  78. in src/test/net_tests.cpp:962 in 4220009bc7 outdated
    957+    BOOST_CHECK(initiator_keys.responder_P == responder_keys.responder_P);
    958+    BOOST_CHECK_EQUAL("82c8d144f1dc7b86993c248db020aecfaed37a5c215bea5a7f1bf4399a85ecca", HexStr(initiator_keys.responder_P));
    959+
    960+    BOOST_CHECK_EQUAL(BIP324_KEY_LEN, initiator_keys.session_id.size());
    961+    BOOST_CHECK(initiator_keys.session_id == responder_keys.session_id);
    962+    BOOST_CHECK_EQUAL("e6b4d42bc1fbce790cf7b419d0128c7caf319b491acfd9fd874f29ca3843fe40", HexStr(initiator_keys.session_id));
    


    stratospher commented at 5:45 pm on August 30, 2022:
    in 4220009: ae605e623a8f710f4f0c99454d74cdfb8861cad1f8f6dd2eb86390d615efab01

    dhruv commented at 8:30 pm on September 11, 2022:
    Done
  79. in src/test/net_tests.cpp:966 in 4220009bc7 outdated
    961+    BOOST_CHECK(initiator_keys.session_id == responder_keys.session_id);
    962+    BOOST_CHECK_EQUAL("e6b4d42bc1fbce790cf7b419d0128c7caf319b491acfd9fd874f29ca3843fe40", HexStr(initiator_keys.session_id));
    963+
    964+    BOOST_CHECK_EQUAL(BIP324_KEY_LEN, initiator_keys.rekey_salt.size());
    965+    BOOST_CHECK(initiator_keys.rekey_salt == responder_keys.rekey_salt);
    966+    BOOST_CHECK_EQUAL("060d26411cdedabda638b1a807d0b68cbbb326385881409fcd2f5705091c5842", HexStr(initiator_keys.rekey_salt));
    


    stratospher commented at 5:46 pm on August 30, 2022:
    in 4220009: e46620b5e10052931401606ccbb4c810c4f9afa9db948e3acfbeaa65b0cc8199

    dhruv commented at 8:30 pm on September 11, 2022:
    Done
  80. in src/test/net_tests.cpp:970 in 4220009bc7 outdated
    965+    BOOST_CHECK(initiator_keys.rekey_salt == responder_keys.rekey_salt);
    966+    BOOST_CHECK_EQUAL("060d26411cdedabda638b1a807d0b68cbbb326385881409fcd2f5705091c5842", HexStr(initiator_keys.rekey_salt));
    967+
    968+    BOOST_CHECK_EQUAL(BIP324_GARBAGE_TERMINATOR_LEN, initiator_keys.garbage_terminator.size());
    969+    BOOST_CHECK(initiator_keys.garbage_terminator == responder_keys.garbage_terminator);
    970+    BOOST_CHECK_EQUAL("118878010356d064", HexStr(Span{initiator_keys.garbage_terminator}));
    


    stratospher commented at 5:46 pm on August 30, 2022:
    in 4220009: 73d7412ff3b42a01

    dhruv commented at 8:30 pm on September 11, 2022:
    Done.
  81. dhruv force-pushed on Sep 11, 2022
  82. dhruv commented at 8:30 pm on September 11, 2022: contributor
    Addressed comments from @stratospher and a clang-tidy issue. Ready for further review.
  83. in src/test/net_tests.cpp:966 in f5d4f368f0 outdated
    961+    BOOST_CHECK(initiator_keys.rekey_salt == responder_keys.rekey_salt);
    962+    BOOST_CHECK_EQUAL("e46620b5e10052931401606ccbb4c810c4f9afa9db948e3acfbeaa65b0cc8199", HexStr(initiator_keys.rekey_salt));
    963+
    964+    BOOST_CHECK_EQUAL(BIP324_GARBAGE_TERMINATOR_LEN, initiator_keys.garbage_terminator.size());
    965+    BOOST_CHECK(initiator_keys.garbage_terminator == responder_keys.garbage_terminator);
    966+    BOOST_CHECK_EQUAL("73d7412ff3b42a01", HexStr(Span{initiator_keys.garbage_terminator}));
    


    stratospher commented at 6:56 pm on September 21, 2022:
    f5d4f36: Span can be removed.

    dhruv commented at 9:18 pm on October 1, 2022:
    Fixed.
  84. in src/key.cpp:348 in ab46788fc0 outdated
    343+
    344+std::optional<ECDHSecret> CKey::ComputeBIP324ECDHSecret(const Span<const std::byte> their_ellswift,
    345+                                                        const Span<const std::byte> our_ellswift,
    346+                                                        bool initiating) const
    347+{
    348+    uint8_t xonly_ecdh[ECDH_SECRET_SIZE];
    


    stratospher commented at 7:12 pm on September 21, 2022:
    ab46788: uint8_t can be made std::byte.

    dhruv commented at 4:58 am on October 1, 2022:
    @stratospher Upon further thought after our conversation, I think unsigned char makes sense here as that’s exactly what all the functions it is used with require. So I’m going with that when I update.
  85. DrahtBot added the label Needs rebase on Sep 25, 2022
  86. dhruv force-pushed on Oct 1, 2022
  87. dhruv commented at 9:17 pm on October 1, 2022: contributor

    Latest push:

    • Rebased
    • Brought in upstream updates
    • Addressed comments from @stratospher
    • Changed ECDH tag for better domain separation
    • Rekey salt is now 23 bytes instead of 32 bytes to allow rekeying in a single SHA256 compression

    Windows tests failing - but should get resolved once secp/PR 1129 is merged.

  88. DrahtBot removed the label Needs rebase on Oct 1, 2022
  89. dhruv force-pushed on Oct 15, 2022
  90. dhruv commented at 4:17 am on October 15, 2022: contributor

    Latest push:

    • garbage terminator length is now 16 bytes instead of 8 bytes
    • bidirectional garbage terminators in derivation in accordance with the recently released BIP draft
  91. DrahtBot added the label Needs rebase on Oct 19, 2022
  92. dhruv force-pushed on Oct 21, 2022
  93. dhruv commented at 5:49 am on October 21, 2022: contributor
    Rebased.
  94. DrahtBot removed the label Needs rebase on Oct 21, 2022
  95. dhruv force-pushed on Nov 18, 2022
  96. dhruv commented at 5:18 am on November 18, 2022: contributor

    Latest push:

  97. DrahtBot added the label Needs rebase on Nov 19, 2022
  98. DrahtBot removed the label Needs rebase on Nov 21, 2022
  99. dhruv force-pushed on Nov 23, 2022
  100. dhruv commented at 5:12 am on November 23, 2022: contributor
    Bringing in upstream rebase (#26153)
  101. DrahtBot added the label Needs rebase on Nov 30, 2022
  102. dhruv force-pushed on Dec 15, 2022
  103. dhruv commented at 4:53 pm on December 15, 2022: contributor

    Latest push:

    • Rebased upstream changes
    • Upstream changes include a new rekey ratchet mechanism (forward security) based on ChaCha20 instead of SHA256. This also means we no longer need the rekey salt in the session derivation process. BIP changes are WIP and coming soon.
  104. DrahtBot removed the label Needs rebase on Dec 15, 2022
  105. DrahtBot added the label Needs rebase on Dec 25, 2022
  106. dhruv force-pushed on Jan 12, 2023
  107. dhruv commented at 7:10 pm on January 12, 2023: contributor
    Rebased
  108. DrahtBot removed the label Needs rebase on Jan 12, 2023
  109. DrahtBot added the label Needs rebase on Jan 13, 2023
  110. dhruv force-pushed on Jan 14, 2023
  111. dhruv commented at 5:54 am on January 14, 2023: contributor
    Rebased
  112. DrahtBot removed the label Needs rebase on Jan 14, 2023
  113. dhruv force-pushed on Jan 23, 2023
  114. dhruv commented at 10:14 pm on January 23, 2023: contributor
    Rebased changes from #26153
  115. DrahtBot added the label Needs rebase on Jan 28, 2023
  116. dhruv force-pushed on Feb 2, 2023
  117. dhruv commented at 6:27 am on February 2, 2023: contributor
    Rebased. Brought in upstream changes.
  118. DrahtBot removed the label Needs rebase on Feb 2, 2023
  119. DrahtBot added the label Needs rebase on Feb 15, 2023
  120. RFC8439 nonce and counter for ChaCha20 8e04f058a4
  121. RFC8439 implementation and tests 7a9d2fb8cf
  122. Adding forward secure FSChaCha20 acd664e805
  123. dhruv commented at 3:35 am on February 21, 2023: contributor
    Rebased.
  124. dhruv force-pushed on Feb 21, 2023
  125. DrahtBot removed the label Needs rebase on Feb 21, 2023
  126. dhruv force-pushed on Mar 8, 2023
  127. dhruv commented at 3:28 pm on March 8, 2023: contributor
    Rebased. Brought in changes from https://github.com/bitcoin-core/secp256k1/pull/1129.
  128. DrahtBot added the label Needs rebase on Mar 12, 2023
  129. BIP324 Cipher Suite 187761fc8a
  130. Allow for RFC8439 AD in cipher suite interface 8405856ed9
  131. Merge branch 'bip324-cipher-suite' into bip324-handshake ea3e911558
  132. Squashed 'src/secp256k1/' changes from bdf39000b9..8034c67a48
    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
    427bc3cdcf Merge bitcoin-core/secp256k1#1236: Update comment for secp256k1_modinv32_inv256
    647f0a5cb1 Update comment for secp256k1_modinv32_inv256
    5658209459 Merge bitcoin-core/secp256k1#1228: release cleanup: bump version after 0.3.0
    28e63f7ea7 release cleanup: bump version after 0.3.0
    
    git-subtree-dir: src/secp256k1
    git-subtree-split: 8034c67a48dc1334bc74ee4ba239111a23d9789e
    984b3d0a1f
  133. Merge commit '984b3d0a1faabc1657e0dd33432fdadfd78335a9' into bip324-handshake 007a92ed80
  134. Enable ECDH computation on secp256k1 keys 3d1b276949
  135. Bench test for ECDH 4b7be855dd
  136. Fuzz test for ECDH 6ffa68f4db
  137. HKDF key derivation from ECDH secret for BIP324 dc2527fb2f
  138. Fuzz test for BIP324 key derivation 178ef757ba
  139. dhruv force-pushed on Mar 21, 2023
  140. dhruv commented at 4:03 am on March 21, 2023: contributor
    Rebased.
  141. DrahtBot removed the label Needs rebase on Mar 21, 2023
  142. DrahtBot added the label Needs rebase on Apr 3, 2023
  143. DrahtBot commented at 2:09 pm on April 3, 2023: contributor

    🐙 This pull request conflicts with the target branch and needs rebase.

  144. fanquake commented at 8:50 am on April 18, 2023: member
    Closing this for now, as it’s partly included in #27479.
  145. fanquake closed this on Apr 18, 2023

  146. achow101 referenced this in commit 679f825ba3 on Jun 26, 2023
  147. bitcoin locked this on Apr 17, 2024

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-09-28 22:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me