From c06a1dc86ff2347538e95041ab7b97af25342958 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Mon, 25 Mar 2024 16:13:58 -0400 Subject: [PATCH] Add MuSig2SecNonce class for secure allocation of musig nonces --- src/musig.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/musig.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/musig.cpp b/src/musig.cpp index 85074796cbf..c361a7ea890 100644 --- a/src/musig.cpp +++ b/src/musig.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#include #include @@ -62,3 +63,43 @@ CExtPubKey CreateMuSig2SyntheticXpub(const CPubKey& pubkey) extpub.pubkey = pubkey; return extpub; } + +class MuSig2SecNonceImpl +{ +private: + //! The actual secnonce itself + secure_unique_ptr m_nonce; + +public: + MuSig2SecNonceImpl() : m_nonce{make_secure_unique()} {} + + // Delete copy constructors + MuSig2SecNonceImpl(const MuSig2SecNonceImpl&) = delete; + MuSig2SecNonceImpl& operator=(const MuSig2SecNonceImpl&) = delete; + + secp256k1_musig_secnonce* Get() const { return m_nonce.get(); } + void Invalidate() { m_nonce.reset(); } + bool IsValid() { return m_nonce != nullptr; } +}; + +MuSig2SecNonce::MuSig2SecNonce() : m_impl{std::make_unique()} {} + +MuSig2SecNonce::MuSig2SecNonce(MuSig2SecNonce&&) noexcept = default; +MuSig2SecNonce& MuSig2SecNonce::operator=(MuSig2SecNonce&&) noexcept = default; + +MuSig2SecNonce::~MuSig2SecNonce() = default; + +secp256k1_musig_secnonce* MuSig2SecNonce::Get() const +{ + return m_impl->Get(); +} + +void MuSig2SecNonce::Invalidate() +{ + return m_impl->Invalidate(); +} + +bool MuSig2SecNonce::IsValid() +{ + return m_impl->IsValid(); +} diff --git a/src/musig.h b/src/musig.h index 0bc1f5ff6f1..40da1f10b97 100644 --- a/src/musig.h +++ b/src/musig.h @@ -11,6 +11,8 @@ #include struct secp256k1_musig_keyagg_cache; +class MuSig2SecNonceImpl; +struct secp256k1_musig_secnonce; //! MuSig2 chaincode as defined by BIP 328 using namespace util::hex_literals; @@ -26,4 +28,35 @@ std::optional MuSig2AggregatePubkeys(const std::vector& pubkey //! Construct the BIP 328 synthetic xpub for a pubkey CExtPubKey CreateMuSig2SyntheticXpub(const CPubKey& pubkey); +/** + * MuSig2SecNonce encapsulates a secret nonce in use in a MuSig2 signing session. + * Since this nonce persists outside of libsecp256k1 signing code, we must handle + * its construction and destruction ourselves. + * The secret nonce must be kept a secret, otherwise the private key may be leaked. + * As such, it needs to be treated in the same way that CKeys are treated. + * So this class handles the secure allocation of the secp256k1_musig_secnonce object + * that libsecp256k1 uses, and only gives out references to this object to avoid + * any possibility of copies being made. Furthermore, objects of this class are not + * copyable to avoid nonce reuse. +*/ +class MuSig2SecNonce +{ +private: + std::unique_ptr m_impl; + +public: + MuSig2SecNonce(); + MuSig2SecNonce(MuSig2SecNonce&&) noexcept; + MuSig2SecNonce& operator=(MuSig2SecNonce&&) noexcept; + ~MuSig2SecNonce(); + + // Delete copy constructors + MuSig2SecNonce(const MuSig2SecNonce&) = delete; + MuSig2SecNonce& operator=(const MuSig2SecNonce&) = delete; + + secp256k1_musig_secnonce* Get() const; + void Invalidate(); + bool IsValid(); +}; + #endif // BITCOIN_MUSIG_H