musig: Include pubnonce in session id

Multiple signing sessions over the same message are allowed. Including
the pubnonce in the session id allows distinguishing the signing
sessions.

This should be safe as a new secret nonce is used for each signing
session, and after the nonce is used, it is still deleted from memory in
order to avoid reuse.
This commit is contained in:
Ava Chow
2026-05-11 19:04:49 -07:00
parent 10ca73c02c
commit bb05986c0a
4 changed files with 12 additions and 6 deletions

View File

@@ -119,10 +119,10 @@ bool MuSig2SecNonce::IsValid()
return m_impl->IsValid();
}
uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash)
uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash, const std::vector<uint8_t>& pubnonce)
{
HashWriter hasher;
hasher << script_pubkey << part_pubkey << sighash;
hasher << script_pubkey << part_pubkey << sighash << pubnonce;
return hasher.GetSHA256();
}

View File

@@ -56,7 +56,11 @@ public:
bool IsValid();
};
uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash);
/**
* 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::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);

View File

@@ -123,7 +123,7 @@ std::vector<uint8_t> MutableTransactionSignatureCreator::CreateMuSig2Nonce(const
if (out.empty()) return {};
// Store the secnonce in the SigningProvider
provider.SetMuSig2SecNonce(MuSig2SessionID(script_pubkey, part_pubkey, *sighash), std::move(secnonce));
provider.SetMuSig2SecNonce(MuSig2SessionID(script_pubkey, part_pubkey, *sighash, out), std::move(secnonce));
return out;
}
@@ -156,7 +156,9 @@ bool MutableTransactionSignatureCreator::CreateMuSig2PartialSig(const SigningPro
if (!sighash.has_value()) return false;
// Retrieve the secnonce
uint256 session_id = MuSig2SessionID(script_pubkey, part_pubkey, *sighash);
auto part_pubnonce_it = pubnonces.find(part_pubkey);
if (part_pubnonce_it == pubnonces.end()) return false;
uint256 session_id = MuSig2SessionID(script_pubkey, part_pubkey, *sighash, part_pubnonce_it->second);
std::optional<std::reference_wrapper<MuSig2SecNonce>> secnonce = provider.GetMuSig2SecNonce(session_id);
if (!secnonce || !secnonce->get().IsValid()) return false;

View File

@@ -299,7 +299,7 @@ private:
* must be done in order to prevent nonce reuse.
*
* The session id is an arbitrary value set by the signer in order for the signing logic
* to find ongoing signing sessions. It is the SHA256 of aggregate xonly key, + participant pubkey + sighash.
* to find ongoing signing sessions, see MuSig2SessionID.
*/
mutable std::map<uint256, MuSig2SecNonce> m_musig2_secnonces;