mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-12 21:52:53 +02:00
2ef6679c2ctest: Check that MuSig2 signing does not reuse nonces (Ava Chow)bb05986c0amusig: Include pubnonce in session id (Ava Chow) Pull request description: It is safe to have multiple musig signing sessions over the same message so long as the nonces used are different. Including the pubnonce in the session id allows for multiple simultaneous signing sessions over the same message, rather than asserting when the user tries to do this. The second commit tests this behavior, both ensuring that there is no crash, and verifying that both sessions produce unique nonces and signatures to verify that no reuse is occurring. Lastly, the assertion in `SetMuSig2SecNonce` is retained as hitting it now would indicate that a nonce has been reused. We prefer to assert and crash rather than do something that is highly likely to leak a private key. Fixes #35250 ACKs for top commit: rkrux: lgtm ACK2ef6679c2cjunbyjun1238: utACK2ef6679c2ctheStack: ACK2ef6679c2cTree-SHA512: 9fb60b68ebe0ea9656408afb65b9ec9f280632e1bb84a4821b074c8d8569847845f7c29da800c757b9ddf3aa31aa890dd9e3646cf119917a714e7daf20be2198
71 lines
3.3 KiB
C++
71 lines
3.3 KiB
C++
// Copyright (c) 2024-present The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#ifndef BITCOIN_MUSIG_H
|
|
#define BITCOIN_MUSIG_H
|
|
|
|
#include <pubkey.h>
|
|
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
class CKey;
|
|
struct secp256k1_musig_keyagg_cache;
|
|
class MuSig2SecNonceImpl;
|
|
struct secp256k1_musig_secnonce;
|
|
|
|
constexpr size_t MUSIG2_PUBNONCE_SIZE{66};
|
|
|
|
//! Compute the full aggregate pubkey from the given participant pubkeys in their current order.
|
|
//! Outputs the secp256k1_musig_keyagg_cache and validates that the computed aggregate pubkey matches an expected aggregate pubkey.
|
|
//! This is necessary for most MuSig2 operations.
|
|
std::optional<CPubKey> MuSig2AggregatePubkeys(const std::vector<CPubKey>& pubkeys, secp256k1_musig_keyagg_cache& keyagg_cache, const std::optional<CPubKey>& expected_aggregate);
|
|
std::optional<CPubKey> MuSig2AggregatePubkeys(const std::vector<CPubKey>& pubkeys);
|
|
|
|
//! 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<MuSig2SecNonceImpl> 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();
|
|
};
|
|
|
|
/**
|
|
* Computes an arbitrary unique session ID to identify ongoing signing sessions.
|
|
* It is the SHA256 of the aggregate xonly key, the participant pubkey, the sighash, and the pubnonce
|
|
*/
|
|
uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash, const std::vector<uint8_t>& pubnonce);
|
|
|
|
std::vector<uint8_t> CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CKey& our_seckey, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys);
|
|
std::optional<uint256> CreateMuSig2PartialSig(const uint256& hash, const CKey& our_seckey, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys, const std::map<CPubKey, std::vector<uint8_t>>& pubnonces, MuSig2SecNonce& secnonce, const std::vector<std::pair<uint256, bool>>& tweaks);
|
|
std::optional<std::vector<uint8_t>> CreateMuSig2AggregateSig(const std::vector<CPubKey>& participants, const CPubKey& aggregate_pubkey, const std::vector<std::pair<uint256, bool>>& tweaks, const uint256& sighash, const std::map<CPubKey, std::vector<uint8_t>>& pubnonces, const std::map<CPubKey, uint256>& partial_sigs);
|
|
|
|
#endif // BITCOIN_MUSIG_H
|