Proposal: Bitcoin Secure Multisig Setup
37 messages, 8 Feb to 12 Apr 2021. Started by Hugo Nguyen.
Hugo Nguyen (18), Dmitry Petukhov (5), Christopher Allen (3), Craig Raw (2), Sjors Provoost (2), Robert Spigler (2), Pavol Rusnak, Peter (Coinkite Inc), +3 more
Hi all, I would like to propose a new BIP for Secure Multisig Setup. This proposal has taken inputs from folks at Coldcard, Shift Crypto and Cobo -- listed below as co-authors.
This was inspired by my own experience working with hardware wallets on the market, as well as existing research into the challenges of multisig.
Cheers, Hugo
<pre> BIP: To be determined Layer: Applications Title: Bitcoin Secure Multisig Setup (BSMS) Author: Hugo Nguyen <hugo@nunchuk•io>, Peter Gray <peter@coinkite•com>, Marko Bencun <marko@shiftcrypto•ch>, Aaron Chen <aarondongchen@gmail•com>, Rodolfo Novak <rodolfo@coinkite•com> Comments-Summary: No comments yet. Comments-URI: Status: Proposed Type: Standards Track Created: 2020-11-10 License: BSD-2-Clause </pre>
==Introduction==
===Abstract===
This document proposes a mechanism to set up multisig wallets securely.
===Copyright===
This BIP is licensed under the 2-clause BSD license.
===Motivation===
The Bitcoin multisig experience has been greatly streamlined under [ https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki BIP-0174 (Partially Signed Bitcoin Transaction)]. However, what is still missing is a standardized process for setting up multisig wallets securely across different vendors.
There are a number of concerns when it comes to setting up a multisig wallet:
# Whether the multisig configuration, such as Signer membership, script type, derivation paths and number of signatures required, is correct and not tampered with. # Whether Signer persists the multisig configuration in their respective storage, and under what format. # Whether Signer's storage is tamper-proof. # Whether Signer subsequently uses the multisig configuration to generate and verify receive and change addresses.
An attacker who can modify the multisig configuration can steal or hold funds to ransom by duping the user into sending funds to the wrong address.
This proposal seeks to address concerns #1 and #2: to mitigate the risk of tampering during the initial setup phase, and to define an interoperable multisig configuration format.
Concerns #3 and #4 should be handled by Signers and is out of scope of this proposal.
==Specification==
===Prerequisites=== This proposal assumes the parties in the multisig support [ https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32], [ https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the descriptor language] and encryption.
==Roles== ===Coordinator===
The Coordinator initiates the multisig setup. The Coordinator determines what type of multisig is used and how many members and signatures are needed. If encryption is enabled, the Coordinator generates a secret token, to be shared among the parties for secure communication. The Coordinator gathers information from the Signers to generate a descriptor record. The Coordinator distributes the descriptor record back to the Signers.
===Signer===
The Signer is a participating member in the multisig. Its responsibilities include providing its XPUB to the Coordinator, verifying that its XPUB is included in the descriptor record and persisting the descriptor record in its storage.
==Setup Process==
===Round 1===
====Coordinator====
* The Coordinator creates a multisig wallet creation session. The Coordinator determines the type of multisig script used and the signing configuration (<tt>M</tt> and <tt>N</tt>). * If encryption is enabled, the Coordinator also generates a secret token, hereby denoted <tt>TOKEN</tt>. * TOKEN is in ASCII format and must have a minimum of 8 characters. TOKEN should expire after some time period determined by the Coordinator, e.g., 24 hours. * TOKEN acts as an encryption key among the parties. The method of encryption is AES, CTR mode. The encryption key can be calculated by performing a double hash operation on the TOKEN: <tt>ENCRYPTION_KEY = SHA256(SHA256(TOKEN))</tt>. * A TOKEN value of <tt>-1</tt> means that encryption is disabled and all the encryption/decryption steps below can be skipped. * The Coordinator shares the TOKEN with all participating Signers over a secure channel.
====Signer====
* The Signer generates a key record by prompting the user for the TOKEN and a derivation path. * The first line in the record must be the <tt>TOKEN</tt>. If encryption is disabled, set the TOKEN to -1. The second line must be the <tt>KEY</tt>, whereas KEY is an XPUB. KEY must include key origin information and written in the descriptor-defined format, i.e.: <tt>[{master key fingerprint}/{derivation path}]{XPUB}</tt>. The third line must be a <tt>SIG</tt>, whereas SIG is the signature generated by using the corresponding private key to sign the first two lines. Finally, the Signer encrypts the entire record with ENCRYPTION_KEY.
===Round 2===
====Coordinator====
* The Coordinator gathers key records from all participating Signers. Abort the setup if TOKEN has expired. * For each key record, the Coordinator decrypts it using ENCRYPTION_KEY. The Coordinator verifies that the included SIG is valid given the KEY. * If all key records look good, the Coordinator generates a descriptor record, which is simply the descriptor string plus a <tt>CHECKSUM</tt>, all in one line. The CHECKSUM has BECH32 encoding and is described at [ https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums]. The Coordinator encrypts this descriptor record with ENCRYPTION_KEY. * The Coordinator sends the encrypted descriptor record to all participating Signers.
====Signer====
* The Signer imports the descriptor record, decrypts it by prompting the user for TOKEN. * The Signer calculates and verifies the descriptor’s CHECKSUM. Abort the setup if the CHECKSUM is incorrect. * The Signer checks whether one of the KEYs in the descriptor belongs to it, using path and fingerprint information included in the descriptor. The check must perform an exact match on the KEYs, and not using shortcuts such as matching fingerprints (which is trivial to spoof). Abort the setup if it doesn’t detect its own KEY. * For confirmation, the Signer must display to the user the descriptor's CHECKSUM, plus other configurations, such as M and N. The total number of Signers, N, is important to prevent a KEY insertion attack. All participating Signers should be able to display the same confirmation. * If all checks pass, the Signer persists the descriptor record in its storage. The Signer should subsequently use the descriptor to generate and verify receive and change addresses.
This completes the setup.
==QR Codes== For signers that use QR codes to transmit data, key and descriptor records can be converted to QR codes, following [ https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md the BCR standard].
==Security==
This proposal introduce two layers of protection. The first one is a temporary, secret token, used to encrypt the two rounds of communication between the Signers and the Coordinator. The second one is through the descriptor checksum and visual inspection of the descriptor itself.
The token is only needed during the setup phase, and can be safely thrown away afterwards. The token does not guarantee that the Signer membership set is not modified, since that depends on the overall security of all parties in the setup, but it can make it significantly harder for an attacker to do so.
There are three ways an attacker can modify the membership set: by changing an existing member, by removing an existing member, or by adding a new member.
For the first two methods, one of the Signers will be able to detect that its membership has been changed or removed, and reject the final descriptor. Thus, it is vital that all participating Signers check that their membership is intact in the descriptor. Even one Signer failing to check for its membership means that the setup could be compromised.
For the third type of attack, the descriptor checksum and visual inspection of the descriptor itself are the only way to guard against malicious members from being inserted into the set.
Hi Hugo,
Thanks for raising this again - I'll note there has already been much discussion on this topic. With respect to your "two layers of protection":
Quoted text (1 line)
> The Coordinator shares the TOKEN with all participating Signers over a
secure channel.
What secure channel do you propose? Currently, with the default of a software wallet coordinator talking to hardware wallets, we have USB, file (microSD), and QR as communication channels. It's unclear to me why the token and encryption process is necessary - in fact it's easier to verify what is going on using clear text, and the majority of setups will be locally done with the reasonable assumption of a secure environment. When the setup is remote, it's simpler to just transmit the key information over the secure channel which presumably already has encryption.
Quoted text (1 line)
> The second one is through the descriptor checksum and visual inspection
of the descriptor itself.
This is a reasonable suggestion, although it's worth noting that support for storing multisig setups on hardware wallets varies. Coldcard supports this through importing of a proprietary .txt format file (which has been adopted by a number of other vendors). Trezor and Ledger (AFAIK) do not however store multisig setups, which could make this step confusing. With that said, the use of an output descriptor is certainly a more standardised approach, albeit one without the wallet name included. By the use of the singular, I assume you mean a descriptor without the /0/* or /1/* suffix (which I think is a good idea).
WRT to QR codes, using the BCR UR2.0 standard you linked to is IMO the right approach. I'll link directly to the two BCR UR2.0 formats here which are relevant:
1. For sharing the sharing the BIP44 account information from the signers to the coordinator, the crypto-account format: [ https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-015-account.md ] 2. For sharing the output descriptor from the coordinator to the signers, the crypto-output format: [ https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-010-output-desc.md ]
Craig
On Tue, Feb 9, 2021 at 9:53 AM Hugo Nguyen via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (201 lines)
> Hi all, > I would like to propose a new BIP for Secure Multisig Setup. > This proposal has taken inputs from folks at Coldcard, Shift Crypto and > Cobo -- listed below as co-authors. > > This was inspired by my own experience working with hardware wallets on > the market, as well as existing research into the challenges of multisig. > > Cheers, > Hugo > > <pre> > BIP: To be determined > Layer: Applications > Title: Bitcoin Secure Multisig Setup (BSMS) > Author: Hugo Nguyen <hugo@nunchuk•io>, Peter Gray <peter@coinkite•com>, > Marko Bencun <marko@shiftcrypto•ch>, Aaron Chen <aarondongchen@gmail•com>, > Rodolfo Novak <rodolfo@coinkite•com> > Comments-Summary: No comments yet. > Comments-URI: > Status: Proposed > Type: Standards Track > Created: 2020-11-10 > License: BSD-2-Clause > </pre> > > ==Introduction== > > ===Abstract=== > > This document proposes a mechanism to set up multisig wallets securely. > > ===Copyright=== > > This BIP is licensed under the 2-clause BSD license. > > ===Motivation=== > > The Bitcoin multisig experience has been greatly streamlined under [ > https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki BIP-0174 > (Partially Signed Bitcoin Transaction)]. However, what is still missing is > a standardized process for setting up multisig wallets securely across > different vendors. > > There are a number of concerns when it comes to setting up a multisig > wallet: > > # Whether the multisig configuration, such as Signer membership, script > type, derivation paths and number of signatures required, is correct and > not tampered with. > # Whether Signer persists the multisig configuration in their respective > storage, and under what format. > # Whether Signer's storage is tamper-proof. > # Whether Signer subsequently uses the multisig configuration to generate > and verify receive and change addresses. > > An attacker who can modify the multisig configuration can steal or hold > funds to ransom by duping the user into sending funds to the wrong address. > > This proposal seeks to address concerns #1 and #2: to mitigate the risk of > tampering during the initial setup phase, and to define an interoperable > multisig configuration format. > > Concerns #3 and #4 should be handled by Signers and is out of scope of > this proposal. > > ==Specification== > > ===Prerequisites=== > This proposal assumes the parties in the multisig support [ > https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32], [ > https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the > descriptor language] and encryption. > > ==Roles== > ===Coordinator=== > > The Coordinator initiates the multisig setup. The Coordinator determines > what type of multisig is used and how many members and signatures are > needed. If encryption is enabled, the Coordinator generates a secret token, > to be shared among the parties for secure communication. The Coordinator > gathers information from the Signers to generate a descriptor record. The > Coordinator distributes the descriptor record back to the Signers. > > ===Signer=== > > The Signer is a participating member in the multisig. Its responsibilities > include providing its XPUB to the Coordinator, verifying that its XPUB is > included in the descriptor record and persisting the descriptor record in > its storage. > > ==Setup Process== > > ===Round 1=== > > ====Coordinator==== > > * The Coordinator creates a multisig wallet creation session. The > Coordinator determines the type of multisig script used and the signing > configuration (<tt>M</tt> and <tt>N</tt>). > * If encryption is enabled, the Coordinator also generates a secret token, > hereby denoted <tt>TOKEN</tt>. > * TOKEN is in ASCII format and must have a minimum of 8 characters. TOKEN > should expire after some time period determined by the Coordinator, e.g., > 24 hours. > * TOKEN acts as an encryption key among the parties. The method of > encryption is AES, CTR mode. The encryption key can be calculated by > performing a double hash operation on the TOKEN: <tt>ENCRYPTION_KEY = > SHA256(SHA256(TOKEN))</tt>. > * A TOKEN value of <tt>-1</tt> means that encryption is disabled and all > the encryption/decryption steps below can be skipped. > * The Coordinator shares the TOKEN with all participating Signers over a > secure channel. > > ====Signer==== > > * The Signer generates a key record by prompting the user for the TOKEN > and a derivation path. > * The first line in the record must be the <tt>TOKEN</tt>. If encryption > is disabled, set the TOKEN to -1. The second line must be the <tt>KEY</tt>, > whereas KEY is an XPUB. KEY must include key origin information and written > in the descriptor-defined format, i.e.: <tt>[{master key > fingerprint}/{derivation path}]{XPUB}</tt>. The third line must be a > <tt>SIG</tt>, whereas SIG is the signature generated by using the > corresponding private key to sign the first two lines. Finally, the Signer > encrypts the entire record with ENCRYPTION_KEY. > > ===Round 2=== > > ====Coordinator==== > > * The Coordinator gathers key records from all participating Signers. > Abort the setup if TOKEN has expired. > * For each key record, the Coordinator decrypts it using ENCRYPTION_KEY. > The Coordinator verifies that the included SIG is valid given the KEY. > * If all key records look good, the Coordinator generates a descriptor > record, which is simply the descriptor string plus a <tt>CHECKSUM</tt>, all > in one line. The CHECKSUM has BECH32 encoding and is described at [ > https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums]. > The Coordinator encrypts this descriptor record with ENCRYPTION_KEY. > * The Coordinator sends the encrypted descriptor record to all > participating Signers. > > ====Signer==== > > * The Signer imports the descriptor record, decrypts it by prompting the > user for TOKEN. > * The Signer calculates and verifies the descriptor’s CHECKSUM. Abort the > setup if the CHECKSUM is incorrect. > * The Signer checks whether one of the KEYs in the descriptor belongs to > it, using path and fingerprint information included in the descriptor. The > check must perform an exact match on the KEYs, and not using shortcuts such > as matching fingerprints (which is trivial to spoof). Abort the setup if it > doesn’t detect its own KEY. > * For confirmation, the Signer must display to the user the descriptor's > CHECKSUM, plus other configurations, such as M and N. The total number of > Signers, N, is important to prevent a KEY insertion attack. All > participating Signers should be able to display the same confirmation. > * If all checks pass, the Signer persists the descriptor record in its > storage. The Signer should subsequently use the descriptor to generate and > verify receive and change addresses. > > This completes the setup. > > ==QR Codes== > For signers that use QR codes to transmit data, key and descriptor records > can be converted to QR codes, following [ > https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md > the BCR standard]. > > ==Security== > > This proposal introduce two layers of protection. The first one is a > temporary, secret token, used to encrypt the two rounds of communication > between the Signers and the Coordinator. The second one is through the > descriptor checksum and visual inspection of the descriptor itself. > > The token is only needed during the setup phase, and can be safely thrown > away afterwards. The token does not guarantee that the Signer membership > set is not modified, since that depends on the overall security of all > parties in the setup, but it can make it significantly harder for an > attacker to do so. > > There are three ways an attacker can modify the membership set: by > changing an existing member, by removing an existing member, or by adding a > new member. > > For the first two methods, one of the Signers will be able to detect that > its membership has been changed or removed, and reject the final > descriptor. Thus, it is vital that all participating Signers check that > their membership is intact in the descriptor. Even one Signer failing to > check for its membership means that the setup could be compromised. > > For the third type of attack, the descriptor checksum and visual > inspection of the descriptor itself are the only way to guard against > malicious members from being inserted into the set. > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists•linuxfoundation•org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >
In the Airgapped Wallet Community we also have been investigating solutions, in particular as current common practice is is reuse the same xpub for all multisigs, for instance [90081696/48'/0'/0'/2'] xpub6DYLEkDfCdHzh5FHGHDJksQvFqu6kYANa1sfo6fA8n5ZWkSwyCRVVzyq9LY2eNGB6T9BKDeGJp2ZarjRZHd7WB95nSaFEDhFMK6zSV6D49b
We’ve also have been looking into multi round commitment scheme, but wanted to align the UX so that it would work like to musig for users. Discussion on it is scattered, for instance https://github.com/BlockchainCommons/Airgapped-Wallet-Community/discussions/16#discussioncomment-212013
Nothing got as far as your version though.
So Concept ACK from Blockchain Commons. Less clear on your specifics though. We will review.
Note that we are releasing a descriptor & multisig centric iOS and Android reference wallet soon so solving this correctly and having interoperability with others is very important for our roadmap.
— Christopher Allen
Hi Craig, Comments inline.
On Tue, Feb 9, 2021 at 1:17 AM Craig Raw <craigraw@gmail•com> wrote:
Quoted text (18 lines)
> Hi Hugo, > > Thanks for raising this again - I'll note there has already been much > discussion on this topic. With respect to your "two layers of protection": > > > The Coordinator shares the TOKEN with all participating Signers over a > secure channel. > > What secure channel do you propose? Currently, with the default of a > software wallet coordinator talking to hardware wallets, we have USB, file > (microSD), and QR as communication channels. It's unclear to me why the > token and encryption process is necessary - in fact it's easier to verify > what is going on using clear text, and the majority of setups will be > locally done with the reasonable assumption of a secure environment. When > the setup is remote, it's simpler to just transmit the key information over > the secure channel which presumably already has encryption. > >
In short, a shared secret (the TOKEN) is needed because without it you cannot guarantee that the devices you are connecting to are legitimate members of the multisig wallet. Yes, the connection between the coordinator and each device could be secure - but a malicious actor can establish a secure channel just as well as a good one. You are correct that this is less of an issue for local setups, but this is especially important for distributed multisig - where you cannot physically see what's on the other side.
I would love to remove the shared secret/encryption aspect out of the proposal, but so far I haven't found any way around this issue, aside from establishing a shared secret prior to setting up the wallet...
I also realized that supporting this could be a big ask for vendors, so I've made this part of the proposal optional.
Another note here is that right after I posted the proposal (classic...), I also realized there could be another optimization: the secure session established by the shared secret can remain open indefinitely on the device side - until a different TOKEN is entered. That way the user needs to enter the TOKEN only once, saving us one interaction.
Quoted text (14 lines)
> > The second one is through the descriptor checksum and visual inspection > of the descriptor itself. > > This is a reasonable suggestion, although it's worth noting that support > for storing multisig setups on hardware wallets varies. Coldcard supports > this through importing of a proprietary .txt format file (which has been > adopted by a number of other vendors). Trezor and Ledger (AFAIK) do not > however store multisig setups, which could make this step confusing. With > that said, the use of an output descriptor is certainly a more standardised > approach, albeit one without the wallet name included. By the use of the > singular, I assume you mean a descriptor without the /0/* or /1/* suffix > (which I think is a good idea). > >
I'm aware that Trezor and Ledger currently cannot support this. But IMHO lack of support on some devices shouldn't prevent us from setting a good standard here. Cosigner registration on the device is crucial, as you don't have to rely on everything being included in the PSBT (which also adds mental overhead as the user has to verify each and every transaction).
Yes, descriptor without the /0/* and /1/* - Thanks for clarifying. Will update the proposal.
Quoted text (14 lines)
> WRT to QR codes, using the BCR UR2.0 standard you linked to is IMO the > right approach. I'll link directly to the two BCR UR2.0 formats here which > are relevant: > > 1. For sharing the sharing the BIP44 account information from the signers > to the coordinator, the crypto-account format: [ > https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-015-account.md > ] > 2. For sharing the output descriptor from the coordinator to the signers, > the crypto-output format: [ > https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-010-output-desc.md > ] > >
Thanks, will update!
Quoted text (209 lines)
> Craig > > > > On Tue, Feb 9, 2021 at 9:53 AM Hugo Nguyen via bitcoin-dev < > bitcoin-dev@lists•linuxfoundation•org> wrote: > >> Hi all, >> I would like to propose a new BIP for Secure Multisig Setup. >> This proposal has taken inputs from folks at Coldcard, Shift Crypto and >> Cobo -- listed below as co-authors. >> >> This was inspired by my own experience working with hardware wallets on >> the market, as well as existing research into the challenges of multisig. >> >> Cheers, >> Hugo >> >> <pre> >> BIP: To be determined >> Layer: Applications >> Title: Bitcoin Secure Multisig Setup (BSMS) >> Author: Hugo Nguyen <hugo@nunchuk•io>, Peter Gray <peter@coinkite•com>, >> Marko Bencun <marko@shiftcrypto•ch>, Aaron Chen <aarondongchen@gmail•com>, >> Rodolfo Novak <rodolfo@coinkite•com> >> Comments-Summary: No comments yet. >> Comments-URI: >> Status: Proposed >> Type: Standards Track >> Created: 2020-11-10 >> License: BSD-2-Clause >> </pre> >> >> ==Introduction== >> >> ===Abstract=== >> >> This document proposes a mechanism to set up multisig wallets securely. >> >> ===Copyright=== >> >> This BIP is licensed under the 2-clause BSD license. >> >> ===Motivation=== >> >> The Bitcoin multisig experience has been greatly streamlined under [ >> https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki BIP-0174 >> (Partially Signed Bitcoin Transaction)]. However, what is still missing is >> a standardized process for setting up multisig wallets securely across >> different vendors. >> >> There are a number of concerns when it comes to setting up a multisig >> wallet: >> >> # Whether the multisig configuration, such as Signer membership, script >> type, derivation paths and number of signatures required, is correct and >> not tampered with. >> # Whether Signer persists the multisig configuration in their respective >> storage, and under what format. >> # Whether Signer's storage is tamper-proof. >> # Whether Signer subsequently uses the multisig configuration to generate >> and verify receive and change addresses. >> >> An attacker who can modify the multisig configuration can steal or hold >> funds to ransom by duping the user into sending funds to the wrong address. >> >> This proposal seeks to address concerns #1 and #2: to mitigate the risk >> of tampering during the initial setup phase, and to define an interoperable >> multisig configuration format. >> >> Concerns #3 and #4 should be handled by Signers and is out of scope of >> this proposal. >> >> ==Specification== >> >> ===Prerequisites=== >> This proposal assumes the parties in the multisig support [ >> https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32], [ >> https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the >> descriptor language] and encryption. >> >> ==Roles== >> ===Coordinator=== >> >> The Coordinator initiates the multisig setup. The Coordinator determines >> what type of multisig is used and how many members and signatures are >> needed. If encryption is enabled, the Coordinator generates a secret token, >> to be shared among the parties for secure communication. The Coordinator >> gathers information from the Signers to generate a descriptor record. The >> Coordinator distributes the descriptor record back to the Signers. >> >> ===Signer=== >> >> The Signer is a participating member in the multisig. Its >> responsibilities include providing its XPUB to the Coordinator, verifying >> that its XPUB is included in the descriptor record and persisting the >> descriptor record in its storage. >> >> ==Setup Process== >> >> ===Round 1=== >> >> ====Coordinator==== >> >> * The Coordinator creates a multisig wallet creation session. The >> Coordinator determines the type of multisig script used and the signing >> configuration (<tt>M</tt> and <tt>N</tt>). >> * If encryption is enabled, the Coordinator also generates a secret >> token, hereby denoted <tt>TOKEN</tt>. >> * TOKEN is in ASCII format and must have a minimum of 8 characters. TOKEN >> should expire after some time period determined by the Coordinator, e.g., >> 24 hours. >> * TOKEN acts as an encryption key among the parties. The method of >> encryption is AES, CTR mode. The encryption key can be calculated by >> performing a double hash operation on the TOKEN: <tt>ENCRYPTION_KEY = >> SHA256(SHA256(TOKEN))</tt>. >> * A TOKEN value of <tt>-1</tt> means that encryption is disabled and all >> the encryption/decryption steps below can be skipped. >> * The Coordinator shares the TOKEN with all participating Signers over a >> secure channel. >> >> ====Signer==== >> >> * The Signer generates a key record by prompting the user for the TOKEN >> and a derivation path. >> * The first line in the record must be the <tt>TOKEN</tt>. If encryption >> is disabled, set the TOKEN to -1. The second line must be the <tt>KEY</tt>, >> whereas KEY is an XPUB. KEY must include key origin information and written >> in the descriptor-defined format, i.e.: <tt>[{master key >> fingerprint}/{derivation path}]{XPUB}</tt>. The third line must be a >> <tt>SIG</tt>, whereas SIG is the signature generated by using the >> corresponding private key to sign the first two lines. Finally, the Signer >> encrypts the entire record with ENCRYPTION_KEY. >> >> ===Round 2=== >> >> ====Coordinator==== >> >> * The Coordinator gathers key records from all participating Signers. >> Abort the setup if TOKEN has expired. >> * For each key record, the Coordinator decrypts it using ENCRYPTION_KEY. >> The Coordinator verifies that the included SIG is valid given the KEY. >> * If all key records look good, the Coordinator generates a descriptor >> record, which is simply the descriptor string plus a <tt>CHECKSUM</tt>, all >> in one line. The CHECKSUM has BECH32 encoding and is described at [ >> https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums]. >> The Coordinator encrypts this descriptor record with ENCRYPTION_KEY. >> * The Coordinator sends the encrypted descriptor record to all >> participating Signers. >> >> ====Signer==== >> >> * The Signer imports the descriptor record, decrypts it by prompting the >> user for TOKEN. >> * The Signer calculates and verifies the descriptor’s CHECKSUM. Abort the >> setup if the CHECKSUM is incorrect. >> * The Signer checks whether one of the KEYs in the descriptor belongs to >> it, using path and fingerprint information included in the descriptor. The >> check must perform an exact match on the KEYs, and not using shortcuts such >> as matching fingerprints (which is trivial to spoof). Abort the setup if it >> doesn’t detect its own KEY. >> * For confirmation, the Signer must display to the user the descriptor's >> CHECKSUM, plus other configurations, such as M and N. The total number of >> Signers, N, is important to prevent a KEY insertion attack. All >> participating Signers should be able to display the same confirmation. >> * If all checks pass, the Signer persists the descriptor record in its >> storage. The Signer should subsequently use the descriptor to generate and >> verify receive and change addresses. >> >> This completes the setup. >> >> ==QR Codes== >> For signers that use QR codes to transmit data, key and descriptor >> records can be converted to QR codes, following [ >> https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md >> the BCR standard]. >> >> ==Security== >> >> This proposal introduce two layers of protection. The first one is a >> temporary, secret token, used to encrypt the two rounds of communication >> between the Signers and the Coordinator. The second one is through the >> descriptor checksum and visual inspection of the descriptor itself. >> >> The token is only needed during the setup phase, and can be safely thrown >> away afterwards. The token does not guarantee that the Signer membership >> set is not modified, since that depends on the overall security of all >> parties in the setup, but it can make it significantly harder for an >> attacker to do so. >> >> There are three ways an attacker can modify the membership set: by >> changing an existing member, by removing an existing member, or by adding a >> new member. >> >> For the first two methods, one of the Signers will be able to detect that >> its membership has been changed or removed, and reject the final >> descriptor. Thus, it is vital that all participating Signers check that >> their membership is intact in the descriptor. Even one Signer failing to >> check for its membership means that the setup could be compromised. >> >> For the third type of attack, the descriptor checksum and visual >> inspection of the descriptor itself are the only way to guard against >> malicious members from being inserted into the set. >> _______________________________________________ >> bitcoin-dev mailing list >> bitcoin-dev@lists•linuxfoundation•org >> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >> >
Hi Christopher, Comments inline.
On Tue, Feb 9, 2021 at 1:31 AM Christopher Allen < ChristopherA@lifewithalacrity•com> wrote:
Quoted text (6 lines)
> In the Airgapped Wallet Community we also have been investigating > solutions, in particular as current common practice is is reuse the same > xpub for all multisigs, for instance [90081696/48'/0'/0'/2'] > xpub6DYLEkDfCdHzh5FHGHDJksQvFqu6kYANa1sfo6fA8n5ZWkSwyCRVVzyq9LY2eNGB6T9BKDeGJp2ZarjRZHd7WB95nSaFEDhFMK6zSV6D49b > >
I don't think reusing XPUBs inside different multisig wallets is a good idea... For starters, loss of privacy in one wallet will immediately affect privacy of other wallets. I think multisig wallets should be completely firewalled from each other. That means one unique XPUB per wallet. This is what we have been doing with the Nunchuk wallet.
Quoted text (15 lines)
> We’ve also have been looking into multi round commitment scheme, but > wanted to align the UX so that it would work like to musig for users. > Discussion on it is scattered, for instance > > https://github.com/BlockchainCommons/Airgapped-Wallet-Community/discussions/16#discussioncomment-212013 > > Nothing got as far as your version though. > > So Concept ACK from Blockchain Commons. Less clear on your specifics > though. We will review. > > Note that we are releasing a descriptor & multisig centric iOS and Android > reference wallet soon so solving this correctly and having interoperability > with others is very important for our roadmap. >
Thank you and good to know ! Look forward to solving this correctly as well.
Best,
Hugo
Quoted text (4 lines)
> > — Christopher Allen > >
On Tue, Feb 9, 2021 at 2:19 AM Christopher Allen < ChristopherA@lifewithalacrity•com> wrote:
Quoted text (23 lines)
> > > On Tue, Feb 9, 2021 at 2:06 AM Hugo Nguyen <hugo@nunchuk•io> wrote: > >> >> I don't think reusing XPUBs inside different multisig wallets is a good >> idea... For starters, loss of privacy in one wallet will immediately affect >> privacy of other wallets. I think multisig wallets should be completely >> firewalled from each other. That means one unique XPUB per wallet. This is >> what we have been doing with the Nunchuk wallet. >> > > To be clear, I have stated repeatedly that xpub reuse into multisig is a > poor practice. However, finding a trustless solution when a wallet is > airgapped with no network, or is stateless like Trezor, is quite hard. > > The challenge also includes how does an airgapped or stateless wallet know > that it is talking to the same process on the other side that that it gave > the xpub to in the first place. Without state to allow for a commitment, or > at least a TOFU, a cosigner who thought he was part of a 3 of 5 could > discover that he instead is in a 2 of 3, or in a script with an OR, as some > form of scam. >
The shared secret approach that I mentioned in the proposal actually can help you here. The TOKEN doubles as a session ID - thereby establishing a common state on both sides.
Best, Hugo
Quoted text (4 lines)
> > — Christopher Allen > >>
Quoted text (1 line)
> ENCRYPTION_KEY = SHA256(SHA256(TOKEN))
This scheme might be vulnerable to rainbow table attack.
The following scheme might be more secure:
DESCRIPTION = ASCII description provided by user NONCE = 256-bit random number ENCRYPTION_KEY = hmac-sha256(key=NONCE, msg=DESCRIPTION)
Coordinator distributes DESCRIPTION (fka TOKEN) together with NONCE to the signers.
Also, is there any reason why you'd want to disable encryption? Why not keep that as mandatory?
On Tue, 9 Feb 2021 at 12:39, Hugo Nguyen via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (45 lines)
> > > On Tue, Feb 9, 2021 at 2:19 AM Christopher Allen < > ChristopherA@lifewithalacrity•com> wrote: > >> >> >> On Tue, Feb 9, 2021 at 2:06 AM Hugo Nguyen <hugo@nunchuk•io> wrote: >> >>> >>> I don't think reusing XPUBs inside different multisig wallets is a good >>> idea... For starters, loss of privacy in one wallet will immediately affect >>> privacy of other wallets. I think multisig wallets should be completely >>> firewalled from each other. That means one unique XPUB per wallet. This is >>> what we have been doing with the Nunchuk wallet. >>> >> >> To be clear, I have stated repeatedly that xpub reuse into multisig is a >> poor practice. However, finding a trustless solution when a wallet is >> airgapped with no network, or is stateless like Trezor, is quite hard. >> >> The challenge also includes how does an airgapped or stateless wallet >> know that it is talking to the same process on the other side that that it >> gave the xpub to in the first place. Without state to allow for a >> commitment, or at least a TOFU, a cosigner who thought he was part of a 3 >> of 5 could discover that he instead is in a 2 of 3, or in a script with an >> OR, as some form of scam. >> > > The shared secret approach that I mentioned in the proposal actually can > help you here. The TOKEN doubles as a session ID - thereby establishing a > common state on both sides. > > Best, > Hugo > > >> >> — Christopher Allen >> >>> _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists•linuxfoundation•org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >
Hi Pavol,
On Thu, Feb 11, 2021 at 5:25 AM Pavol Rusnak <stick@satoshilabs•com> wrote:
Quoted text (4 lines)
> > ENCRYPTION_KEY = SHA256(SHA256(TOKEN)) > > This scheme might be vulnerable to rainbow table attack. >
Thank you for pointing this out! Incidentally, Dmitry Petukhov also told me the same privately.
Quoted text (10 lines)
> > The following scheme might be more secure: > > DESCRIPTION = ASCII description provided by user > NONCE = 256-bit random number > ENCRYPTION_KEY = hmac-sha256(key=NONCE, msg=DESCRIPTION) > > Coordinator distributes DESCRIPTION (fka TOKEN) together with NONCE to > the signers. >
This does seem to add a lot more entropy. The challenge is to balance the security requirement with UX. In the absence of some handshake protocol to exchange the shared secrets (DESCRIPTION / NONCE) , the user will have to enter these manually on the devices. I'll think about this some more.
Quoted text (4 lines)
> > Also, is there any reason why you'd want to disable encryption? Why not > keep that as mandatory? >
Making it mandatory would be nice, but IMHO not all use cases might require encryption. For example, if you are setting up the multisig locally under a safe environment you control, encryption might be an overkill.
Best, Hugo
Quoted text (59 lines)
> > > On Tue, 9 Feb 2021 at 12:39, Hugo Nguyen via bitcoin-dev < > bitcoin-dev@lists•linuxfoundation•org> wrote: > >> >> >> On Tue, Feb 9, 2021 at 2:19 AM Christopher Allen < >> ChristopherA@lifewithalacrity•com> wrote: >> >>> >>> >>> On Tue, Feb 9, 2021 at 2:06 AM Hugo Nguyen <hugo@nunchuk•io> wrote: >>> >>>> >>>> I don't think reusing XPUBs inside different multisig wallets is a good >>>> idea... For starters, loss of privacy in one wallet will immediately affect >>>> privacy of other wallets. I think multisig wallets should be completely >>>> firewalled from each other. That means one unique XPUB per wallet. This is >>>> what we have been doing with the Nunchuk wallet. >>>> >>> >>> To be clear, I have stated repeatedly that xpub reuse into multisig is a >>> poor practice. However, finding a trustless solution when a wallet is >>> airgapped with no network, or is stateless like Trezor, is quite hard. >>> >>> The challenge also includes how does an airgapped or stateless wallet >>> know that it is talking to the same process on the other side that that it >>> gave the xpub to in the first place. Without state to allow for a >>> commitment, or at least a TOFU, a cosigner who thought he was part of a 3 >>> of 5 could discover that he instead is in a 2 of 3, or in a script with an >>> OR, as some form of scam. >>> >> >> The shared secret approach that I mentioned in the proposal actually can >> help you here. The TOKEN doubles as a session ID - thereby establishing a >> common state on both sides. >> >> Best, >> Hugo >> >> >>> >>> — Christopher Allen >>> >>>> _______________________________________________ >> bitcoin-dev mailing list >> bitcoin-dev@lists•linuxfoundation•org >> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >> > > > -- > Best Regards / S pozdravom, > > Pavol "stick" Rusnak > CTO, SatoshiLabs > >
В Thu, 11 Feb 2021 05:45:33 -0800 Hugo Nguyen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (7 lines)
> > > ENCRYPTION_KEY = SHA256(SHA256(TOKEN)) > > > > This scheme might be vulnerable to rainbow table attack. > > > > Thank you for pointing this out! Incidentally, Dmitry Petukhov also > told me the same privately.
My thought was that if TOKEN has the characteristics of a password (short ASCII string), then it would be better to use key derivation function designed for passwords, like PBKDF2.
The counter-argument to this is that this adds another code dependency for vendors, if the device firmware does not already have the required key derivation function.
Maybe this could be solved by going into opposite direction - make the "token" even longer, use the mnemoic.
The issue is that entering long data of the shared key into the device manually is difficult UX-wise.
Hww vendors that allow to enter custom keys into their device already have to face this issue, and those who allow to enter custom keys via mnemonic probably tackled this somehow.
Maybe the shared key for multisig setup can be entered in the same way ? (with maybe additional visual check via some fingerprint).
Although we would then have another issue of potential confusion between two procedures (entering the main key and entering the shared key for multisig setup), and the measures has to be taken to prevent such confusion.
The approaches can be combined - specify a key derivation function suitable for passwords; via secure channel, share a password and/or the derived key. If hww supports derivation function, it can derive the key from password. If hww supports only keys, the key can be entered raw or via mnemonic.
Hi Pavol,
On Thu, Feb 11, 2021 at 8:25 AM Dmitry Petukhov via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (33 lines)
> В Thu, 11 Feb 2021 05:45:33 -0800 > Hugo Nguyen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> > wrote: > > > > > ENCRYPTION_KEY = SHA256(SHA256(TOKEN)) > > > > > > This scheme might be vulnerable to rainbow table attack. > > > > > > > Thank you for pointing this out! Incidentally, Dmitry Petukhov also > > told me the same privately. > > My thought was that if TOKEN has the characteristics of a password > (short ASCII string), then it would be better to use key derivation > function designed for passwords, like PBKDF2. > > The counter-argument to this is that this adds another code dependency > for vendors, if the device firmware does not already have the required > key derivation function. > > Maybe this could be solved by going into opposite direction - make the > "token" even longer, use the mnemoic. > > The issue is that entering long data of the shared key into the device > manually is difficult UX-wise. > > Hww vendors that allow to enter custom keys into their device already > have to face this issue, and those who allow to enter custom keys via > mnemonic probably tackled this somehow. > > Maybe the shared key for multisig setup can be entered in the same way > ? (with maybe additional visual check via some fingerprint). >
You just gave me a great idea! We can reuse the BIP32 seed words list! Perhaps the encryption key can just be 6 words, but it'll be derived the same way. BIP39 also uses PBKDF2 as a key derivation function, so it matches with what you described here.
And all HWW should have this functionality already.
Best, Hugo
Quoted text (16 lines)
> > Although we would then have another issue of potential confusion > between two procedures (entering the main key and entering the shared > key for multisig setup), and the measures has to be taken to prevent > such confusion. > > The approaches can be combined - specify a key derivation function > suitable for passwords; via secure channel, share a password and/or the > derived key. If hww supports derivation function, it can derive the key > from password. If hww supports only keys, the key can be entered raw or > via mnemonic. > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists•linuxfoundation•org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >
*BIP39 seed words list.
On Thu, Feb 11, 2021 at 11:11 AM Hugo Nguyen <hugo@nunchuk•io> wrote:
Quoted text (67 lines)
> Hi Pavol, > > On Thu, Feb 11, 2021 at 8:25 AM Dmitry Petukhov via bitcoin-dev < > bitcoin-dev@lists•linuxfoundation•org> wrote: > >> В Thu, 11 Feb 2021 05:45:33 -0800 >> Hugo Nguyen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> >> wrote: >> >> > > > ENCRYPTION_KEY = SHA256(SHA256(TOKEN)) >> > > >> > > This scheme might be vulnerable to rainbow table attack. >> > > >> > >> > Thank you for pointing this out! Incidentally, Dmitry Petukhov also >> > told me the same privately. >> >> My thought was that if TOKEN has the characteristics of a password >> (short ASCII string), then it would be better to use key derivation >> function designed for passwords, like PBKDF2. >> >> The counter-argument to this is that this adds another code dependency >> for vendors, if the device firmware does not already have the required >> key derivation function. >> >> Maybe this could be solved by going into opposite direction - make the >> "token" even longer, use the mnemoic. >> >> The issue is that entering long data of the shared key into the device >> manually is difficult UX-wise. >> >> Hww vendors that allow to enter custom keys into their device already >> have to face this issue, and those who allow to enter custom keys via >> mnemonic probably tackled this somehow. >> >> Maybe the shared key for multisig setup can be entered in the same way >> ? (with maybe additional visual check via some fingerprint). >> > > You just gave me a great idea! We can reuse the BIP32 seed words list! > Perhaps the encryption key can just be 6 words, but it'll be derived the > same way. BIP39 also uses PBKDF2 as a key derivation function, so it > matches with what you described here. > > And all HWW should have this functionality already. > > Best, > Hugo > > >> >> Although we would then have another issue of potential confusion >> between two procedures (entering the main key and entering the shared >> key for multisig setup), and the measures has to be taken to prevent >> such confusion. >> >> The approaches can be combined - specify a key derivation function >> suitable for passwords; via secure channel, share a password and/or the >> derived key. If hww supports derivation function, it can derive the key >> from password. If hww supports only keys, the key can be entered raw or >> via mnemonic. >> _______________________________________________ >> bitcoin-dev mailing list >> bitcoin-dev@lists•linuxfoundation•org >> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >> >
I think the key issue here is avoiding xpub key reuse in multisig. Not only in the future with Schnorr, but we need it today!
Current common practice by hardware wallets is the 48'/0'/0'/2' derivation for segwit multsig ( e.g. [90081696/48'/0'/0'/2']xpub6DYLEkDfCdHzh5FHGHDJksQvFqu6kYANa1sfo6fA8n5ZWkSwyCRVVzyq9LY2eNGB6T9BKDeGJp2ZarjRZHd7WB95nSaFEDhFMK6zSV6D49b ) is the only one used for ALL multisigs offered by that hardware wallet.
As Pieter said, leveraging a HD path parameters can help, but we need a better, less reusable path for the index.
I personally suggest a simpler solution, which is to create an index using a PBKDF of the Account Policy (a descriptor with all xpubs and keys removed), plus optional notes. (BTW, I think double sha256 or HMAC is overkill).
Example: for the reference bit descriptor that might result in:
``` wsh(sortedmulti(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*)) ```
What Blockchain Commons (and the Airgapped Wallet Community) call a policy map would be
``` wsh(sortedmulti(1,,,)) ```
A PBKDF of that as would be unique for all 2 of 3 segwig transactions. With the addition of the addition of the Policy Map creators optional note, it would be truly unique. The Policy Map and/or PBKDF are small and could easily added to existing APIs.
So for legacy hardware, we can use existing 48' subtree, but 3' as the format for this form (2' is segwit), then the desktop can just ask for the /48'/0'/0'/3'/PBKDF' when it requests a new xpub from the hardware token. More sophisticated Airgapped apps you can send "wsh(sortedmulti(1,,,))"+label and let the cosigner app do the PBKDF, and optionally allow it return something different in a full keyset (i.e. "[90081696/48'/0'/0'/3'/af3948cg…'/]xpub6DYLEk…", and then the requesting app, knowing that it is different from the PBKDF can know what to do if it needs to what to ask for in the future.
The other advantage of this technique is that the cosigner app can know what policy it is participating in, before the descriptor is completed. It may decide it doesn't want to participate in some funky 4:9 with a weird script, and not return an xpub at all.
Long term I think a commitment scheme should be used, so that you don't reveal what xpub you offered until all the parties xpubs are shared, but as Pieter said, we can do that at the same time we do the musig. But we need to prevent xpub reuse NOW, and I think my proposal easy and could the job.
-- Christopher Allen, Blockchain Commons
On Thu, Feb 11, 2021 at 3:05 PM Christopher Allen via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (22 lines)
> What Blockchain Commons (and the Airgapped Wallet Community) call a policy > map would be > > ``` > wsh(sortedmulti(1,,,)) > ``` > > A PBKDF of that as would be unique for all 2 of 3 segwig transactions. > With the addition of the addition of the Policy Map creators optional note, > it would be truly unique. The Policy Map and/or PBKDF are small and could > easily added to existing APIs. > > So for legacy hardware, we can use existing 48' subtree, but 3' as the > format for this form (2' is segwit), then the desktop can just ask for the > /48'/0'/0'/3'/PBKDF' when it requests a new xpub from the hardware token. > More sophisticated Airgapped apps you can send > "wsh(sortedmulti(1,,,))"+label and let the cosigner app do the PBKDF, and > optionally allow it return something different in a full keyset (i.e. > "[90081696/48'/0'/0'/3'/af3948cg…'/]xpub6DYLEk…", and then the requesting > app, knowing that it is different from the PBKDF can know what to do if it > needs to what to ask for in the future. >
Thanks Christopher, very interesting ideas... A couple of thoughts: 1/ Generating the path index using the policy is clever. However, I think it has 2 problems. Number #1 is with the above scheme now you have a hard dependency on (policy map + note) - losing (policy map + note) means that you will lose access to PBKDF', and hence the funds permanently. At least with the current soluttions, you can look up what the most common derivation paths and indices are to recover funds in the worst case. 2/ Number #2 is that this wouldn't necessarily prevent XPUB reuse. It seems like the above scheme depends on (a) the Coordinator keeping track accurately of all the existing PBKDF-ed indices and (b) the Signer truthfully gives the XPUB at the path that the Coordinator asks for. In reality, neither of these conditions can be guaranteed. For example, the Signer could lie about the XPUB at /48'/0'/0'/3'/PBKDF' when it just keeps reusing the XPUB at /48'/0'/0'/2' 3/ Preventing XPUB reuse is an interesting problem, but IMHO it is beyond the scope of the current proposal. Maybe worth a separate BIP?
Best, Hugo
On Thu, Feb 11, 2021 at 3:05 PM Christopher Allen via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (61 lines)
> I think the key issue here is avoiding xpub key reuse in multisig. Not > only in the future with Schnorr, but we need it today! > > Current common practice by hardware wallets is the 48'/0'/0'/2' derivation > for segwit multsig ( e.g. > [90081696/48'/0'/0'/2']xpub6DYLEkDfCdHzh5FHGHDJksQvFqu6kYANa1sfo6fA8n5ZWkSwyCRVVzyq9LY2eNGB6T9BKDeGJp2ZarjRZHd7WB95nSaFEDhFMK6zSV6D49b > ) is the only one used for ALL multisigs offered by that hardware wallet. > > As Pieter said, leveraging a HD path parameters can help, but we need a > better, less reusable path for the index. > > I personally suggest a simpler solution, which is to create an index using > a PBKDF of the Account Policy (a descriptor with all xpubs and keys > removed), plus optional notes. (BTW, I think double sha256 or HMAC is > overkill). > > Example: for the reference bit descriptor that might result in: > > ``` > > wsh(sortedmulti(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*)) > ``` > > What Blockchain Commons (and the Airgapped Wallet Community) call a policy > map would be > > ``` > wsh(sortedmulti(1,,,)) > ``` > > A PBKDF of that as would be unique for all 2 of 3 segwig transactions. > With the addition of the addition of the Policy Map creators optional note, > it would be truly unique. The Policy Map and/or PBKDF are small and could > easily added to existing APIs. > > So for legacy hardware, we can use existing 48' subtree, but 3' as the > format for this form (2' is segwit), then the desktop can just ask for the > /48'/0'/0'/3'/PBKDF' when it requests a new xpub from the hardware token. > More sophisticated Airgapped apps you can send > "wsh(sortedmulti(1,,,))"+label and let the cosigner app do the PBKDF, and > optionally allow it return something different in a full keyset (i.e. > "[90081696/48'/0'/0'/3'/af3948cg…'/]xpub6DYLEk…", and then the requesting > app, knowing that it is different from the PBKDF can know what to do if it > needs to what to ask for in the future. > > The other advantage of this technique is that the cosigner app can know > what policy it is participating in, before the descriptor is completed. It > may decide it doesn't want to participate in some funky 4:9 with a weird > script, and not return an xpub at all. > > Long term I think a commitment scheme should be used, so that you don't > reveal what xpub you offered until all the parties xpubs are shared, but as > Pieter said, we can do that at the same time we do the musig. But we need > to prevent xpub reuse NOW, and I think my proposal easy and could the job. > > -- Christopher Allen, Blockchain Commons > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists•linuxfoundation•org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >
Hard no to this idea:
On Thu, Feb 11, 2021 at 02:29:46PM -0800, Christopher Allen proposed: ...
Quoted text (1 line)
> /48'/0'/0'/3'/PBKDF(complex string)'
As someone who has helped people find UTXO at key paths they didn't know/want, this is a terrible idea. Key derivation paths should be small, sequential integers, so they can be searched in reasonable time.
Of course when things are working it doesn't matter, but the stakes can be very high when they stop working.
This is true for multisig and single signer.
--- Peter D. Gray || Founder, Coinkite || Twitter: @dochex || GPG: A3A31BAD 5A2A5B10
On Thu, Feb 11, 2021 at 02:29:46PM -0800, Christopher Allen wrote:
Quoted text (55 lines)
> I think the key issue here is avoiding xpub key reuse in multisig. Not only > in the future with Schnorr, but we need it today! > > Current common practice by hardware wallets is the 48'/0'/0'/2' derivation > for segwit multsig ( e.g. > [90081696/48'/0'/0'/2']xpub6DYLEkDfCdHzh5FHGHDJksQvFqu6kYANa1sfo6fA8n5ZWkSwyCRVVzyq9LY2eNGB6T9BKDeGJp2ZarjRZHd7WB95nSaFEDhFMK6zSV6D49b > ) is the only one used for ALL multisigs offered by that hardware wallet. > > As Pieter said, leveraging a HD path parameters can help, but we need a > better, less reusable path for the index. > > I personally suggest a simpler solution, which is to create an index using > a PBKDF of the Account Policy (a descriptor with all xpubs and keys > removed), plus optional notes. (BTW, I think double sha256 or HMAC is > overkill). > > Example: for the reference bit descriptor that might result in: > > ``` > wsh(sortedmulti(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*)) > ``` > > What Blockchain Commons (and the Airgapped Wallet Community) call a policy > map would be > > ``` > wsh(sortedmulti(1,,,)) > ``` > > A PBKDF of that as would be unique for all 2 of 3 segwig transactions. With > the addition of the addition of the Policy Map creators optional note, it > would be truly unique. The Policy Map and/or PBKDF are small and could > easily added to existing APIs. > > So for legacy hardware, we can use existing 48' subtree, but 3' as the > format for this form (2' is segwit), then the desktop can just ask for the > /48'/0'/0'/3'/PBKDF' when it requests a new xpub from the hardware token. > More sophisticated Airgapped apps you can send > "wsh(sortedmulti(1,,,))"+label and let the cosigner app do the PBKDF, and > optionally allow it return something different in a full keyset (i.e. > "[90081696/48'/0'/0'/3'/af3948cg…'/]xpub6DYLEk…", and then the requesting > app, knowing that it is different from the PBKDF can know what to do if it > needs to what to ask for in the future. > > The other advantage of this technique is that the cosigner app can know > what policy it is participating in, before the descriptor is completed. It > may decide it doesn't want to participate in some funky 4:9 with a weird > script, and not return an xpub at all. > > Long term I think a commitment scheme should be used, so that you don't > reveal what xpub you offered until all the parties xpubs are shared, but as > Pieter said, we can do that at the same time we do the musig. But we need > to prevent xpub reuse NOW, and I think my proposal easy and could the job. > > -- Christopher Allen, Blockchain Commons
Thanks everyone who has provided inputs so far!
This is the new proposal for the encryption aspect of the scheme, based on all the feedback.
The key derivation function would be PBKDF2, with PRF = SHA512. This should be readily available on today's hardware already, as they are used for BIP39.
DK = PBKDF2(PRF, Password, Salt, c, dkLen) PRF = SHA512 Pwd = HUMAN_READABLE_TITLE Salt = NONCE c = 2048 dkLen = 256
HUMAN_READABLE_TITLE is in ASCII format, minimum length = 8, maximum length = 20. NONCE is a 64-bit number.
Reason for going with SHA512 is due to legacy support on some hardware. c=2048 also mimics BIP39. It takes about ~3 seconds to derive the encryption key on a 80Mhz MCU. We feel like this is a good enough tradeoff for this use case. The assumption here is that the secure session is only needed temporarily for a few hours, maybe up to one day.
The Coordinator and Signers agree and exchange these 2 secrets prior to the setup. The NONCE can be converted to either: (a) a 6-word phrase using BIP39 wordlist (b) a 20-digit decimal number (c) a QR code
Depending on the vendor. This flexibility in the data format allows each vendor to customize the UX based on their respective device capabilities.
Best, Hugo
On Thu, Feb 11, 2021 at 8:25 AM Dmitry Petukhov via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (48 lines)
> В Thu, 11 Feb 2021 05:45:33 -0800 > Hugo Nguyen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> > wrote: > > > > > ENCRYPTION_KEY = SHA256(SHA256(TOKEN)) > > > > > > This scheme might be vulnerable to rainbow table attack. > > > > > > > Thank you for pointing this out! Incidentally, Dmitry Petukhov also > > told me the same privately. > > My thought was that if TOKEN has the characteristics of a password > (short ASCII string), then it would be better to use key derivation > function designed for passwords, like PBKDF2. > > The counter-argument to this is that this adds another code dependency > for vendors, if the device firmware does not already have the required > key derivation function. > > Maybe this could be solved by going into opposite direction - make the > "token" even longer, use the mnemoic. > > The issue is that entering long data of the shared key into the device > manually is difficult UX-wise. > > Hww vendors that allow to enter custom keys into their device already > have to face this issue, and those who allow to enter custom keys via > mnemonic probably tackled this somehow. > > Maybe the shared key for multisig setup can be entered in the same way > ? (with maybe additional visual check via some fingerprint). > > Although we would then have another issue of potential confusion > between two procedures (entering the main key and entering the shared > key for multisig setup), and the measures has to be taken to prevent > such confusion. > > The approaches can be combined - specify a key derivation function > suitable for passwords; via secure channel, share a password and/or the > derived key. If hww supports derivation function, it can derive the key > from password. If hww supports only keys, the key can be entered raw or > via mnemonic. > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists•linuxfoundation•org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >
If HUMAN_READABLE_TITLE is the additional secret, the user would need to enter it on the device in addition to the nonce, wouldn't it defeat the advantage in UX that was gained by using (relatively) short nonce ?
Is 64 bit nonce not enough ?
It seems that to crack this with fixed Pwd and 64 bit nonce, the attacker will need to be about 10^15 more powerful than 80Mhz MCU: (2^64)/(0.3*10^15)/3600 = 17 hours. I don't know if 10^15 is realistic scale. Average desktop cpu seems to be about 10^3 more powerful than the mentioned MCU for this task.
Maybe for the UX it would be better to choose the number of rounds to use in PBKDF2, instead of using variable Pwd. Number of rounds will be easier to enter on the device (or just choose it from a set of pre-defined values). The more money is at stake, the higher number of rounds could the coordinator choose (taking into account the characteristics of the participant devices)
В Fri, 12 Feb 2021 08:55:55 -0800 Hugo Nguyen <hugo@nunchuk•io> wrote:
Quoted text (91 lines)
> Thanks everyone who has provided inputs so far! > > This is the new proposal for the encryption aspect of the scheme, > based on all the feedback. > > The key derivation function would be PBKDF2, with PRF = SHA512. This > should be readily available on today's hardware already, as they are > used for BIP39. > > DK = PBKDF2(PRF, Password, Salt, c, dkLen) > PRF = SHA512 > Pwd = HUMAN_READABLE_TITLE > Salt = NONCE > c = 2048 > dkLen = 256 > > HUMAN_READABLE_TITLE is in ASCII format, minimum length = 8, maximum > length = 20. > NONCE is a 64-bit number. > > Reason for going with SHA512 is due to legacy support on some > hardware. c=2048 also mimics BIP39. It takes about ~3 seconds to > derive the encryption key on a 80Mhz MCU. We feel like this is a good > enough tradeoff for this use case. The assumption here is that the > secure session is only needed temporarily for a few hours, maybe up > to one day. > > The Coordinator and Signers agree and exchange these 2 secrets prior > to the setup. The NONCE can be converted to either: > (a) a 6-word phrase using BIP39 wordlist > (b) a 20-digit decimal number > (c) a QR code > > Depending on the vendor. This flexibility in the data format allows > each vendor to customize the UX based on their respective device > capabilities. > > Best, > Hugo > > On Thu, Feb 11, 2021 at 8:25 AM Dmitry Petukhov via bitcoin-dev < > bitcoin-dev@lists•linuxfoundation•org> wrote: > > > В Thu, 11 Feb 2021 05:45:33 -0800 > > Hugo Nguyen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> > > wrote: > > > > > > > ENCRYPTION_KEY = SHA256(SHA256(TOKEN)) > > > > > > > > This scheme might be vulnerable to rainbow table attack. > > > > > > > > > > Thank you for pointing this out! Incidentally, Dmitry Petukhov > > > also told me the same privately. > > > > My thought was that if TOKEN has the characteristics of a password > > (short ASCII string), then it would be better to use key derivation > > function designed for passwords, like PBKDF2. > > > > The counter-argument to this is that this adds another code > > dependency for vendors, if the device firmware does not already > > have the required key derivation function. > > > > Maybe this could be solved by going into opposite direction - make > > the "token" even longer, use the mnemoic. > > > > The issue is that entering long data of the shared key into the > > device manually is difficult UX-wise. > > > > Hww vendors that allow to enter custom keys into their device > > already have to face this issue, and those who allow to enter > > custom keys via mnemonic probably tackled this somehow. > > > > Maybe the shared key for multisig setup can be entered in the same > > way ? (with maybe additional visual check via some fingerprint). > > > > Although we would then have another issue of potential confusion > > between two procedures (entering the main key and entering the > > shared key for multisig setup), and the measures has to be taken to > > prevent such confusion. > > > > The approaches can be combined - specify a key derivation function > > suitable for passwords; via secure channel, share a password and/or > > the derived key. If hww supports derivation function, it can derive > > the key from password. If hww supports only keys, the key can be > > entered raw or via mnemonic. > > _______________________________________________ > > bitcoin-dev mailing list > > bitcoin-dev@lists•linuxfoundation•org > > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > >
В Fri, 12 Feb 2021 18:42:31 +0100 Dmitry Petukhov <dp@simplexum•com> wrote:
Quoted text (6 lines)
> Maybe for the UX it would be better to choose the number of rounds to > use in PBKDF2, instead of using variable Pwd. Number of rounds will be > easier to enter on the device (or just choose it from a set of > pre-defined values). The more money is at stake, the higher number of > rounds could the coordinator choose (taking into account the > characteristics of the participant devices)
Or simply allow bigger entropy (more than 6 mnemonic words), if the coordinator feels that 64 bit of entropy is not enough.
On Fri, Feb 12, 2021 at 9:36 AM Dmitry Petukhov <dp@simplexum•com> wrote:
Quoted text (7 lines)
> If HUMAN_READABLE_TITLE is the additional secret, the user would need > to enter it on the device in addition to the nonce, wouldn't it defeat > the advantage in UX that was gained by using (relatively) short nonce ? > > Is 64 bit nonce not enough ? > >
Good question. If we don't need the extra entropy, we can fix the HUMAN_READABLE_TITLE string.
Something like "No SPOF". (No Single Point Of Failure).
Quoted text (15 lines)
> It seems that to crack this with fixed Pwd and 64 bit nonce, the > attacker will need to be about 10^15 more powerful than 80Mhz MCU: > (2^64)/(0.3*10^15)/3600 = 17 hours. I don't know if 10^15 is realistic > scale. Average desktop cpu seems to be about 10^3 more powerful than > the mentioned MCU for this task. > > Maybe for the UX it would be better to choose the number of rounds to > use in PBKDF2, instead of using variable Pwd. Number of rounds will be > easier to enter on the device (or just choose it from a set of > pre-defined values). The more money is at stake, the higher number of > rounds could the coordinator choose (taking into account the > characteristics of the participant devices) > > Or simply allow bigger entropy (more than 6 mnemonic words), if > the coordinator feels that 64 bit of entropy is not enough.
That could work. Allowing variable iteration count is probably better UX-wise.
Best, Hugo
Quoted text (97 lines)
> > В Fri, 12 Feb 2021 08:55:55 -0800 > Hugo Nguyen <hugo@nunchuk•io> wrote: > > > Thanks everyone who has provided inputs so far! > > > > This is the new proposal for the encryption aspect of the scheme, > > based on all the feedback. > > > > The key derivation function would be PBKDF2, with PRF = SHA512. This > > should be readily available on today's hardware already, as they are > > used for BIP39. > > > > DK = PBKDF2(PRF, Password, Salt, c, dkLen) > > PRF = SHA512 > > Pwd = HUMAN_READABLE_TITLE > > Salt = NONCE > > c = 2048 > > dkLen = 256 > > > > HUMAN_READABLE_TITLE is in ASCII format, minimum length = 8, maximum > > length = 20. > > NONCE is a 64-bit number. > > > > Reason for going with SHA512 is due to legacy support on some > > hardware. c=2048 also mimics BIP39. It takes about ~3 seconds to > > derive the encryption key on a 80Mhz MCU. We feel like this is a good > > enough tradeoff for this use case. The assumption here is that the > > secure session is only needed temporarily for a few hours, maybe up > > to one day. > > > > The Coordinator and Signers agree and exchange these 2 secrets prior > > to the setup. The NONCE can be converted to either: > > (a) a 6-word phrase using BIP39 wordlist > > (b) a 20-digit decimal number > > (c) a QR code > > > > Depending on the vendor. This flexibility in the data format allows > > each vendor to customize the UX based on their respective device > > capabilities. > > > > Best, > > Hugo > > > > On Thu, Feb 11, 2021 at 8:25 AM Dmitry Petukhov via bitcoin-dev < > > bitcoin-dev@lists•linuxfoundation•org> wrote: > > > > > В Thu, 11 Feb 2021 05:45:33 -0800 > > > Hugo Nguyen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> > > > wrote: > > > > > > > > > ENCRYPTION_KEY = SHA256(SHA256(TOKEN)) > > > > > > > > > > This scheme might be vulnerable to rainbow table attack. > > > > > > > > > > > > > Thank you for pointing this out! Incidentally, Dmitry Petukhov > > > > also told me the same privately. > > > > > > My thought was that if TOKEN has the characteristics of a password > > > (short ASCII string), then it would be better to use key derivation > > > function designed for passwords, like PBKDF2. > > > > > > The counter-argument to this is that this adds another code > > > dependency for vendors, if the device firmware does not already > > > have the required key derivation function. > > > > > > Maybe this could be solved by going into opposite direction - make > > > the "token" even longer, use the mnemoic. > > > > > > The issue is that entering long data of the shared key into the > > > device manually is difficult UX-wise. > > > > > > Hww vendors that allow to enter custom keys into their device > > > already have to face this issue, and those who allow to enter > > > custom keys via mnemonic probably tackled this somehow. > > > > > > Maybe the shared key for multisig setup can be entered in the same > > > way ? (with maybe additional visual check via some fingerprint). > > > > > > Although we would then have another issue of potential confusion > > > between two procedures (entering the main key and entering the > > > shared key for multisig setup), and the measures has to be taken to > > > prevent such confusion. > > > > > > The approaches can be combined - specify a key derivation function > > > suitable for passwords; via secure channel, share a password and/or > > > the derived key. If hww supports derivation function, it can derive > > > the key from password. If hww supports only keys, the key can be > > > entered raw or via mnemonic. > > > _______________________________________________ > > > bitcoin-dev mailing list > > > bitcoin-dev@lists•linuxfoundation•org > > > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > > > > >
I think that it is better to issue individual TOKEN for each participant. Otherwise it will be possible for one participant to attack another (intercept and replace their xpub sent to the coordinator).
It will also be convenient to have a public 'participant id', derived from the token. It can be derived from the same token, but with different (but fixed) `Pwd`. With unique token per participant, such derivation will uniquely identify each participant, so the coordinator won't need to try all the tokens to decrypt the data.
It will also be easier to deal with more elaborate setups where the position of the xpub in the descriptor does matter - for example, with miniscript-extended descriptors. With a descriptor template such as
`wsh(or(multi(2, <Alice>, <Bob>, <Carol>), older(1000, <Dylan>))`
The coordinator will be able to store the map between the participant labels (Alice, Bob, Carol, Dylan) and their participant ids (and the TOKENs). When the data from Alice comes with participant id attached, the coordinator will immediately know which TOKEN to use, and which place in the descriptor the xpub should be put in.
Of course this is all possible without 'participant id' derived from token, as long as there's unique TOKEN per participant - the coordinator can always try all the tokens to decrypt the data from participant. But implementors will likely invent their own ways to introduce 'participant id' anyway, as this is more convenient, and it might make sense to have this standardized, for interoperability.
В Fri, 12 Feb 2021 09:54:57 -0800 Hugo Nguyen <hugo@nunchuk•io> wrote:
Quoted text (141 lines)
> On Fri, Feb 12, 2021 at 9:36 AM Dmitry Petukhov <dp@simplexum•com> > wrote: > > > If HUMAN_READABLE_TITLE is the additional secret, the user would > > need to enter it on the device in addition to the nonce, wouldn't > > it defeat the advantage in UX that was gained by using (relatively) > > short nonce ? > > > > Is 64 bit nonce not enough ? > > > > > Good question. If we don't need the extra entropy, we can fix > the HUMAN_READABLE_TITLE string. > > Something like "No SPOF". (No Single Point Of Failure). > > > > > It seems that to crack this with fixed Pwd and 64 bit nonce, the > > attacker will need to be about 10^15 more powerful than 80Mhz MCU: > > (2^64)/(0.3*10^15)/3600 = 17 hours. I don't know if 10^15 is > > realistic scale. Average desktop cpu seems to be about 10^3 more > > powerful than the mentioned MCU for this task. > > > > Maybe for the UX it would be better to choose the number of rounds > > to use in PBKDF2, instead of using variable Pwd. Number of rounds > > will be easier to enter on the device (or just choose it from a set > > of pre-defined values). The more money is at stake, the higher > > number of rounds could the coordinator choose (taking into account > > the characteristics of the participant devices) > > > > > Or simply allow bigger entropy (more than 6 mnemonic words), if > > the coordinator feels that 64 bit of entropy is not enough. > > > That could work. Allowing variable iteration count is probably better > UX-wise. > > Best, > Hugo > > > > > > В Fri, 12 Feb 2021 08:55:55 -0800 > > Hugo Nguyen <hugo@nunchuk•io> wrote: > > > > > Thanks everyone who has provided inputs so far! > > > > > > This is the new proposal for the encryption aspect of the scheme, > > > based on all the feedback. > > > > > > The key derivation function would be PBKDF2, with PRF = SHA512. > > > This should be readily available on today's hardware already, as > > > they are used for BIP39. > > > > > > DK = PBKDF2(PRF, Password, Salt, c, dkLen) > > > PRF = SHA512 > > > Pwd = HUMAN_READABLE_TITLE > > > Salt = NONCE > > > c = 2048 > > > dkLen = 256 > > > > > > HUMAN_READABLE_TITLE is in ASCII format, minimum length = 8, > > > maximum length = 20. > > > NONCE is a 64-bit number. > > > > > > Reason for going with SHA512 is due to legacy support on some > > > hardware. c=2048 also mimics BIP39. It takes about ~3 seconds to > > > derive the encryption key on a 80Mhz MCU. We feel like this is a > > > good enough tradeoff for this use case. The assumption here is > > > that the secure session is only needed temporarily for a few > > > hours, maybe up to one day. > > > > > > The Coordinator and Signers agree and exchange these 2 secrets > > > prior to the setup. The NONCE can be converted to either: > > > (a) a 6-word phrase using BIP39 wordlist > > > (b) a 20-digit decimal number > > > (c) a QR code > > > > > > Depending on the vendor. This flexibility in the data format > > > allows each vendor to customize the UX based on their respective > > > device capabilities. > > > > > > Best, > > > Hugo > > > > > > On Thu, Feb 11, 2021 at 8:25 AM Dmitry Petukhov via bitcoin-dev < > > > bitcoin-dev@lists•linuxfoundation•org> wrote: > > > > > > > В Thu, 11 Feb 2021 05:45:33 -0800 > > > > Hugo Nguyen via bitcoin-dev > > > > <bitcoin-dev@lists•linuxfoundation•org> wrote: > > > > > > > > > > > ENCRYPTION_KEY = SHA256(SHA256(TOKEN)) > > > > > > > > > > > > This scheme might be vulnerable to rainbow table attack. > > > > > > > > > > > > > > > > Thank you for pointing this out! Incidentally, Dmitry Petukhov > > > > > also told me the same privately. > > > > > > > > My thought was that if TOKEN has the characteristics of a > > > > password (short ASCII string), then it would be better to use > > > > key derivation function designed for passwords, like PBKDF2. > > > > > > > > The counter-argument to this is that this adds another code > > > > dependency for vendors, if the device firmware does not already > > > > have the required key derivation function. > > > > > > > > Maybe this could be solved by going into opposite direction - > > > > make the "token" even longer, use the mnemoic. > > > > > > > > The issue is that entering long data of the shared key into the > > > > device manually is difficult UX-wise. > > > > > > > > Hww vendors that allow to enter custom keys into their device > > > > already have to face this issue, and those who allow to enter > > > > custom keys via mnemonic probably tackled this somehow. > > > > > > > > Maybe the shared key for multisig setup can be entered in the > > > > same way ? (with maybe additional visual check via some > > > > fingerprint). > > > > > > > > Although we would then have another issue of potential confusion > > > > between two procedures (entering the main key and entering the > > > > shared key for multisig setup), and the measures has to be > > > > taken to prevent such confusion. > > > > > > > > The approaches can be combined - specify a key derivation > > > > function suitable for passwords; via secure channel, share a > > > > password and/or the derived key. If hww supports derivation > > > > function, it can derive the key from password. If hww supports > > > > only keys, the key can be entered raw or via mnemonic. > > > > _______________________________________________ > > > > bitcoin-dev mailing list > > > > bitcoin-dev@lists•linuxfoundation•org > > > > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > > > > > > > >
After off-list discussion with Hugo, I'm convinced that adding a requirement for signers to derive participant ids is unnecessary complication that only buys slight convenience for coordinator, and this is not a net positive tradeoff.
And since the coordinator can choose to generate unique TOKEN per participant without participants even knowing about this, there's probably no reason to mention this possibility in the spec, either.
В Sun, 14 Feb 2021 11:37:52 +0100 Dmitry Petukhov <dp@simplexum•com> wrote:
Quoted text (175 lines)
> I think that it is better to issue individual TOKEN for each > participant. Otherwise it will be possible for one participant to > attack another (intercept and replace their xpub sent to the > coordinator). > > It will also be convenient to have a public 'participant id', derived > from the token. It can be derived from the same token, but with > different (but fixed) `Pwd`. With unique token per participant, such > derivation will uniquely identify each participant, so the coordinator > won't need to try all the tokens to decrypt the data. > > It will also be easier to deal with more elaborate setups where the > position of the xpub in the descriptor does matter - for example, with > miniscript-extended descriptors. With a descriptor template such as > > `wsh(or(multi(2, <Alice>, <Bob>, <Carol>), older(1000, <Dylan>))` > > The coordinator will be able to store the map between the participant > labels (Alice, Bob, Carol, Dylan) and their participant ids (and the > TOKENs). When the data from Alice comes with participant id attached, > the coordinator will immediately know which TOKEN to use, and which > place in the descriptor the xpub should be put in. > > Of course this is all possible without 'participant id' derived from > token, as long as there's unique TOKEN per participant - the > coordinator can always try all the tokens to decrypt the data from > participant. But implementors will likely invent their own ways to > introduce 'participant id' anyway, as this is more convenient, and it > might make sense to have this standardized, for interoperability. > > В Fri, 12 Feb 2021 09:54:57 -0800 > Hugo Nguyen <hugo@nunchuk•io> wrote: > > > On Fri, Feb 12, 2021 at 9:36 AM Dmitry Petukhov <dp@simplexum•com> > > wrote: > > > > > If HUMAN_READABLE_TITLE is the additional secret, the user would > > > need to enter it on the device in addition to the nonce, wouldn't > > > it defeat the advantage in UX that was gained by using > > > (relatively) short nonce ? > > > > > > Is 64 bit nonce not enough ? > > > > > > > > Good question. If we don't need the extra entropy, we can fix > > the HUMAN_READABLE_TITLE string. > > > > Something like "No SPOF". (No Single Point Of Failure). > > > > > > > > > It seems that to crack this with fixed Pwd and 64 bit nonce, the > > > attacker will need to be about 10^15 more powerful than 80Mhz MCU: > > > (2^64)/(0.3*10^15)/3600 = 17 hours. I don't know if 10^15 is > > > realistic scale. Average desktop cpu seems to be about 10^3 more > > > powerful than the mentioned MCU for this task. > > > > > > Maybe for the UX it would be better to choose the number of rounds > > > to use in PBKDF2, instead of using variable Pwd. Number of rounds > > > will be easier to enter on the device (or just choose it from a > > > set of pre-defined values). The more money is at stake, the higher > > > number of rounds could the coordinator choose (taking into account > > > the characteristics of the participant devices) > > > > > > > > Or simply allow bigger entropy (more than 6 mnemonic words), if > > > the coordinator feels that 64 bit of entropy is not enough. > > > > > > That could work. Allowing variable iteration count is probably > > better UX-wise. > > > > Best, > > Hugo > > > > > > > > > > В Fri, 12 Feb 2021 08:55:55 -0800 > > > Hugo Nguyen <hugo@nunchuk•io> wrote: > > > > > > > Thanks everyone who has provided inputs so far! > > > > > > > > This is the new proposal for the encryption aspect of the > > > > scheme, based on all the feedback. > > > > > > > > The key derivation function would be PBKDF2, with PRF = SHA512. > > > > This should be readily available on today's hardware already, as > > > > they are used for BIP39. > > > > > > > > DK = PBKDF2(PRF, Password, Salt, c, dkLen) > > > > PRF = SHA512 > > > > Pwd = HUMAN_READABLE_TITLE > > > > Salt = NONCE > > > > c = 2048 > > > > dkLen = 256 > > > > > > > > HUMAN_READABLE_TITLE is in ASCII format, minimum length = 8, > > > > maximum length = 20. > > > > NONCE is a 64-bit number. > > > > > > > > Reason for going with SHA512 is due to legacy support on some > > > > hardware. c=2048 also mimics BIP39. It takes about ~3 seconds to > > > > derive the encryption key on a 80Mhz MCU. We feel like this is a > > > > good enough tradeoff for this use case. The assumption here is > > > > that the secure session is only needed temporarily for a few > > > > hours, maybe up to one day. > > > > > > > > The Coordinator and Signers agree and exchange these 2 secrets > > > > prior to the setup. The NONCE can be converted to either: > > > > (a) a 6-word phrase using BIP39 wordlist > > > > (b) a 20-digit decimal number > > > > (c) a QR code > > > > > > > > Depending on the vendor. This flexibility in the data format > > > > allows each vendor to customize the UX based on their respective > > > > device capabilities. > > > > > > > > Best, > > > > Hugo > > > > > > > > On Thu, Feb 11, 2021 at 8:25 AM Dmitry Petukhov via bitcoin-dev > > > > < bitcoin-dev@lists•linuxfoundation•org> wrote: > > > > > > > > > В Thu, 11 Feb 2021 05:45:33 -0800 > > > > > Hugo Nguyen via bitcoin-dev > > > > > <bitcoin-dev@lists•linuxfoundation•org> wrote: > > > > > > > > > > > > > ENCRYPTION_KEY = SHA256(SHA256(TOKEN)) > > > > > > > > > > > > > > This scheme might be vulnerable to rainbow table attack. > > > > > > > > > > > > > > > > > > > Thank you for pointing this out! Incidentally, Dmitry > > > > > > Petukhov also told me the same privately. > > > > > > > > > > My thought was that if TOKEN has the characteristics of a > > > > > password (short ASCII string), then it would be better to use > > > > > key derivation function designed for passwords, like PBKDF2. > > > > > > > > > > The counter-argument to this is that this adds another code > > > > > dependency for vendors, if the device firmware does not > > > > > already have the required key derivation function. > > > > > > > > > > Maybe this could be solved by going into opposite direction - > > > > > make the "token" even longer, use the mnemoic. > > > > > > > > > > The issue is that entering long data of the shared key into > > > > > the device manually is difficult UX-wise. > > > > > > > > > > Hww vendors that allow to enter custom keys into their device > > > > > already have to face this issue, and those who allow to enter > > > > > custom keys via mnemonic probably tackled this somehow. > > > > > > > > > > Maybe the shared key for multisig setup can be entered in the > > > > > same way ? (with maybe additional visual check via some > > > > > fingerprint). > > > > > > > > > > Although we would then have another issue of potential > > > > > confusion between two procedures (entering the main key and > > > > > entering the shared key for multisig setup), and the measures > > > > > has to be taken to prevent such confusion. > > > > > > > > > > The approaches can be combined - specify a key derivation > > > > > function suitable for passwords; via secure channel, share a > > > > > password and/or the derived key. If hww supports derivation > > > > > function, it can derive the key from password. If hww supports > > > > > only keys, the key can be entered raw or via mnemonic. > > > > > _______________________________________________ > > > > > bitcoin-dev mailing list > > > > > bitcoin-dev@lists•linuxfoundation•org > > > > > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > > > > > > > > > > > >
Hi all, I have updated the proposal based on further feedback. The new spec is included at the bottom.
I have also created a public Github PR to make it easier to comment on the text of the spec itself: https://github.com/nunchuk-io/bips/pull/1 .
Could someone please let me know what else needs to be done before a BIP number can be assigned?
=== Quick summary of changes from last update ===
1. Define encryption modes
# NO_ENCRYPTION: Encryption is disabled. # STANDARD : the TOKEN is a 64-bit nonce. # EXTENDED : the TOKEN is a 128-bit nonce.
2. Define signature algorithm
Follow BIP-0322, legacy format allowed.
3. Multiple TOKENs (optional)
Also add an option where the Coordinator can choose to use one common TOKEN for all Signers, or use one per Signer.
=== End of summary ===
Cheers, Hugo
<pre> BIP: To be determined Layer: Applications Title: Bitcoin Secure Multisig Setup (BSMS) Author: Hugo Nguyen <hugo at nunchuk.io>, Peter Gray <peter at coinkite.com>, Marko Bencun <marko at shiftcrypto.ch>, Pavol Rusnak < stick@satoshilabs•com>, Aaron Chen <aarondongchen at gmail.com>, Rodolfo Novak <rodolfo at coinkite.com> Comments-Summary: No comments yet. Comments-URI: Status: Proposed Type: Standards Track Created: 2020-11-10 License: BSD-2-Clause </pre>
==Introduction==
===Abstract===
This document proposes a mechanism to set up multisig wallets securely.
===Copyright===
This BIP is licensed under the 2-clause BSD license.
===Motivation===
The Bitcoin multisig experience has been greatly streamlined under [ https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki BIP-0174 (Partially Signed Bitcoin Transaction)]. However, what is still missing is a standardized process for setting up multisig wallets securely across different vendors.
There are a number of concerns when it comes to setting up a multisig wallet:
# Whether the multisig configuration, such as Signer membership, script type, derivation paths and number of signatures required, is correct and not tampered with. # Whether Signer persists the multisig configuration in their respective storage, and under what format. # Whether Signer's storage is tamper-proof. # Whether Signer subsequently uses the multisig configuration to generate and verify receive and change addresses.
An attacker who can modify the multisig configuration can steal or hold funds to ransom by duping the user into sending funds to the wrong address.
This proposal seeks to address concerns #1 and #2: to mitigate the risk of tampering during the initial setup phase, and to define an interoperable multisig configuration format.
Concerns #3 and #4 should be handled by Signers and is out of scope of this proposal.
==Specification==
===Prerequisites=== This proposal assumes the parties in the multisig support [ https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP-0032], [ https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the descriptor language] and encryption.
===Roles=== ====Coordinator====
The Coordinator initiates the multisig setup. The Coordinator determines what type of multisig is used and the exact policy script. If encryption is enabled, the Coordinator also distributes a shared secret or shared secrets to the parties involved for secure communication. The Coordinator gathers information from the Signers to generate a descriptor record. The Coordinator distributes the descriptor record back to the Signers.
====Signer====
The Signer is a participating member in the multisig. Its responsibilities include providing its key record -- which contains an Extended Public Key (XPUB) -- to the Coordinator, verifying that its XPUB is included in the descriptor record and persisting the descriptor record in its storage.
===Setup Process===
====Round 1====
=====Coordinator=====
* The Coordinator creates a multisig wallet creation session. The Coordinator constructs the multisig script and its policy parameters, such as the total number of signers and the required number of signatures (<tt>M</tt> and <tt>N</tt>). * The session should expire after some time period determined by the Coordinator, e.g., 24 hours. * If encryption is enabled, the Coordinator distributes a secret <tt>TOKEN</tt> to each Signer over a secure channel. The Signer can use the <tt>TOKEN</tt> to derive an <tt>ENCRYPTION_KEY</tt>. Refer to the Encryption section below for details on the <tt>TOKEN</tt>, the key derivation function and the encryption scheme. Depending on the use case, the Coordinator can decide whether to share one common <tt>TOKEN</tt> for all Signers, or to have one per Signer. * If encryption is disabled, <tt>TOKEN</tt> is set to <tt>0</tt>, and all the encryption/decryption steps below can be skipped.
=====Signer=====
* The Signer initiates a new secure multisig setup session by setting the <tt>TOKEN</tt>. The Signer derives an <tt>ENCRYPTION_KEY</tt> from the <tt>TOKEN</tt>. The Signer can keep the session open until a different value for the <tt>TOKEN</tt> is set. * The Signer generates a key record by prompting the user for a multisig derivation path and retrieves the XPUB at that derivation path. Optionally, the Signer can choose a path on behalf of the user. If the Signer chooses the path, it should try to avoid reusing XPUBs for different wallets. * The first line in the record must be the <tt>TOKEN</tt>. The second line must be the <tt>KEY</tt>. The <tt>KEY</tt> is an XPUB plus its key origin information, written in the descriptor-defined format, i.e.: <tt>[{master key fingerprint}/{derivation path}]{XPUB}</tt>. The third line must be a <tt>SIG</tt>, whereas <tt>SIG</tt> is the signature generated by using the private key associated with the XPUB to sign the first two lines. The signature should follow [ https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki BIP-0322], legacy format accepted. Finally, the Signer encrypts the entire record with <tt>ENCRYPTION_KEY</tt>.
====Round 2====
=====Coordinator=====
* The Coordinator gathers key records from all participating Signers. Abort the setup if the wallet setup session has expired. * For each key record, the Coordinator decrypts it using <tt>ENCRYPTION_KEY</tt>. The Coordinator verifies that the included <tt>SIG</tt> is valid given the <tt>KEY</tt>. * If all key records look good, the Coordinator fills in all necessary information to generate a descriptor record, which is simply the descriptor string plus a <tt>CHECKSUM</tt>, all in one line. The <tt>CHECKSUM</tt> has [https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums BECH32 encoding]. * The Coordinator encrypts this descriptor record with <tt>ENCRYPTION_KEY</tt>. * The Coordinator sends the encrypted descriptor record to all participating Signers.
=====Signer=====
* The Signer imports the descriptor record, decrypts it using the <tt>ENCRYPTION_KEY</tt> derived from the open session. * The Signer calculates and verifies the descriptor’s <tt>CHECKSUM</tt>. Abort the setup if the <tt>CHECKSUM</tt> is incorrect. * The Signer checks whether one of the <tt>KEY</tt>s in the descriptor belongs to it, using path and fingerprint information included in the descriptor. The check must perform an exact match on the <tt>KEY</tt>s, and not using shortcuts such as matching fingerprints (which is trivial to spoof). Abort the setup if it doesn’t detect its own <tt>KEY</tt>. * For confirmation, the Signer must display to the user the <tt>CHECKSUM</tt>, plus other configurations, such as <tt>M</tt> and <tt>N</tt>. The total number of Signers, <tt>N</tt>, is important to prevent a <tt>KEY</tt> insertion attack. All participating Signers should be able to display the same confirmation. * If all checks pass, the Signer persists the descriptor record in its storage. * The Signer can choose to further restrict post-XPUB derivation paths, such as to those defined in [ https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki BIP-0044]. * The Signer should subsequently use the descriptor to generate and verify receive and change addresses.
This completes the setup.
===Encryption===
====The Token==== We define three modes of encryption.
# <tt>NO_ENCRYPTION</tt> : the <tt>TOKEN</tt> is set to <tt>0</tt>. Encryption is disabled. # <tt>STANDARD</tt> : the <tt>TOKEN</tt> is a 64-bit nonce. # <tt>EXTENDED</tt> : the <tt>TOKEN</tt> is a 128-bit nonce.
The <tt>TOKEN</tt> can be converted to one of these formats: * A mnemonic phrase using [ https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki BIP-0039] word list (6 words in <tt>STANDARD</tt> mode, 12 words in <tt>EXTENDED</tt> mode) * A decimal number (20 digits in <tt>STANDARD</tt> mode, 40 digits in <tt>EXTENDED</tt> mode) * A QR code * Other formats
The flexibility in the data format allows each Signer to customize the User Experience based on its respective capabilities.
====Key Derivation==== The key derivation function is [https://tools.ietf.org/html/rfc2898 PBKDF2], with PRF = SHA512. Specifically:
<tt>DK = PBKDF2(PRF, Password, Salt, c, dkLen)</tt>
Whereas:
* PRF = <tt>SHA512</tt> * Password = <tt>"No SPOF"</tt> * Salt = <tt>TOKEN</tt> * c = <tt>2048</tt> * dkLen = <tt>256</tt> * DK = Derived <tt>ENCRYPTION_KEY</tt>
====Encryption Scheme==== The encryption scheme is [https://tools.ietf.org/html/rfc3686 AES, CTR mode].
==QR Codes== For signers that use QR codes to transmit data, key and descriptor records can be converted to QR codes, following [ https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md the BCR standard].
Also refer to [ https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-015-account.md UR Type Definition for BIP44 Accounts] and [ https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-010-output-desc.md UR Type Definition for Bitcoin Output Descriptors] for more details.
==Security==
This proposal introduces two layers of protection. The first one is a temporary, secret token, used to encrypt the two rounds of communication between the Signer and the Coordinator. The second one is through the descriptor checksum and visual inspection of the descriptor itself.
The token is only needed during the setup phase, and can be safely thrown away afterwards. The token does not guarantee that the Signer membership set is not modified, since that depends on the overall security of all parties in the setup, but it can make it significantly harder for an attacker to do so.
There are three ways an attacker can modify the membership set: by changing an existing member, by removing an existing member, or by adding a new member.
For the first two methods, one of the Signers will be able to detect that its membership has been changed or removed, and reject the final descriptor. Thus, it is vital that all participating Signers check that their membership is intact in the descriptor. Even one Signer failing to check for its membership means that the setup could be compromised.
For the third type of attack, the descriptor checksum and visual inspection of the descriptor itself are the only way to guard against malicious members from being inserted into the set.
==Acknowledgement==
Special thanks to Dmitry Petukhov, Christopher Allen, Craig Raw and others for their feedback on the specification.
==References==
Original mailing list thread: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-February/018385.html
Hi all,
Hugo and I have discussed off-list, and I have two concerns with this proposal:
1. I believe adding the TOKEN and encryption to the exchange adds complexity to already notoriously complex multisig, without adding much in the way of security. This is because the shared secret (TOKEN) must still be shared securely, and if you have established an (off-protocol) secure channel to do this, why not just share the actual multisig configuration data directly in that channel? If you are able to do so, you retain the advantage of being able to inspect the data directly.
2. Asking the user to enter the derivation into the Signer also adds (IMO unnecessary) complexity to the multisig setup process. A different way of doing it, which is specified in the UR crypto-account format linked to previously, has the Signer provide as many common derivations (along with their xpubs) as it can support for a given BIP44 account number. This has the dual advantage of making things simpler for the user (they only have to provide an optional account number) and increasing the standardisation on common derivation paths. On receiving these derivation/xpub pairs, the Coordinator can simply pick the appropriate one.
These concerns noted, I agree it's a good idea to have Signers save the multisig configuration as proposed, and it would be great to have standardisation in hww import and export formats (not just for multisig). On that note, I'd love to see greater adoption of the efficient UR2.0 standard and associated formats for airgapped data transmission using QR codes.
Craig
On Mon, Feb 15, 2021 at 11:13 AM Hugo Nguyen via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (302 lines)
> Hi all, > I have updated the proposal based on further feedback. The new spec is > included at the bottom. > > I have also created a public Github PR to make it easier to comment on the > text of the spec itself: https://github.com/nunchuk-io/bips/pull/1 . > > Could someone please let me know what else needs to be done before a BIP > number can be assigned? > > > === Quick summary of changes from last update === > > 1. Define encryption modes > > # NO_ENCRYPTION: Encryption is disabled. > # STANDARD : the TOKEN is a 64-bit nonce. > # EXTENDED : the TOKEN is a 128-bit nonce. > > 2. Define signature algorithm > > Follow BIP-0322, legacy format allowed. > > 3. Multiple TOKENs (optional) > > Also add an option where the Coordinator can choose to use one common > TOKEN for all Signers, or use one per Signer. > > === End of summary === > > > Cheers, > Hugo > > > <pre> > BIP: To be determined > Layer: Applications > Title: Bitcoin Secure Multisig Setup (BSMS) > Author: Hugo Nguyen <hugo at nunchuk.io>, Peter Gray <peter at > coinkite.com>, Marko Bencun <marko at shiftcrypto.ch>, Pavol Rusnak < > stick@satoshilabs•com>, Aaron Chen <aarondongchen at gmail.com>, Rodolfo > Novak <rodolfo at coinkite.com> > Comments-Summary: No comments yet. > Comments-URI: > Status: Proposed > Type: Standards Track > Created: 2020-11-10 > License: BSD-2-Clause > </pre> > > ==Introduction== > > ===Abstract=== > > This document proposes a mechanism to set up multisig wallets securely. > > ===Copyright=== > > This BIP is licensed under the 2-clause BSD license. > > ===Motivation=== > > The Bitcoin multisig experience has been greatly streamlined under [ > https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki BIP-0174 > (Partially Signed Bitcoin Transaction)]. However, what is still missing is > a standardized process for setting up multisig wallets securely across > different vendors. > > There are a number of concerns when it comes to setting up a multisig > wallet: > > # Whether the multisig configuration, such as Signer membership, script > type, derivation paths and number of signatures required, is correct and > not tampered with. > # Whether Signer persists the multisig configuration in their respective > storage, and under what format. > # Whether Signer's storage is tamper-proof. > # Whether Signer subsequently uses the multisig configuration to generate > and verify receive and change addresses. > > An attacker who can modify the multisig configuration can steal or hold > funds to ransom by duping the user into sending funds to the wrong address. > > This proposal seeks to address concerns #1 and #2: to mitigate the risk of > tampering during the initial setup phase, and to define an interoperable > multisig configuration format. > > Concerns #3 and #4 should be handled by Signers and is out of scope of > this proposal. > > ==Specification== > > ===Prerequisites=== > This proposal assumes the parties in the multisig support [ > https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP-0032], > [https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the > descriptor language] and encryption. > > ===Roles=== > ====Coordinator==== > > The Coordinator initiates the multisig setup. The Coordinator determines > what type of multisig is used and the exact policy script. If encryption is > enabled, the Coordinator also distributes a shared secret or shared secrets > to the parties involved for secure communication. The Coordinator gathers > information from the Signers to generate a descriptor record. The > Coordinator distributes the descriptor record back to the Signers. > > ====Signer==== > > The Signer is a participating member in the multisig. Its responsibilities > include providing its key record -- which contains an Extended Public Key > (XPUB) -- to the Coordinator, verifying that its XPUB is included in the > descriptor record and persisting the descriptor record in its storage. > > ===Setup Process=== > > ====Round 1==== > > =====Coordinator===== > > * The Coordinator creates a multisig wallet creation session. The > Coordinator constructs the multisig script and its policy parameters, such > as the total number of signers and the required number of signatures > (<tt>M</tt> and <tt>N</tt>). > * The session should expire after some time period determined by the > Coordinator, e.g., 24 hours. > * If encryption is enabled, the Coordinator distributes a secret > <tt>TOKEN</tt> to each Signer over a secure channel. The Signer can use the > <tt>TOKEN</tt> to derive an <tt>ENCRYPTION_KEY</tt>. Refer to the > Encryption section below for details on the <tt>TOKEN</tt>, the key > derivation function and the encryption scheme. Depending on the use case, > the Coordinator can decide whether to share one common <tt>TOKEN</tt> for > all Signers, or to have one per Signer. > * If encryption is disabled, <tt>TOKEN</tt> is set to <tt>0</tt>, and all > the encryption/decryption steps below can be skipped. > > =====Signer===== > > * The Signer initiates a new secure multisig setup session by setting the > <tt>TOKEN</tt>. The Signer derives an <tt>ENCRYPTION_KEY</tt> from the > <tt>TOKEN</tt>. The Signer can keep the session open until a different > value for the <tt>TOKEN</tt> is set. > * The Signer generates a key record by prompting the user for a multisig > derivation path and retrieves the XPUB at that derivation path. Optionally, > the Signer can choose a path on behalf of the user. If the Signer chooses > the path, it should try to avoid reusing XPUBs for different wallets. > * The first line in the record must be the <tt>TOKEN</tt>. The second line > must be the <tt>KEY</tt>. The <tt>KEY</tt> is an XPUB plus its key origin > information, written in the descriptor-defined format, i.e.: <tt>[{master > key fingerprint}/{derivation path}]{XPUB}</tt>. The third line must be a > <tt>SIG</tt>, whereas <tt>SIG</tt> is the signature generated by using the > private key associated with the XPUB to sign the first two lines. The > signature should follow [ > https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki BIP-0322], > legacy format accepted. Finally, the Signer encrypts the entire record with > <tt>ENCRYPTION_KEY</tt>. > > ====Round 2==== > > =====Coordinator===== > > * The Coordinator gathers key records from all participating Signers. > Abort the setup if the wallet setup session has expired. > * For each key record, the Coordinator decrypts it using > <tt>ENCRYPTION_KEY</tt>. The Coordinator verifies that the included > <tt>SIG</tt> is valid given the <tt>KEY</tt>. > * If all key records look good, the Coordinator fills in all necessary > information to generate a descriptor record, which is simply the descriptor > string plus a <tt>CHECKSUM</tt>, all in one line. The <tt>CHECKSUM</tt> has > [ > https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums > BECH32 encoding]. > * The Coordinator encrypts this descriptor record with > <tt>ENCRYPTION_KEY</tt>. > * The Coordinator sends the encrypted descriptor record to all > participating Signers. > > =====Signer===== > > * The Signer imports the descriptor record, decrypts it using the > <tt>ENCRYPTION_KEY</tt> derived from the open session. > * The Signer calculates and verifies the descriptor’s <tt>CHECKSUM</tt>. > Abort the setup if the <tt>CHECKSUM</tt> is incorrect. > * The Signer checks whether one of the <tt>KEY</tt>s in the descriptor > belongs to it, using path and fingerprint information included in the > descriptor. The check must perform an exact match on the <tt>KEY</tt>s, and > not using shortcuts such as matching fingerprints (which is trivial to > spoof). Abort the setup if it doesn’t detect its own <tt>KEY</tt>. > * For confirmation, the Signer must display to the user the > <tt>CHECKSUM</tt>, plus other configurations, such as <tt>M</tt> and > <tt>N</tt>. The total number of Signers, <tt>N</tt>, is important to > prevent a <tt>KEY</tt> insertion attack. All participating Signers should > be able to display the same confirmation. > * If all checks pass, the Signer persists the descriptor record in its > storage. > * The Signer can choose to further restrict post-XPUB derivation paths, > such as to those defined in [ > https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki BIP-0044]. > * The Signer should subsequently use the descriptor to generate and verify > receive and change addresses. > > This completes the setup. > > ===Encryption=== > > ====The Token==== > We define three modes of encryption. > > # <tt>NO_ENCRYPTION</tt> : the <tt>TOKEN</tt> is set to <tt>0</tt>. > Encryption is disabled. > # <tt>STANDARD</tt> : the <tt>TOKEN</tt> is a 64-bit nonce. > # <tt>EXTENDED</tt> : the <tt>TOKEN</tt> is a 128-bit nonce. > > The <tt>TOKEN</tt> can be converted to one of these formats: > * A mnemonic phrase using [ > https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki BIP-0039] > word list (6 words in <tt>STANDARD</tt> mode, 12 words in <tt>EXTENDED</tt> > mode) > * A decimal number (20 digits in <tt>STANDARD</tt> mode, 40 digits in > <tt>EXTENDED</tt> mode) > * A QR code > * Other formats > > The flexibility in the data format allows each Signer to customize the > User Experience based on its respective capabilities. > > ====Key Derivation==== > The key derivation function is [https://tools.ietf.org/html/rfc2898 > PBKDF2], with PRF = SHA512. Specifically: > > <tt>DK = PBKDF2(PRF, Password, Salt, c, dkLen)</tt> > > Whereas: > > * PRF = <tt>SHA512</tt> > * Password = <tt>"No SPOF"</tt> > * Salt = <tt>TOKEN</tt> > * c = <tt>2048</tt> > * dkLen = <tt>256</tt> > * DK = Derived <tt>ENCRYPTION_KEY</tt> > > ====Encryption Scheme==== > The encryption scheme is [https://tools.ietf.org/html/rfc3686 AES, CTR > mode]. > > ==QR Codes== > For signers that use QR codes to transmit data, key and descriptor records > can be converted to QR codes, following [ > https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md > the BCR standard]. > > Also refer to [ > https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-015-account.md > UR Type Definition for BIP44 Accounts] and [ > https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-010-output-desc.md > UR Type Definition for Bitcoin Output Descriptors] for more details. > > ==Security== > > This proposal introduces two layers of protection. The first one is a > temporary, secret token, used to encrypt the two rounds of communication > between the Signer and the Coordinator. The second one is through the > descriptor checksum and visual inspection of the descriptor itself. > > The token is only needed during the setup phase, and can be safely thrown > away afterwards. The token does not guarantee that the Signer membership > set is not modified, since that depends on the overall security of all > parties in the setup, but it can make it significantly harder for an > attacker to do so. > > There are three ways an attacker can modify the membership set: by > changing an existing member, by removing an existing member, or by adding a > new member. > > For the first two methods, one of the Signers will be able to detect that > its membership has been changed or removed, and reject the final > descriptor. Thus, it is vital that all participating Signers check that > their membership is intact in the descriptor. Even one Signer failing to > check for its membership means that the setup could be compromised. > > For the third type of attack, the descriptor checksum and visual > inspection of the descriptor itself are the only way to guard against > malicious members from being inserted into the set. > > ==Acknowledgement== > > Special thanks to Dmitry Petukhov, Christopher Allen, Craig Raw and others > for their feedback on the specification. > > ==References== > > Original mailing list thread: > https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-February/018385.html > > > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists•linuxfoundation•org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >
Hi Craig, Thanks for the feedback! Sharing my comments inline.
On Mon, Feb 15, 2021 at 5:53 AM Craig Raw <craigraw@gmail•com> wrote:
Quoted text (9 lines)
> Hi all, > > Hugo and I have discussed off-list, and I have two concerns with this > proposal: > > 1. I believe adding the TOKEN and encryption to the exchange adds > complexity to already notoriously complex multisig, without adding much in > the way of security. >
I disagree that this doesn't add security. This proposal was inspired by a real vulnerability we discovered in the wild while experimenting with HWWs, and during that process I noticed that there is little in the way of a an attacker to pull off a MITM attack, where he/she can intercept and tamper with the multisig configuration file, potentially swapping in their own XPUBs. This is especially important for remote multisig setups - which is not common now but I imagine will be a lot more common in the future.
This is because the shared secret (TOKEN) must still be shared securely,
Quoted text (3 lines)
> and if you have established an (off-protocol) secure channel to do this, > why not just share the actual multisig configuration data directly in that > channel?
Because multisig is inherently an interactive process. If we can create the multisig configuration in one shot for everybody, you're correct that this is not necessary! But the fact that multisig is by nature interactive and requires a few rounds of communication (since it needs each Signer to voluntarily share its XPUB before a wallet can be created) makes this necessary IMO.
If you are able to do so, you retain the advantage of being able to inspect
Quoted text (1 line)
> the data directly.
Note that some manual inspection is still part of the proposal. But instead of exclusively relying on manual inspection (which is error-prone, and also doesn't scale very well for a large number of signers), we strengthen this process by automating some of the checks and making it harder to tamper with.
Quoted text (11 lines)
> > 2. Asking the user to enter the derivation into the Signer also adds (IMO > unnecessary) complexity to the multisig setup process. A different way of > doing it, which is specified in the UR crypto-account format linked to > previously, has the Signer provide as many common derivations (along with > their xpubs) as it can support for a given BIP44 account number. This has > the dual advantage of making things simpler for the user (they only have to > provide an optional account number) and increasing the standardisation on > common derivation paths. On receiving these derivation/xpub pairs, the > Coordinator can simply pick the appropriate one. >
Note that in the updated proposal, I added the option of the Signer automatically filling in the derivation paths on behalf of the user (and also should take care not to reuse XPUBs). Perhaps this can be made the default behavior.
Best, Hugo
Quoted text (319 lines)
> > These concerns noted, I agree it's a good idea to have Signers save the > multisig configuration as proposed, and it would be great to have > standardisation in hww import and export formats (not just for multisig). > On that note, I'd love to see greater adoption of the efficient UR2.0 > standard and associated formats for airgapped data transmission using QR > codes. > > Craig > > > On Mon, Feb 15, 2021 at 11:13 AM Hugo Nguyen via bitcoin-dev < > bitcoin-dev@lists•linuxfoundation•org> wrote: > >> Hi all, >> I have updated the proposal based on further feedback. The new spec is >> included at the bottom. >> >> I have also created a public Github PR to make it easier to comment on >> the text of the spec itself: https://github.com/nunchuk-io/bips/pull/1 . >> >> Could someone please let me know what else needs to be done before a BIP >> number can be assigned? >> >> >> === Quick summary of changes from last update === >> >> 1. Define encryption modes >> >> # NO_ENCRYPTION: Encryption is disabled. >> # STANDARD : the TOKEN is a 64-bit nonce. >> # EXTENDED : the TOKEN is a 128-bit nonce. >> >> 2. Define signature algorithm >> >> Follow BIP-0322, legacy format allowed. >> >> 3. Multiple TOKENs (optional) >> >> Also add an option where the Coordinator can choose to use one common >> TOKEN for all Signers, or use one per Signer. >> >> === End of summary === >> >> >> Cheers, >> Hugo >> >> >> <pre> >> BIP: To be determined >> Layer: Applications >> Title: Bitcoin Secure Multisig Setup (BSMS) >> Author: Hugo Nguyen <hugo at nunchuk.io>, Peter Gray <peter at >> coinkite.com>, Marko Bencun <marko at shiftcrypto.ch>, Pavol Rusnak < >> stick@satoshilabs•com>, Aaron Chen <aarondongchen at gmail.com>, Rodolfo >> Novak <rodolfo at coinkite.com> >> Comments-Summary: No comments yet. >> Comments-URI: >> Status: Proposed >> Type: Standards Track >> Created: 2020-11-10 >> License: BSD-2-Clause >> </pre> >> >> ==Introduction== >> >> ===Abstract=== >> >> This document proposes a mechanism to set up multisig wallets securely. >> >> ===Copyright=== >> >> This BIP is licensed under the 2-clause BSD license. >> >> ===Motivation=== >> >> The Bitcoin multisig experience has been greatly streamlined under [ >> https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki BIP-0174 >> (Partially Signed Bitcoin Transaction)]. However, what is still missing >> is a standardized process for setting up multisig wallets securely across >> different vendors. >> >> There are a number of concerns when it comes to setting up a multisig >> wallet: >> >> # Whether the multisig configuration, such as Signer membership, script >> type, derivation paths and number of signatures required, is correct and >> not tampered with. >> # Whether Signer persists the multisig configuration in their respective >> storage, and under what format. >> # Whether Signer's storage is tamper-proof. >> # Whether Signer subsequently uses the multisig configuration to generate >> and verify receive and change addresses. >> >> An attacker who can modify the multisig configuration can steal or hold >> funds to ransom by duping the user into sending funds to the wrong address. >> >> This proposal seeks to address concerns #1 and #2: to mitigate the risk >> of tampering during the initial setup phase, and to define an interoperable >> multisig configuration format. >> >> Concerns #3 and #4 should be handled by Signers and is out of scope of >> this proposal. >> >> ==Specification== >> >> ===Prerequisites=== >> This proposal assumes the parties in the multisig support [ >> https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki >> BIP-0032], [ >> https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the >> descriptor language] and encryption. >> >> ===Roles=== >> ====Coordinator==== >> >> The Coordinator initiates the multisig setup. The Coordinator determines >> what type of multisig is used and the exact policy script. If encryption is >> enabled, the Coordinator also distributes a shared secret or shared secrets >> to the parties involved for secure communication. The Coordinator gathers >> information from the Signers to generate a descriptor record. The >> Coordinator distributes the descriptor record back to the Signers. >> >> ====Signer==== >> >> The Signer is a participating member in the multisig. Its >> responsibilities include providing its key record -- which contains an >> Extended Public Key (XPUB) -- to the Coordinator, verifying that its XPUB >> is included in the descriptor record and persisting the descriptor record >> in its storage. >> >> ===Setup Process=== >> >> ====Round 1==== >> >> =====Coordinator===== >> >> * The Coordinator creates a multisig wallet creation session. The >> Coordinator constructs the multisig script and its policy parameters, such >> as the total number of signers and the required number of signatures >> (<tt>M</tt> and <tt>N</tt>). >> * The session should expire after some time period determined by the >> Coordinator, e.g., 24 hours. >> * If encryption is enabled, the Coordinator distributes a secret >> <tt>TOKEN</tt> to each Signer over a secure channel. The Signer can use the >> <tt>TOKEN</tt> to derive an <tt>ENCRYPTION_KEY</tt>. Refer to the >> Encryption section below for details on the <tt>TOKEN</tt>, the key >> derivation function and the encryption scheme. Depending on the use case, >> the Coordinator can decide whether to share one common <tt>TOKEN</tt> for >> all Signers, or to have one per Signer. >> * If encryption is disabled, <tt>TOKEN</tt> is set to <tt>0</tt>, and all >> the encryption/decryption steps below can be skipped. >> >> =====Signer===== >> >> * The Signer initiates a new secure multisig setup session by setting the >> <tt>TOKEN</tt>. The Signer derives an <tt>ENCRYPTION_KEY</tt> from the >> <tt>TOKEN</tt>. The Signer can keep the session open until a different >> value for the <tt>TOKEN</tt> is set. >> * The Signer generates a key record by prompting the user for a multisig >> derivation path and retrieves the XPUB at that derivation path. Optionally, >> the Signer can choose a path on behalf of the user. If the Signer chooses >> the path, it should try to avoid reusing XPUBs for different wallets. >> * The first line in the record must be the <tt>TOKEN</tt>. The second >> line must be the <tt>KEY</tt>. The <tt>KEY</tt> is an XPUB plus its key >> origin information, written in the descriptor-defined format, i.e.: >> <tt>[{master key fingerprint}/{derivation path}]{XPUB}</tt>. The third line >> must be a <tt>SIG</tt>, whereas <tt>SIG</tt> is the signature generated by >> using the private key associated with the XPUB to sign the first two >> lines. The signature should follow [ >> https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki >> BIP-0322], legacy format accepted. Finally, the Signer encrypts the entire >> record with <tt>ENCRYPTION_KEY</tt>. >> >> ====Round 2==== >> >> =====Coordinator===== >> >> * The Coordinator gathers key records from all participating Signers. >> Abort the setup if the wallet setup session has expired. >> * For each key record, the Coordinator decrypts it using >> <tt>ENCRYPTION_KEY</tt>. The Coordinator verifies that the included >> <tt>SIG</tt> is valid given the <tt>KEY</tt>. >> * If all key records look good, the Coordinator fills in all necessary >> information to generate a descriptor record, which is simply the descriptor >> string plus a <tt>CHECKSUM</tt>, all in one line. The <tt>CHECKSUM</tt> has >> [ >> https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums >> BECH32 encoding]. >> * The Coordinator encrypts this descriptor record with >> <tt>ENCRYPTION_KEY</tt>. >> * The Coordinator sends the encrypted descriptor record to all >> participating Signers. >> >> =====Signer===== >> >> * The Signer imports the descriptor record, decrypts it using the >> <tt>ENCRYPTION_KEY</tt> derived from the open session. >> * The Signer calculates and verifies the descriptor’s <tt>CHECKSUM</tt>. >> Abort the setup if the <tt>CHECKSUM</tt> is incorrect. >> * The Signer checks whether one of the <tt>KEY</tt>s in the descriptor >> belongs to it, using path and fingerprint information included in the >> descriptor. The check must perform an exact match on the <tt>KEY</tt>s, and >> not using shortcuts such as matching fingerprints (which is trivial to >> spoof). Abort the setup if it doesn’t detect its own <tt>KEY</tt>. >> * For confirmation, the Signer must display to the user the >> <tt>CHECKSUM</tt>, plus other configurations, such as <tt>M</tt> and >> <tt>N</tt>. The total number of Signers, <tt>N</tt>, is important to >> prevent a <tt>KEY</tt> insertion attack. All participating Signers should >> be able to display the same confirmation. >> * If all checks pass, the Signer persists the descriptor record in its >> storage. >> * The Signer can choose to further restrict post-XPUB derivation paths, >> such as to those defined in [ >> https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki BIP-0044]. >> * The Signer should subsequently use the descriptor to generate and >> verify receive and change addresses. >> >> This completes the setup. >> >> ===Encryption=== >> >> ====The Token==== >> We define three modes of encryption. >> >> # <tt>NO_ENCRYPTION</tt> : the <tt>TOKEN</tt> is set to <tt>0</tt>. >> Encryption is disabled. >> # <tt>STANDARD</tt> : the <tt>TOKEN</tt> is a 64-bit nonce. >> # <tt>EXTENDED</tt> : the <tt>TOKEN</tt> is a 128-bit nonce. >> >> The <tt>TOKEN</tt> can be converted to one of these formats: >> * A mnemonic phrase using [ >> https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki BIP-0039] >> word list (6 words in <tt>STANDARD</tt> mode, 12 words in <tt>EXTENDED</tt> >> mode) >> * A decimal number (20 digits in <tt>STANDARD</tt> mode, 40 digits in >> <tt>EXTENDED</tt> mode) >> * A QR code >> * Other formats >> >> The flexibility in the data format allows each Signer to customize the >> User Experience based on its respective capabilities. >> >> ====Key Derivation==== >> The key derivation function is [https://tools.ietf.org/html/rfc2898 >> PBKDF2], with PRF = SHA512. Specifically: >> >> <tt>DK = PBKDF2(PRF, Password, Salt, c, dkLen)</tt> >> >> Whereas: >> >> * PRF = <tt>SHA512</tt> >> * Password = <tt>"No SPOF"</tt> >> * Salt = <tt>TOKEN</tt> >> * c = <tt>2048</tt> >> * dkLen = <tt>256</tt> >> * DK = Derived <tt>ENCRYPTION_KEY</tt> >> >> ====Encryption Scheme==== >> The encryption scheme is [https://tools.ietf.org/html/rfc3686 AES, CTR >> mode]. >> >> ==QR Codes== >> For signers that use QR codes to transmit data, key and descriptor >> records can be converted to QR codes, following [ >> https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md >> the BCR standard]. >> >> Also refer to [ >> https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-015-account.md >> UR Type Definition for BIP44 Accounts] and [ >> https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-010-output-desc.md >> UR Type Definition for Bitcoin Output Descriptors] for more details. >> >> ==Security== >> >> This proposal introduces two layers of protection. The first one is a >> temporary, secret token, used to encrypt the two rounds of communication >> between the Signer and the Coordinator. The second one is through the >> descriptor checksum and visual inspection of the descriptor itself. >> >> The token is only needed during the setup phase, and can be safely thrown >> away afterwards. The token does not guarantee that the Signer membership >> set is not modified, since that depends on the overall security of all >> parties in the setup, but it can make it significantly harder for an >> attacker to do so. >> >> There are three ways an attacker can modify the membership set: by >> changing an existing member, by removing an existing member, or by adding a >> new member. >> >> For the first two methods, one of the Signers will be able to detect that >> its membership has been changed or removed, and reject the final >> descriptor. Thus, it is vital that all participating Signers check that >> their membership is intact in the descriptor. Even one Signer failing to >> check for its membership means that the setup could be compromised. >> >> For the third type of attack, the descriptor checksum and visual >> inspection of the descriptor itself are the only way to guard against >> malicious members from being inserted into the set. >> >> ==Acknowledgement== >> >> Special thanks to Dmitry Petukhov, Christopher Allen, Craig Raw and >> others for their feedback on the specification. >> >> ==References== >> >> Original mailing list thread: >> https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-February/018385.html >> >> >> _______________________________________________ >> bitcoin-dev mailing list >> bitcoin-dev@lists•linuxfoundation•org >> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >> >
I would also like to add 2 notes for those who are concerned about the potential complexity that comes with encryption - which is understandable:
1. As mentioned elsewhere in the thread, I've made the encryption aspect entirely optional. In scenarios where encryption is an overkill -- such as when you're setting things up under an environment you control 100% -- you can turn encryption off, and things are unchanged from the way they are now. The "session" would be unencrypted and XPUBs and descriptor records are simply shared in plaintext.
2. Multisig setup is a one-time operation! After the multisig wallet has been set up and registered with the Signers, you don't have to worry about sharing XPUBs ever again (not even in PSBTs which is an additional benefit of the stateful registration approach). I believe this one-time cost is worth it if the amount of funds you are securing are significant, e.g., few millions of dollars or even billions of dollars. But it's important that we have this extra level of security if necessary IMHO.
Best, Hugo
On Mon, Feb 15, 2021 at 6:19 AM Hugo Nguyen <hugo@nunchuk•io> wrote:
Quoted text (388 lines)
> Hi Craig, > Thanks for the feedback! Sharing my comments inline. > > On Mon, Feb 15, 2021 at 5:53 AM Craig Raw <craigraw@gmail•com> wrote: > >> Hi all, >> >> Hugo and I have discussed off-list, and I have two concerns with this >> proposal: >> >> 1. I believe adding the TOKEN and encryption to the exchange adds >> complexity to already notoriously complex multisig, without adding much in >> the way of security. >> > > I disagree that this doesn't add security. This proposal was inspired by a > real vulnerability we discovered in the wild while experimenting with HWWs, > and during that process I noticed that there is little in the way of a an > attacker to pull off a MITM attack, where he/she can intercept and tamper > with the multisig configuration file, potentially swapping in their own > XPUBs. This is especially important for remote multisig setups - which is > not common now but I imagine will be a lot more common in the future. > > This is because the shared secret (TOKEN) must still be shared securely, >> and if you have established an (off-protocol) secure channel to do this, >> why not just share the actual multisig configuration data directly in that >> channel? > > > Because multisig is inherently an interactive process. If we can create > the multisig configuration in one shot for everybody, you're correct that > this is not necessary! But the fact that multisig is by nature interactive > and requires a few rounds of communication (since it needs each Signer to > voluntarily share its XPUB before a wallet can be created) makes this > necessary IMO. > > If you are able to do so, you retain the advantage of being able to >> inspect the data directly. > > > Note that some manual inspection is still part of the proposal. But > instead of exclusively relying on manual inspection (which is error-prone, > and also doesn't scale very well for a large number of signers), we > strengthen this process by automating some of the checks and making it > harder to tamper with. > > >> >> 2. Asking the user to enter the derivation into the Signer also adds (IMO >> unnecessary) complexity to the multisig setup process. A different way of >> doing it, which is specified in the UR crypto-account format linked to >> previously, has the Signer provide as many common derivations (along with >> their xpubs) as it can support for a given BIP44 account number. This has >> the dual advantage of making things simpler for the user (they only have to >> provide an optional account number) and increasing the standardisation on >> common derivation paths. On receiving these derivation/xpub pairs, the >> Coordinator can simply pick the appropriate one. >> > > Note that in the updated proposal, I added the option of the Signer > automatically filling in the derivation paths on behalf of the user (and > also should take care not to reuse XPUBs). Perhaps this can be made the > default behavior. > > Best, > Hugo > > >> >> These concerns noted, I agree it's a good idea to have Signers save the >> multisig configuration as proposed, and it would be great to have >> standardisation in hww import and export formats (not just for multisig). >> On that note, I'd love to see greater adoption of the efficient UR2.0 >> standard and associated formats for airgapped data transmission using QR >> codes. >> >> Craig >> >> >> On Mon, Feb 15, 2021 at 11:13 AM Hugo Nguyen via bitcoin-dev < >> bitcoin-dev@lists•linuxfoundation•org> wrote: >> >>> Hi all, >>> I have updated the proposal based on further feedback. The new spec is >>> included at the bottom. >>> >>> I have also created a public Github PR to make it easier to comment on >>> the text of the spec itself: https://github.com/nunchuk-io/bips/pull/1 . >>> >>> Could someone please let me know what else needs to be done before a BIP >>> number can be assigned? >>> >>> >>> === Quick summary of changes from last update === >>> >>> 1. Define encryption modes >>> >>> # NO_ENCRYPTION: Encryption is disabled. >>> # STANDARD : the TOKEN is a 64-bit nonce. >>> # EXTENDED : the TOKEN is a 128-bit nonce. >>> >>> 2. Define signature algorithm >>> >>> Follow BIP-0322, legacy format allowed. >>> >>> 3. Multiple TOKENs (optional) >>> >>> Also add an option where the Coordinator can choose to use one common >>> TOKEN for all Signers, or use one per Signer. >>> >>> === End of summary === >>> >>> >>> Cheers, >>> Hugo >>> >>> >>> <pre> >>> BIP: To be determined >>> Layer: Applications >>> Title: Bitcoin Secure Multisig Setup (BSMS) >>> Author: Hugo Nguyen <hugo at nunchuk.io>, Peter Gray <peter at >>> coinkite.com>, Marko Bencun <marko at shiftcrypto.ch>, Pavol Rusnak < >>> stick@satoshilabs•com>, Aaron Chen <aarondongchen at gmail.com>, >>> Rodolfo Novak <rodolfo at coinkite.com> >>> Comments-Summary: No comments yet. >>> Comments-URI: >>> Status: Proposed >>> Type: Standards Track >>> Created: 2020-11-10 >>> License: BSD-2-Clause >>> </pre> >>> >>> ==Introduction== >>> >>> ===Abstract=== >>> >>> This document proposes a mechanism to set up multisig wallets securely. >>> >>> ===Copyright=== >>> >>> This BIP is licensed under the 2-clause BSD license. >>> >>> ===Motivation=== >>> >>> The Bitcoin multisig experience has been greatly streamlined under [ >>> https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki BIP-0174 >>> (Partially Signed Bitcoin Transaction)]. However, what is still missing >>> is a standardized process for setting up multisig wallets securely across >>> different vendors. >>> >>> There are a number of concerns when it comes to setting up a multisig >>> wallet: >>> >>> # Whether the multisig configuration, such as Signer membership, script >>> type, derivation paths and number of signatures required, is correct and >>> not tampered with. >>> # Whether Signer persists the multisig configuration in their respective >>> storage, and under what format. >>> # Whether Signer's storage is tamper-proof. >>> # Whether Signer subsequently uses the multisig configuration to >>> generate and verify receive and change addresses. >>> >>> An attacker who can modify the multisig configuration can steal or hold >>> funds to ransom by duping the user into sending funds to the wrong address. >>> >>> This proposal seeks to address concerns #1 and #2: to mitigate the risk >>> of tampering during the initial setup phase, and to define an interoperable >>> multisig configuration format. >>> >>> Concerns #3 and #4 should be handled by Signers and is out of scope of >>> this proposal. >>> >>> ==Specification== >>> >>> ===Prerequisites=== >>> This proposal assumes the parties in the multisig support [ >>> https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki >>> BIP-0032], [ >>> https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the >>> descriptor language] and encryption. >>> >>> ===Roles=== >>> ====Coordinator==== >>> >>> The Coordinator initiates the multisig setup. The Coordinator determines >>> what type of multisig is used and the exact policy script. If encryption is >>> enabled, the Coordinator also distributes a shared secret or shared secrets >>> to the parties involved for secure communication. The Coordinator gathers >>> information from the Signers to generate a descriptor record. The >>> Coordinator distributes the descriptor record back to the Signers. >>> >>> ====Signer==== >>> >>> The Signer is a participating member in the multisig. Its >>> responsibilities include providing its key record -- which contains an >>> Extended Public Key (XPUB) -- to the Coordinator, verifying that its XPUB >>> is included in the descriptor record and persisting the descriptor record >>> in its storage. >>> >>> ===Setup Process=== >>> >>> ====Round 1==== >>> >>> =====Coordinator===== >>> >>> * The Coordinator creates a multisig wallet creation session. The >>> Coordinator constructs the multisig script and its policy parameters, such >>> as the total number of signers and the required number of signatures >>> (<tt>M</tt> and <tt>N</tt>). >>> * The session should expire after some time period determined by the >>> Coordinator, e.g., 24 hours. >>> * If encryption is enabled, the Coordinator distributes a secret >>> <tt>TOKEN</tt> to each Signer over a secure channel. The Signer can use the >>> <tt>TOKEN</tt> to derive an <tt>ENCRYPTION_KEY</tt>. Refer to the >>> Encryption section below for details on the <tt>TOKEN</tt>, the key >>> derivation function and the encryption scheme. Depending on the use case, >>> the Coordinator can decide whether to share one common <tt>TOKEN</tt> for >>> all Signers, or to have one per Signer. >>> * If encryption is disabled, <tt>TOKEN</tt> is set to <tt>0</tt>, and >>> all the encryption/decryption steps below can be skipped. >>> >>> =====Signer===== >>> >>> * The Signer initiates a new secure multisig setup session by setting >>> the <tt>TOKEN</tt>. The Signer derives an <tt>ENCRYPTION_KEY</tt> from the >>> <tt>TOKEN</tt>. The Signer can keep the session open until a different >>> value for the <tt>TOKEN</tt> is set. >>> * The Signer generates a key record by prompting the user for a multisig >>> derivation path and retrieves the XPUB at that derivation path. Optionally, >>> the Signer can choose a path on behalf of the user. If the Signer chooses >>> the path, it should try to avoid reusing XPUBs for different wallets. >>> * The first line in the record must be the <tt>TOKEN</tt>. The second >>> line must be the <tt>KEY</tt>. The <tt>KEY</tt> is an XPUB plus its key >>> origin information, written in the descriptor-defined format, i.e.: >>> <tt>[{master key fingerprint}/{derivation path}]{XPUB}</tt>. The third line >>> must be a <tt>SIG</tt>, whereas <tt>SIG</tt> is the signature generated by >>> using the private key associated with the XPUB to sign the first two >>> lines. The signature should follow [ >>> https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki >>> BIP-0322], legacy format accepted. Finally, the Signer encrypts the entire >>> record with <tt>ENCRYPTION_KEY</tt>. >>> >>> ====Round 2==== >>> >>> =====Coordinator===== >>> >>> * The Coordinator gathers key records from all participating Signers. >>> Abort the setup if the wallet setup session has expired. >>> * For each key record, the Coordinator decrypts it using >>> <tt>ENCRYPTION_KEY</tt>. The Coordinator verifies that the included >>> <tt>SIG</tt> is valid given the <tt>KEY</tt>. >>> * If all key records look good, the Coordinator fills in all necessary >>> information to generate a descriptor record, which is simply the descriptor >>> string plus a <tt>CHECKSUM</tt>, all in one line. The <tt>CHECKSUM</tt> has >>> [ >>> https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums >>> BECH32 encoding]. >>> * The Coordinator encrypts this descriptor record with >>> <tt>ENCRYPTION_KEY</tt>. >>> * The Coordinator sends the encrypted descriptor record to all >>> participating Signers. >>> >>> =====Signer===== >>> >>> * The Signer imports the descriptor record, decrypts it using the >>> <tt>ENCRYPTION_KEY</tt> derived from the open session. >>> * The Signer calculates and verifies the descriptor’s <tt>CHECKSUM</tt>. >>> Abort the setup if the <tt>CHECKSUM</tt> is incorrect. >>> * The Signer checks whether one of the <tt>KEY</tt>s in the descriptor >>> belongs to it, using path and fingerprint information included in the >>> descriptor. The check must perform an exact match on the <tt>KEY</tt>s, and >>> not using shortcuts such as matching fingerprints (which is trivial to >>> spoof). Abort the setup if it doesn’t detect its own <tt>KEY</tt>. >>> * For confirmation, the Signer must display to the user the >>> <tt>CHECKSUM</tt>, plus other configurations, such as <tt>M</tt> and >>> <tt>N</tt>. The total number of Signers, <tt>N</tt>, is important to >>> prevent a <tt>KEY</tt> insertion attack. All participating Signers should >>> be able to display the same confirmation. >>> * If all checks pass, the Signer persists the descriptor record in its >>> storage. >>> * The Signer can choose to further restrict post-XPUB derivation paths, >>> such as to those defined in [ >>> https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki >>> BIP-0044]. >>> * The Signer should subsequently use the descriptor to generate and >>> verify receive and change addresses. >>> >>> This completes the setup. >>> >>> ===Encryption=== >>> >>> ====The Token==== >>> We define three modes of encryption. >>> >>> # <tt>NO_ENCRYPTION</tt> : the <tt>TOKEN</tt> is set to <tt>0</tt>. >>> Encryption is disabled. >>> # <tt>STANDARD</tt> : the <tt>TOKEN</tt> is a 64-bit nonce. >>> # <tt>EXTENDED</tt> : the <tt>TOKEN</tt> is a 128-bit nonce. >>> >>> The <tt>TOKEN</tt> can be converted to one of these formats: >>> * A mnemonic phrase using [ >>> https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki >>> BIP-0039] word list (6 words in <tt>STANDARD</tt> mode, 12 words in >>> <tt>EXTENDED</tt> mode) >>> * A decimal number (20 digits in <tt>STANDARD</tt> mode, 40 digits in >>> <tt>EXTENDED</tt> mode) >>> * A QR code >>> * Other formats >>> >>> The flexibility in the data format allows each Signer to customize the >>> User Experience based on its respective capabilities. >>> >>> ====Key Derivation==== >>> The key derivation function is [https://tools.ietf.org/html/rfc2898 >>> PBKDF2], with PRF = SHA512. Specifically: >>> >>> <tt>DK = PBKDF2(PRF, Password, Salt, c, dkLen)</tt> >>> >>> Whereas: >>> >>> * PRF = <tt>SHA512</tt> >>> * Password = <tt>"No SPOF"</tt> >>> * Salt = <tt>TOKEN</tt> >>> * c = <tt>2048</tt> >>> * dkLen = <tt>256</tt> >>> * DK = Derived <tt>ENCRYPTION_KEY</tt> >>> >>> ====Encryption Scheme==== >>> The encryption scheme is [https://tools.ietf.org/html/rfc3686 AES, CTR >>> mode]. >>> >>> ==QR Codes== >>> For signers that use QR codes to transmit data, key and descriptor >>> records can be converted to QR codes, following [ >>> https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md >>> the BCR standard]. >>> >>> Also refer to [ >>> https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-015-account.md >>> UR Type Definition for BIP44 Accounts] and [ >>> https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-010-output-desc.md >>> UR Type Definition for Bitcoin Output Descriptors] for more details. >>> >>> ==Security== >>> >>> This proposal introduces two layers of protection. The first one is a >>> temporary, secret token, used to encrypt the two rounds of communication >>> between the Signer and the Coordinator. The second one is through the >>> descriptor checksum and visual inspection of the descriptor itself. >>> >>> The token is only needed during the setup phase, and can be safely >>> thrown away afterwards. The token does not guarantee that the Signer >>> membership set is not modified, since that depends on the overall security >>> of all parties in the setup, but it can make it significantly harder for an >>> attacker to do so. >>> >>> There are three ways an attacker can modify the membership set: by >>> changing an existing member, by removing an existing member, or by adding a >>> new member. >>> >>> For the first two methods, one of the Signers will be able to detect >>> that its membership has been changed or removed, and reject the final >>> descriptor. Thus, it is vital that all participating Signers check that >>> their membership is intact in the descriptor. Even one Signer failing to >>> check for its membership means that the setup could be compromised. >>> >>> For the third type of attack, the descriptor checksum and visual >>> inspection of the descriptor itself are the only way to guard against >>> malicious members from being inserted into the set. >>> >>> ==Acknowledgement== >>> >>> Special thanks to Dmitry Petukhov, Christopher Allen, Craig Raw and >>> others for their feedback on the specification. >>> >>> ==References== >>> >>> Original mailing list thread: >>> https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-February/018385.html >>> >>> >>> _______________________________________________ >>> bitcoin-dev mailing list >>> bitcoin-dev@lists•linuxfoundation•org >>> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >>> >>
Hi all,
Please find below the complete draft of the Bitcoin Secure Multisig Setup (BSMS) BIP. The spec has gone through a number of important updates in the last month or so. Thanks everyone who has participated in the review process.
As a PR: https://github.com/bitcoin/bips/pull/1097
A few notes: * PBKDF2-SHA512 was chosen instead of PBKDF2-SHA256 for the key derivation function, due to widespread existing hardware support for PBKDF2-SHA512 * Only one descriptor is stored in the multisig configuration - this simplifies wallet setup and recovery (For the full review and relevant discussions, please check out https://github.com/nunchuk-io/bips/pull/1).
Best, Hugo
<pre> BIP: To be determined Layer: Applications Title: Bitcoin Secure Multisig Setup (BSMS) Author: Hugo Nguyen <hugo at nunchuk.io>, Peter Gray <peter at coinkite.com>, Marko Bencun <marko at shiftcrypto.ch>, Aaron Chen <aarondongchen at gmail.com>, Rodolfo Novak <rodolfo at coinkite.com> Comments-Summary: No comments yet. Comments-URI: Status: Proposed Type: Standards Track Created: 2020-11-10 License: BSD-2-Clause </pre>
==Introduction==
===Abstract===
This document proposes a mechanism to set up multisig wallets securely.
===Copyright===
This BIP is licensed under the 2-clause BSD license.
===Motivation===
The Bitcoin multisig experience has been greatly streamlined under [https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki BIP-0174 (Partially Signed Bitcoin Transaction)]. However, what is still missing is a standardized process for setting up multisig wallets securely across different vendors.
There are a number of concerns when it comes to setting up a multisig wallet:
# Whether the multisig configuration, such as Signer membership, script type, derivation paths and number of signatures required, is correct and not tampered with. # Whether the keys or the multisig configuration are leaked during the setup. # Whether the Signer persists the multisig configuration in their respective storage, and under what format. # Whether the Signer's storage is tamper-proof. # Whether the Signer subsequently uses the multisig configuration to generate and verify receive and change addresses.
An attacker who can modify the multisig configuration can steal or hold funds for ransom by duping the user into sending funds to the wrong address. An attacker who cannot modify the configuration but can learn about the keys and/or the configuration can monitor transactions in the wallet, resulting in loss of privacy.
This proposal seeks to address concerns #1, #2 and #3: to mitigate the risk of tampering during the initial setup phase, and to define an interoperable multisig configuration format.
Concerns #4 and #5 should be handled by Signers and are out of scope of this proposal.
==Specification==
===Prerequisites=== This proposal assumes the parties in the multisig support [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP-0032], [https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki BIP-0322], [https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the descriptor language] and [https://tools.ietf.org/html/rfc3686 AES encryption].
===File Extension=== All descriptor and key records should have a <tt>.bsms</tt> file extension. Encrypted data should have a <tt>.dat</tt> extension.
===Roles=== ====Coordinator====
The Coordinator initiates the multisig setup. The Coordinator determines what type of multisig is used and the exact policy script. If encryption is enabled, the Coordinator also distributes a shared secret or shared secrets to the parties involved for secure communication. The Coordinator gathers information from the Signers to generate a descriptor record. The Coordinator distributes the descriptor record back to the Signers.
====Signer====
The Signer is a participating member in the multisig. Its responsibilities include providing its key record -- which contains an Extended Public Key (XPUB) -- to the Coordinator, verifying that its XPUB is included in the descriptor record and persisting the descriptor record in its storage.
===Setup Process===
====Round 1====
=====Coordinator=====
* The Coordinator creates a new multisig wallet creation session. The Coordinator constructs the multisig script and its policy parameters, such as the required number of signatures and the total number of Signers (<tt>M</tt> and <tt>N</tt>). * The session should expire after some time period determined by the Coordinator, e.g., 24 hours. The timeout allows the encryption key to have lower entropy. * If encryption is enabled, the Coordinator distributes a secret <tt>TOKEN</tt> to each Signer over a secure channel. The Signer can use the <tt>TOKEN</tt> to derive an <tt>ENCRYPTION_KEY</tt>. Refer to the Encryption section below for details on the <tt>TOKEN</tt>, the key derivation function and the encryption scheme. Depending on the use case, the Coordinator can decide whether to share one common <tt>TOKEN</tt> for all Signers, or to have one per Signer. * If encryption is disabled, the <tt>TOKEN</tt> is set to <tt>0</tt>, and all the encryption/decryption steps below can be skipped.
=====Signer=====
* The Signer initiates the multisig wallet creation session by setting
the <tt>TOKEN</tt>. The Signer derives an <tt>ENCRYPTION_KEY</tt> from
the <tt>TOKEN</tt>. The Signer can keep the session open until a
different value for the <tt>TOKEN</tt> is set.
* The Signer generates a key record by prompting the user for a
multisig derivation path and retrieves the XPUB at that derivation
path. Alternatively, the Signer can choose a path on behalf of the
user. If the Signer chooses the path, it should try to avoid reusing
XPUBs for different wallets.
* The first line in the record must be the specification version
(<tt>BSMS 1.0</tt> as of this writing). The second line must be the
hex-encoded <tt>TOKEN</tt>. The third line must be the <tt>KEY</tt>.
The <tt>KEY</tt> is an XPUB plus its key origin information, written
in the descriptor-defined format, i.e.: <tt>[{master key
fingerprint}/{derivation path}]{XPUB}</tt>. The fourth line is a text
description of the key, 80 characters maximum. The fifth line must be
a <tt>SIG</tt>, whereas <tt>SIG</tt> is the signature generated by
using the private key associated with the XPUB to sign the first four
lines. The signature should follow
[https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki
BIP-0322], legacy format accepted.
* The Signer calculates the Message Authentication Code (<tt>MAC</tt>)
for the record. The first 16 bytes of the <tt>MAC</tt> serves as the
Initialization Vector (<tt>IV</tt>) for the encryption.
* The Signer encrypts the key record with the <tt>ENCRYPTION_KEY</tt>
and <tt>IV</tt>.
* The Signer encodes the <tt>MAC</tt> and the ciphertext into
hexadecimal format, then concatenates the results: <tt>(MAC ||
ciphertext)</tt>.
====Round 2====
=====Coordinator=====
* The Coordinator gathers key records from all participating Signers. The Coordinator verifies that there are exactly <tt>N</tt> unique key records before the wallet setup session expires. * For each key record, the Coordinator extracts the <tt>MAC</tt> from the data, sets <tt>IV</tt> to the first 16 bytes of the <tt>MAC</tt>, then decrypts the ciphertext using the <tt>ENCRYPTION_KEY</tt> and <tt>IV</tt>. * The Coordinator verifies that the included <tt>MAC</tt> is valid given the plaintext. * The Coordinator verifies that the key records have compatible specification versions. * The Coordinator verifies that the included <tt>SIG</tt> is valid given the <tt>KEY</tt>. * If all key records look good, the Coordinator fills in all necessary information to generate a descriptor record. * The first line in the descriptor record must be the specification version (<tt>BSMS 1.0</tt> as of this writing). The second line must be a comma-separated list of accepted derivation paths that the Signers can use to generate addresses from the included XPUBs. The paths must start with <tt>/</tt> and use non-hardened derivation. For example, <tt>/0/*</tt> and <tt>/1/*</tt> are some common paths. If there are no restrictions, it must say <tt>No path restrictions</tt>. The third line must be the descriptor string plus a <tt>CHECKSUM</tt>, all in one line. The <tt>CHECKSUM</tt> has [https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums BECH32 encoding]. * The Coordinator calculates the <tt>MAC</tt> for the record. The first 16 bytes of the <tt>MAC</tt> serves as the <tt>IV</tt> for the encryption.. * The Coordinator encrypts the descriptor record with the <tt>ENCRYPTION_KEY</tt> and <tt>IV</tt>. * The Coordinator encodes the <tt>MAC</tt> and the ciphertext into hexadecimal format, then concatenates the results: <tt>(MAC || ciphertext)</tt>. * The Coordinator sends the encrypted descriptor record to all participating Signers.
=====Signer=====
* The Signer imports the descriptor record. * The Signer extracts the <tt>MAC</tt> from the data, sets <tt>IV</tt> to the first 16 bytes of the <tt>MAC</tt>, then decrypts the ciphertext using the <tt>ENCRYPTION_KEY</tt> (derived from the open session) and <tt>IV</tt>. * The Signer verifies that the included <tt>MAC</tt> is valid given the plaintext. * The Signer verifies that it can support the included specification version. * The Signer verifies that it is compatible with the derivation path restrictions. * The Signer verifies the descriptor’s <tt>CHECKSUM</tt>. * The Signer verifies that it can support the descriptor. * The Signer checks that its <tt>KEY</tt> is included in the descriptor, using path and fingerprint information provided. The check must perform an exact match on the <tt>KEY</tt>s and not using shortcuts such as matching fingerprints, which is trivial to spoof. * For confirmation, the Signer must display to the user the <tt>CHECKSUM</tt>, the derivation path restrictions and the policy parameters, such as <tt>M</tt>, <tt>N</tt> and the position(s) of its own XPUB in the policy script. The total number of Signers, <tt>N</tt>, is important to prevent a <tt>KEY</tt> insertion attack. The position is important for scripts where key order matters. When applicable, all positions of the XPUB must be displayed. The full descriptor must also be available for review upon user request. * When possible, the Signer should also show a preview of the first address(es) of the wallet. * Parties must check with each other that all Signers have verified the descriptor and has the same confirmation (except for the key positions). * If all checks pass, the Signer must persist the descriptor record in its storage.
This completes the setup.
===Encryption===
====The Token==== We define three modes of encryption.
# <tt>NO_ENCRYPTION</tt> : the <tt>TOKEN</tt> is set to <tt>0</tt>. Encryption is disabled. # <tt>STANDARD</tt> : the <tt>TOKEN</tt> is a 64-bit nonce. # <tt>EXTENDED</tt> : the <tt>TOKEN</tt> is a 96-bit nonce.
The <tt>TOKEN</tt> can be converted to one of these formats: * A decimal number (recommended). The number must not exceed the maximum value of the nonce. * A mnemonic phrase using [https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki BIP-0039] word list (6 words in <tt>STANDARD</tt> mode; 9 words in <tt>EXTENDED</tt> mode). * A QR code. * Other formats.
The flexibility in the data format allows each Signer to customize the User Experience based on its respective capabilities.
====Key Derivation==== The key derivation function is [https://tools.ietf.org/html/rfc2898 PBKDF2], with PRF = SHA512. Specifically:
<tt>DKey = PBKDF2(PRF, Password, Salt, c, dkLen)</tt>
Whereas:
* PRF = SHA512 * Password = "No SPOF" * Salt = <tt>TOKEN</tt> * c = 2048 * dkLen = 256 * DKey = Derived <tt>ENCRYPTION_KEY</tt>
====Encryption Scheme==== The encryption scheme is [https://tools.ietf.org/html/rfc3686 AES-256-CTR].
<tt>MAC = HMAC-SHA256(HMAC_Key, hex-encoded TOKEN || Data)</tt>
<tt>IV = First 16 bytes of MAC</tt>
<tt>Ciphertext = AES-256-CTR-Encrypt(Plaintext, DKey, IV)</tt>
<tt>Plaintext = AES-256-CTR-Decrypt(Ciphertext, DKey, IV)</tt>
Whereas: * DKey = <tt>ENCRYPTION_KEY</tt> * HMAC_Key = SHA256(<tt>ENCRYPTION_KEY</tt>) * Data = the plaintext, e.g. the entire key record in round 1 and the entire descriptor record in round 2
The <tt>MAC</tt> is to be sent along with the key and descriptor record, as specified above. Because it is a <tt>MAC</tt> over the entire plaintext, this is essentially an [https://en.wikipedia.org/wiki/Authenticated_encryption#Encrypt-and-MAC_(E&M) Encrypt-and-MAC] form of authenticated encryption.
==QR Codes== For signers that use QR codes to transmit data, key and descriptor records can be converted to QR codes, following [https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md the BCR standard].
Also refer to [https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-015-account.md UR Type Definition for BIP44 Accounts] and [https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-010-output-desc.md UR Type Definition for Bitcoin Output Descriptors] for more details.
==Security==
This proposal introduces two layers of protection. The first one is a temporary, secret <tt>TOKEN</tt>. The second one is the descriptor <tt>CHECKSUM</tt>.
The <tt>TOKEN</tt> is used to encrypt the two rounds of communication between the Signer and the Coordinator. A <tt>MAC</tt> is also generated from the <tt>TOKEN</tt> and plaintext to authenticate the data being exchanged. The <tt>TOKEN</tt> is only needed during the setup phase, and can be safely discarded afterwards.
The descriptor <tt>CHECKSUM</tt>, on the other hand, can be used to verify the integrity of the multisig configuration. An attacker who tampers with the multisig configuration must also change the descriptor <tt>CHECKSUM</tt>. Parties must check with each other that all Signers have the same <tt>CHECKSUM</tt>, along with the policy parameters, to reduce the chance of tampering. The <tt>CHECKSUM</tt> must be persisted along with the descriptor in each Signer’s storage.
The <tt>TOKEN</tt> and the <tt>CHECKSUM</tt> can’t guarantee complete protection, since that depends on the overall security of all parties in the setup, but they can make it significantly harder for an attacker to tamper with the multisig configuration.
==Privacy== Encryption helps improve the privacy of the wallet by avoiding sharing XPUBs and descriptors in plaintext.
If the parties wish to have stronger privacy, it is recommended to use a higher number of bits for the <tt>TOKEN</tt>, and to completely erase knowledge of the <tt>TOKEN</tt> after the multisig wallet has been set up.
==Test Vectors==
===Mode: <tt>NO_ENCRYPTION</tt>=== ====ROUND 1==== * Coordinator ** M-of-N: 2/2 ** ADDRESS_TYPE: NATIVE_SEGWIT ** TOKEN: 0
* Signer 1 ** MASTER_KEY_FINGERPRINT: 539f3d89 ** PRIVATE_KEY (m/48'/0'/0'/2'): KyoXqiwiz6qm21BSYebiZFfNF7obkhiJW6TdPMZTQQMF4kZtfD78 ** XPUB (m/48'/0'/0'/2'): xpub6ETerig7tq89mtaD8Gau2xRWxouRMBy6XHqciA8GZzC2dJv3w6FxfgoegH4b2qYF4oG6VBrhpLrauPs5E1q58GLCnhKp6g9QsV9ZA7J5JNa ** Legacy signature ** <tt>signer_1_key.bsms</tt>: <pre>BSMS 1.0 00 [539f3d89/48'/0'/0'/2']xpub6ETerig7tq89mtaD8Gau2xRWxouRMBy6XHqciA8GZzC2dJv3w6FxfgoegH4b2qYF4oG6VBrhpLrauPs5E1q58GLCnhKp6g9QsV9ZA7J5JNa Signer 1 key IPXsnNSZb8M6H4fAWtpjAc75hyHHd89fskpM5o7qFg+mPDzEPc1k2mjuIpVIIzaCe45FwPfAAa91RaStfC5Sak0=</pre>
* Signer 2 ** MASTER_KEY_FINGERPRINT: f8b12aa6 ** PRIVATE_KEY (m/48'/0'/0'/2'): L1zht7muKnUYFMdzC3jwXd78u8tGoKr46AXGh4waF9nphUYWq7ow ** XPUB (m/48'/0'/0'/2'): xpub6EWPNhGSX86SN4J2DrBUaQ826o6V4egHqAJZUDJqnsthv9CcjBZV79u68M3YZkuTJnJBXfCrHuJy97fkVurntwgt3V7Ms5hXpJV2vS8fQZM ** Legacy signature ** <tt>signer_2_key.bsms</tt>: <pre>BSMS 1.0 00 [f8b12aa6/48'/0'/0'/2']xpub6EWPNhGSX86SN4J2DrBUaQ826o6V4egHqAJZUDJqnsthv9CcjBZV79u68M3YZkuTJnJBXfCrHuJy97fkVurntwgt3V7Ms5hXpJV2vS8fQZM Signer 2 key H38+lp9iaesBeCN05BDTH/SnmarlH6+X+Kmw1pgCk+c1Pc1evYIdBag9Nc0nsKhvPtfEbRt9r/qsUVZ5onCtBTc=</pre>
====ROUND 2==== * Coordinator ** <tt>my_multisig_wallet.bsms</tt>: <pre>BSMS 1.0 /0/*,/1/* wsh(sortedmulti(2,[539f3d89/48'/0'/0'/2']xpub6ETerig7tq89mtaD8Gau2xRWxouRMBy6XHqciA8GZzC2dJv3w6FxfgoegH4b2qYF4oG6VBrhpLrauPs5E1q58GLCnhKp6g9QsV9ZA7J5JNa/*,[f8b12aa6/48'/0'/0'/2']xpub6EWPNhGSX86SN4J2DrBUaQ826o6V4egHqAJZUDJqnsthv9CcjBZV79u68M3YZkuTJnJBXfCrHuJy97fkVurntwgt3V7Ms5hXpJV2vS8fQZM/*))#fntxdj7p</pre>
===Mode: <tt>STANDARD</tt> Encryption=== ====ROUND 1==== * Coordinator ** M-of-N: 2/2 ** ADDRESS_TYPE: NATIVE_SEGWIT ** TOKEN (hex): 1ed4ba49e96336b8 *** TOKEN (decimal): 2221605342811469496 *** TOKEN (mnemonic): burst place mystery spot cricket foster ** ENCRYPTION_KEY (hex): 72185a0e25b4efc5d6ac0f8ed32b0165199100e32385040e3a48eb30164bf492
* Signer 1 ** MASTER_KEY_FINGERPRINT: 98d79e95 ** PRIVATE_KEY (m/48'/0'/0'/2'): KydC7hZFtWe56oQUAw14HvQ3gKeKVd3m8frFgVMxUqpuhKHvcmm3 ** XPUB (m/48'/0'/0'/2'): xpub6DvvwHS5pd1D36xt4YBGJvtdThWXfn8L9qRj9DbFMExMeP6eBE6Aw9WyBC7XUQwiPPDFurirewsKZpYv68yTV5RBy7SZmw45QEkaLka5BCt ** Legacy signature ** <tt>signer_1_key.bsms</tt>: <pre>BSMS 1.0 1ed4ba49e96336b8 [98d79e95/48'/0'/0'/2']xpub6DvvwHS5pd1D36xt4YBGJvtdThWXfn8L9qRj9DbFMExMeP6eBE6Aw9WyBC7XUQwiPPDFurirewsKZpYv68yTV5RBy7SZmw45QEkaLka5BCt Signer 1 key HxtPoP0DrQSac/7ypcwC07R2s6jjpXR6Li2Q92zXj/FSIMQcV5yOU0/ONsDgHXamq0gD5DfPbvuVCp9ZJubclV4=</pre>
* Signer 1 encryption ** HMAC_KEY (hex): 4dab3988cbc683ad7a8c93d43f9b11a78b63a93d5e33ea19c603f4b7b87ac284 ** MAC (hex): afe99e92f0eadc3308eb990045e90a4f54e9f59d22aae5034ac3d866d29c508d ** IV (hex) : afe99e92f0eadc3308eb990045e90a4f ** CIPHERTEXT (hex): 214ec9a861a238ba7f0412305a97a6e0faa332be15af09127e131d669e5d55d73891580a5808cea5d2bf39f43496d3c0f8236eff3854fcc7446daf9d2b58fd40d97ce3b1745de2959e29767039b99969821400eca0c3517fae56d2d24d5235a3430af1ed894b68681d706cce7c75adf35d8580603aa302bc01fef06d0336a37f19dd46100baa9e4eabd8796a810e13941ad0980c126ad55d6a4bbef11a7bf893b7d2ed8fb0d8324c4c9b512d4d1e75096c63511e15018fc832816b5639d58fc28c60c049487d04bd5a6cb32aa1381d0809660d54376b9f63325c18cfd1ac5024088e74cb703fe165972cc4485abb1feefe92a0b4ea297fe2f4f7416eeee1efc9b942540931ef ** <tt>signer_1_key.dat</tt>: <pre>afe99e92f0eadc3308eb990045e90a4f54e9f59d22aae5034ac3d866d29c508d214ec9a861a238ba7f0412305a97a6e0faa332be15af09127e131d669e5d55d73891580a5808cea5d2bf39f43496d3c0f8236eff3854fcc7446daf9d2b58fd40d97ce3b1745de2959e29767039b99969821400eca0c3517fae56d2d24d5235a3430af1ed894b68681d706cce7c75adf35d8580603aa302bc01fef06d0336a37f19dd46100baa9e4eabd8796a810e13941ad0980c126ad55d6a4bbef11a7bf893b7d2ed8fb0d8324c4c9b512d4d1e75096c63511e15018fc832816b5639d58fc28c60c049487d04bd5a6cb32aa1381d0809660d54376b9f63325c18cfd1ac5024088e74cb703fe165972cc4485abb1feefe92a0b4ea297fe2f4f7416eeee1efc9b942540931ef</pre>
* Signer 2 ** MASTER_KEY_FINGERPRINT: 3e94b5a1 ** PRIVATE_KEY (m/48'/0'/0'/2'): KyPh5XYjExjNHPiBjYhp8iAntAehrDziiwRv7y9Ln6eK9QU2xP55 ** XPUB (m/48'/0'/0'/2'): xpub6E1W1DUYY29V2b8czCcpi36GG2uD33B11vwNopgTZwsVyfgAkA4kPCqLP5R4YzaRvzW17CQrDkgmDQbA848AdkR7W18nNvMKXzzCBSnZP9c ** Legacy signature ** <tt>signer_2_key.bsms</tt>: <pre>BSMS 1.0 1ed4ba49e96336b8 [3e94b5a1/48'/0'/0'/2']xpub6E1W1DUYY29V2b8czCcpi36GG2uD33B11vwNopgTZwsVyfgAkA4kPCqLP5R4YzaRvzW17CQrDkgmDQbA848AdkR7W18nNvMKXzzCBSnZP9c Signer 2 key ILR49QLy9+xkMS11TIXJRSMgOQOzGbAaooq4/ZRcd8VgM6j5upJMI0mjJHseQOMYSGk8FqjXZbMvBGyiX9wdutM=</pre>
* Signer 2 encryption ** HMAC_KEY (hex): 4dab3988cbc683ad7a8c93d43f9b11a78b63a93d5e33ea19c603f4b7b87ac284 ** MAC (hex): 5c7cb2ac407cd60b1f2b86ef46077d3a312b6ce921df2a141347e8bf1e5c6573 ** IV (hex) : 5c7cb2ac407cd60b1f2b86ef46077d3a ** CIPHERTEXT (hex): f23e6c76ff45d308dea6014030a274127ad437228f1d5ec2431d2ea9e3cedd5b0a207a9efa6f926d5420205003f3cb9c4b82b2d595180e62a173a2e5aa0322de48a70a873f641bdae1764e6b1667c241e0fe03a4ccdc3fe0cfa5f75b239d6497c3b69dca17bb685ba70b307d1243836d8fb198ce727cfae4057ee0b4fdcb09f4ba5ae127f49c5de780edb4e40aec96303c8a7b98b1b8e53dd5e07e01d4f3ffd836763209a1f0cbc61adcfdc2951e77528ee7b6e68114c3a4bec38875d285021e68ae8aa913bb1e2e65dd52c649a0e98bfb4e8bab6dd10295c1167a0854ba44f094feb75d2fb00c944f07d4b47114f483df9838459316f3ddbc4a82e6507881931f8e20f5b805 ** <tt>signer_2_key.dat</tt>: <pre>5c7cb2ac407cd60b1f2b86ef46077d3a312b6ce921df2a141347e8bf1e5c6573f23e6c76ff45d308dea6014030a274127ad437228f1d5ec2431d2ea9e3cedd5b0a207a9efa6f926d5420205003f3cb9c4b82b2d595180e62a173a2e5aa0322de48a70a873f641bdae1764e6b1667c241e0fe03a4ccdc3fe0cfa5f75b239d6497c3b69dca17bb685ba70b307d1243836d8fb198ce727cfae4057ee0b4fdcb09f4ba5ae127f49c5de780edb4e40aec96303c8a7b98b1b8e53dd5e07e01d4f3ffd836763209a1f0cbc61adcfdc2951e77528ee7b6e68114c3a4bec38875d285021e68ae8aa913bb1e2e65dd52c649a0e98bfb4e8bab6dd10295c1167a0854ba44f094feb75d2fb00c944f07d4b47114f483df9838459316f3ddbc4a82e6507881931f8e20f5b805</pre>
====ROUND 2==== *Coordinator ** <tt>my_multisig_wallet.bsms</tt>: <pre>BSMS 1.0 /0/*,/1/* wsh(sortedmulti(2,[98d79e95/48'/0'/0'/2']xpub6DvvwHS5pd1D36xt4YBGJvtdThWXfn8L9qRj9DbFMExMeP6eBE6Aw9WyBC7XUQwiPPDFurirewsKZpYv68yTV5RBy7SZmw45QEkaLka5BCt/*,[3e94b5a1/48'/0'/0'/2']xpub6E1W1DUYY29V2b8czCcpi36GG2uD33B11vwNopgTZwsVyfgAkA4kPCqLP5R4YzaRvzW17CQrDkgmDQbA848AdkR7W18nNvMKXzzCBSnZP9c/*))#x0lx92qk</pre>
*Coordinator encryption ** HMAC_KEY (hex): 4dab3988cbc683ad7a8c93d43f9b11a78b63a93d5e33ea19c603f4b7b87ac284 ** MAC (hex): df3d06db6c8b8a5f25de202e10ea225df6415d1ed0e36c64cc2be1b7e86c2a38 ** IV (hex) : df3d06db6c8b8a5f25de202e10ea225d ** CIPHERTEXT (hex): 2761e6bfe839586b4c90954200bc4ce6d39ef164c5d14997755575d1691ee249ffd20beda526f57a7424907f839c6c2e3ecd46889ede290a2c81de22d3f33a7fa5e55ec95c0e26005c596d0f6346f819823f361f9f9f54d1eae48b325240d66c5888bd5ebab843061dcdd73b675346da982646c83026694d757661d31c2d654fb263c9ab3e874a258bc234c48532f15e9450c982fcf161404746e9f23d25e17b74139cd799983fd0c7a7a0386a823d3789b4578879a764172cc8ef96ab003eee24f6288007d31e2b999aff5a6d30cc524a0111a99730a29cf28ae41dbff6ce21ca6bc1df37074228178048e835584e6e70dba941154d024cd03cb6c56d0bde441ce464aa749de5e814dd30e21b75f62e831ac1f28eda1a7ba7e122076789e284402c8ba85b5a0e864bce220e3c78fa2f465e2bcf6b1d378816319de99f99ce7068 ** <tt>my_multisig_wallet.dat</tt>: <pre>df3d06db6c8b8a5f25de202e10ea225df6415d1ed0e36c64cc2be1b7e86c2a382761e6bfe839586b4c90954200bc4ce6d39ef164c5d14997755575d1691ee249ffd20beda526f57a7424907f839c6c2e3ecd46889ede290a2c81de22d3f33a7fa5e55ec95c0e26005c596d0f6346f819823f361f9f9f54d1eae48b325240d66c5888bd5ebab843061dcdd73b675346da982646c83026694d757661d31c2d654fb263c9ab3e874a258bc234c48532f15e9450c982fcf161404746e9f23d25e17b74139cd799983fd0c7a7a0386a823d3789b4578879a764172cc8ef96ab003eee24f6288007d31e2b999aff5a6d30cc524a0111a99730a29cf28ae41dbff6ce21ca6bc1df37074228178048e835584e6e70dba941154d024cd03cb6c56d0bde441ce464aa749de5e814dd30e21b75f62e831ac1f28eda1a7ba7e122076789e284402c8ba85b5a0e864bce220e3c78fa2f465e2bcf6b1d378816319de99f99ce7068</pre>
===Mode: <tt>EXTENDED</tt> Encryption=== ====ROUND 1==== *Coordinator ** M-of-N: 2/3 ** ADDRESS_TYPE: NESTED_SEGWIT ** TOKEN for Signer 1 (hex): 654d63309464afcda558c6aa *** TOKEN (decimal): 31351541690484562733651510954 *** TOKEN (mnemonic): grab help slow churn enough traffic nice boat price *** ENCRYPTION_KEY (hex): 4073adac2351e164b8d68039abd9d4b8e4d07adccfdf73ece6e236d60b107802 ** TOKEN for Signer 2 (hex): b0344f51d5cb04083d598fa3 *** TOKEN (decimal): 54532600447720520868878192547 *** TOKEN (mnemonic): rabbit pen stamp process raccoon advice voice cradle person *** ENCRYPTION_KEY (hex): 6bae6b670e257d7468c3e90194029dd468a2f39d8b9a3ff187b08209b1d409b6 ** TOKEN for Signer 3 (hex): 163fd307195982c4c39d50bb *** TOKEN (decimal): 6885829092987042066541138107 *** TOKEN (mnemonic): bike write scrub crawl oblige give attack present rookie *** ENCRYPTION_KEY (hex): c78b94589214b6dc98b337ba4ce54380553ed00a1e5b1955fc540ce3b30d6566
* Signer 1 ** MASTER_KEY_FINGERPRINT: 110dc257 ** PRIVATE_KEY (m/48'/0'/0'/1'): KzshDDEBhzyiwXHoyE7ZiLegzztEy54AG6Wq8N844LqHSQMHt4Ji ** XPUB (m/48'/0'/0'/1'): xpub6EPQbDFezXYvVFHqnc8R7QUSE8hTepbyCXU7jJBT4dVm2rQHe1i6isqoj59qhyBiCdKquo6QsgMZNHvEz3BM4cNSszF25siTqLUCznBm8vk ** Legacy signature ** <tt>signer_1_key.bsms</tt>: <pre>BSMS 1.0 654d63309464afcda558c6aa [110dc257/48'/0'/0'/1']xpub6EPQbDFezXYvVFHqnc8R7QUSE8hTepbyCXU7jJBT4dVm2rQHe1i6isqoj59qhyBiCdKquo6QsgMZNHvEz3BM4cNSszF25siTqLUCznBm8vk Signer 1 key IDX6xLdM4XjetYPvVfpVBXAfT7oE3tHAOB4blZpbIst8bjJ+LbDeP4tZl4O8utAuys9igXE0G3kaHz1mg/+OU8w=</pre>
* Signer 1 encryption ** HMAC_KEY (hex): f43c359a4b3d7b2e01be73c54519b12545ca9a23a86f824aadf577b314a7caa7 ** MAC (hex): 40b6b43e2f1bc01b748eb242235d7e09fa8a2fd6cebe35784cf3adf81910ec98 ** IV (hex) : 40b6b43e2f1bc01b748eb242235d7e09 ** CIPHERTEXT (hex): 0877987764401c27e6c60ed2f1bb89dff1dbc5e8204149f682d53049bffe39553f24af3928aa2f78ac2d04ac5baa0c3ec39aaccf0d258e7bb6659a7b92e92f2c2784a94f4df8e8af2270d9d411bfff2cfb9f71b4e1ac87561c7d2ac57ca86a1f9716d5da7571719d24830fc8d015a0daf04b3742439484488798335357f2eeaa8e2db2ba630f9dffd88236e327ab5bfcfb6e29ee3ef6cc18e0b71c1731465c2351e76b92f7b1bd28ef6eff5414c22aa6c80090fa59b973c22e3044e92dbf3688990a49a42828e52c1e686f1193dcdf7b7118930e01419fe938c6811c58c84c36d692fd52846f998bc328471f1e73c22261791a08cda096ee3ac8b37f31afd0b1d9c335ff9ac67ff230eb0d69f2d7 ** <tt>signer_1_key.dat</tt>: <pre>40b6b43e2f1bc01b748eb242235d7e09fa8a2fd6cebe35784cf3adf81910ec980877987764401c27e6c60ed2f1bb89dff1dbc5e8204149f682d53049bffe39553f24af3928aa2f78ac2d04ac5baa0c3ec39aaccf0d258e7bb6659a7b92e92f2c2784a94f4df8e8af2270d9d411bfff2cfb9f71b4e1ac87561c7d2ac57ca86a1f9716d5da7571719d24830fc8d015a0daf04b3742439484488798335357f2eeaa8e2db2ba630f9dffd88236e327ab5bfcfb6e29ee3ef6cc18e0b71c1731465c2351e76b92f7b1bd28ef6eff5414c22aa6c80090fa59b973c22e3044e92dbf3688990a49a42828e52c1e686f1193dcdf7b7118930e01419fe938c6811c58c84c36d692fd52846f998bc328471f1e73c22261791a08cda096ee3ac8b37f31afd0b1d9c335ff9ac67ff230eb0d69f2d7</pre>
* Signer 2 ** MASTER_KEY_FINGERPRINT: 5c890401 ** PRIVATE_KEY (m/48'/0'/0'/1'): L41Jnc9CdBtBJd18429MDGcTgP2DNoXaKyyGr271ndTprvrHXDQf ** XPUB (m/48'/0'/0'/1'): xpub6EW1SmjSXq9YwVwcan5qWEncgx89SozMvGNpYF6hfZHYNTikNZ4gsXuVhHTi6xYJCkmY4X4wpPPS5Gr7aY39dVJMS2TGfihr25oaspKtU8q ** Legacy signature ** <tt>signer_2_key.bsms</tt>: <pre>BSMS 1.0 b0344f51d5cb04083d598fa3 [5c890401/48'/0'/0'/1']xpub6EW1SmjSXq9YwVwcan5qWEncgx89SozMvGNpYF6hfZHYNTikNZ4gsXuVhHTi6xYJCkmY4X4wpPPS5Gr7aY39dVJMS2TGfihr25oaspKtU8q Signer 2 key H5kN6UHaK2xACB6iYdTxxQPD8qyFEYv9iMsQs5B0MRfCM7NA5GB+7EFgmBpSctwt6B122zWBr6mRjpYjKmj+7hs=</pre>
* Signer 2 encryption ** HMAC_KEY (hex): e0a20b5f5285fbaa35aad08fb70f5626c9abbe1b384a4950735b28aca6325ff2 ** MAC (hex): 3a6deec8dbdbd6606a52c7d7e64eca4f972a293cbabac6f62736629fbe77928a ** IV (hex) : 3a6deec8dbdbd6606a52c7d7e64eca4f ** CIPHERTEXT (hex): bb0fb72f61b0c4858bd9c65235390b67651b94c4b0329238b0116dd6d3365ade33cb1c1b1619638968791a5d2d1d263d90280bdad8d9ca24c34a78e320076e0dccf59e7f729b541b44bbe40ba803dedd3b17c49765377cb2d913a856b86c3dd383dab475790e89226ed8ef2301574212d2809ed9c099aa67be434024ee2a4e82a146300acf755863da64807cb7bb2636f6616489636d254a870778d3540832aea44abac4328b5d90f3e6045ef36a526ce5d575f2305e3e4699dccbc713e9e68f50364036c1054c2a506aab77ea7c43a89536947c24330b09a62a90c3b4ae2d452f96ef34ec871af2c52d68ddede2503c87e2ba68d5cf9be589457879e06021ea6a6176f7dded820ba4c0e709e2a2 ** <tt>signer_2_key.dat</tt>: <pre>3a6deec8dbdbd6606a52c7d7e64eca4f972a293cbabac6f62736629fbe77928abb0fb72f61b0c4858bd9c65235390b67651b94c4b0329238b0116dd6d3365ade33cb1c1b1619638968791a5d2d1d263d90280bdad8d9ca24c34a78e320076e0dccf59e7f729b541b44bbe40ba803dedd3b17c49765377cb2d913a856b86c3dd383dab475790e89226ed8ef2301574212d2809ed9c099aa67be434024ee2a4e82a146300acf755863da64807cb7bb2636f6616489636d254a870778d3540832aea44abac4328b5d90f3e6045ef36a526ce5d575f2305e3e4699dccbc713e9e68f50364036c1054c2a506aab77ea7c43a89536947c24330b09a62a90c3b4ae2d452f96ef34ec871af2c52d68ddede2503c87e2ba68d5cf9be589457879e06021ea6a6176f7dded820ba4c0e709e2a2</pre>
* Signer 3 ** MASTER_KEY_FINGERPRINT: 614cbf5f ** PRIVATE_KEY (m/48'/0'/0'/1'): L2ccRLzH7GfVxWpU8YSY9y5UGyRoqW3UdeNT1vGfVbxAGhwU5qhD ** XPUB (m/48'/0'/0'/1'): xpub6F9TfWTFcMYy5Ycd2ka2az1brJj78J2isLAWptZnCpFsesss5sZv5B8xsgt71ZXfhDWhUtf4vng4zY6HUVrQbDMPDYRLYvFFoLnAYfzgYPH ** Legacy signature ** <tt>signer_3_key.bsms</tt>: <pre>BSMS 1.0 163fd307195982c4c39d50bb [614cbf5f/48'/0'/0'/1']xpub6F9TfWTFcMYy5Ycd2ka2az1brJj78J2isLAWptZnCpFsesss5sZv5B8xsgt71ZXfhDWhUtf4vng4zY6HUVrQbDMPDYRLYvFFoLnAYfzgYPH Signer 3 key H0jf2JMtke5zDDIWys6fihOCA6QBmC5+hbgVB/c2mMPNPLB6tDXt0TFZU1f9wvaCR9762anKSc8CCqXLogw8V00=</pre>
* Signer 3 encryption ** HMAC_KEY (hex): 1f51ea067c121e2f86af5e1d484905046bc63e861573157d8b1ae9e7e47e224b ** MAC (hex): 1a5624fcb39cebabb6174456173eec19b756bc916cf2c9d815e9bcce070898c4 ** IV (hex) : 1a5624fcb39cebabb6174456173eec19 ** CIPHERTEXT (hex): 48d6e139bdc8c19e93cbbf5b4478340c8cf08aa91c28803084d5f58618773f7e615e0134492b496c4e7c130351c0350701f686918033f621378552d7040efedd5539d38c258bf936475de775f23da3953fe3ba5bbbd24816b8902b87a9a09700c446b085119dedee2395dd69665e742f72f2fb6da4ebe3f4704eaf45486fbfb84d764b718cc0b756e72f72ab6069d47765bdd3ebd4074af4fa99a95691a659675ce5f72235c28ddf3c3d53179e598cddc967fc896adc6e97edeeffc85b9e44611df748d923ff3dd921ad4d6e98e0de12359a37558e326faf585ba57e73ab45bc4a49f6e8a756f365f5d204e70f7c7bed269e81e9524a41e5d4cbaad0b6b442d6eea1e5da1ca345cc665a0cffe2c3 ** <tt>signer_3_key.dat</tt>: <pre>1a5624fcb39cebabb6174456173eec19b756bc916cf2c9d815e9bcce070898c448d6e139bdc8c19e93cbbf5b4478340c8cf08aa91c28803084d5f58618773f7e615e0134492b496c4e7c130351c0350701f686918033f621378552d7040efedd5539d38c258bf936475de775f23da3953fe3ba5bbbd24816b8902b87a9a09700c446b085119dedee2395dd69665e742f72f2fb6da4ebe3f4704eaf45486fbfb84d764b718cc0b756e72f72ab6069d47765bdd3ebd4074af4fa99a95691a659675ce5f72235c28ddf3c3d53179e598cddc967fc896adc6e97edeeffc85b9e44611df748d923ff3dd921ad4d6e98e0de12359a37558e326faf585ba57e73ab45bc4a49f6e8a756f365f5d204e70f7c7bed269e81e9524a41e5d4cbaad0b6b442d6eea1e5da1ca345cc665a0cffe2c3</pre>
====ROUND 2==== * Coordinator ** <tt>my_multisig_wallet.bsms</tt>: <pre>BSMS 1.0 /0/*,/1/* sh(wsh(multi(2,[110dc257/48'/0'/0'/1']xpub6EPQbDFezXYvVFHqnc8R7QUSE8hTepbyCXU7jJBT4dVm2rQHe1i6isqoj59qhyBiCdKquo6QsgMZNHvEz3BM4cNSszF25siTqLUCznBm8vk/*,[5c890401/48'/0'/0'/1']xpub6EW1SmjSXq9YwVwcan5qWEncgx89SozMvGNpYF6hfZHYNTikNZ4gsXuVhHTi6xYJCkmY4X4wpPPS5Gr7aY39dVJMS2TGfihr25oaspKtU8q/*,[614cbf5f/48'/0'/0'/1']xpub6F9TfWTFcMYy5Ycd2ka2az1brJj78J2isLAWptZnCpFsesss5sZv5B8xsgt71ZXfhDWhUtf4vng4zY6HUVrQbDMPDYRLYvFFoLnAYfzgYPH/*)))#j3ykhz7f</pre>
* Send to Signer 1: ** HMAC_KEY (hex): f43c359a4b3d7b2e01be73c54519b12545ca9a23a86f824aadf577b314a7caa7 ** MAC (hex): ee74a0f50943d7d1b65270028bb05133e87c832cdc1ef0a07c79db2093ca3432 ** IV (hex) : ee74a0f50943d7d1b65270028bb05133 ** CIPHERTEXT (hex): 8e3ba3dac0f979fad0d160bd00c8294ff1726d51b95ff3e1534e5a1900f3d7cd4f6d929985a94b9da2c11e4e0f7770cc53c6739fd099477323bd26a3eca9c8016e79848d15e274463424b8355cd73cced61f1816ac8bac87f8c650ee9052f50e347c52ad24b00794a9d5523714be2fdcf731f14b7a8d7c93eab44c258e1c417d2837b9676832e8ce7239dc28b4e1166803209947b8a875a99b9478ee94f7bc17399e886179ab2a0285dc11a3883f6fa439d0f2277dadbec8c355c379fc50e945897e1a738f6a55b09f6b8b6bdf6d4bc248219cbad3662a78a2f539c989e055e00b8efd42fbff978e1a5cc10f83df56117ece4d17f94a0a6d3803778ed53531419250c5a0fff6cad4ab401468dd054915b068cc8826ae1308a71b38060d68c9248d59eea11c2c52a66d5f6bc0d7ae6cb44305c36e56068456d293b70037902e7b05a3ee0af710201128dffc0c16c3306b66bd19b9ae5b91aded35ef33f07743e5b185a9f88a5c67d40270e3bbcf592167ceaf82ead693728d5129b50075edd5ce24863f3484b4b063599ed1327e1c87d0a2051fed3b1234a702722b686e4c9392a403b79726800dd6b691e516e44d9e836c190b10cf2bb262bba98293c97f2c323e59acd0a1f988c5 ** <tt>my_multisig_wallet_for_signer_1.dat</tt>: <pre>ee74a0f50943d7d1b65270028bb05133e87c832cdc1ef0a07c79db2093ca34328e3ba3dac0f979fad0d160bd00c8294ff1726d51b95ff3e1534e5a1900f3d7cd4f6d929985a94b9da2c11e4e0f7770cc53c6739fd099477323bd26a3eca9c8016e79848d15e274463424b8355cd73cced61f1816ac8bac87f8c650ee9052f50e347c52ad24b00794a9d5523714be2fdcf731f14b7a8d7c93eab44c258e1c417d2837b9676832e8ce7239dc28b4e1166803209947b8a875a99b9478ee94f7bc17399e886179ab2a0285dc11a3883f6fa439d0f2277dadbec8c355c379fc50e945897e1a738f6a55b09f6b8b6bdf6d4bc248219cbad3662a78a2f539c989e055e00b8efd42fbff978e1a5cc10f83df56117ece4d17f94a0a6d3803778ed53531419250c5a0fff6cad4ab401468dd054915b068cc8826ae1308a71b38060d68c9248d59eea11c2c52a66d5f6bc0d7ae6cb44305c36e56068456d293b70037902e7b05a3ee0af710201128dffc0c16c3306b66bd19b9ae5b91aded35ef33f07743e5b185a9f88a5c67d40270e3bbcf592167ceaf82ead693728d5129b50075edd5ce24863f3484b4b063599ed1327e1c87d0a2051fed3b1234a702722b686e4c9392a403b79726800dd6b691e516e44d9e836c190b10cf2bb262bba98293c97f2c323e59acd0a1f988c5</pre>
* Send to Signer 2: ** HMAC_KEY (hex): e0a20b5f5285fbaa35aad08fb70f5626c9abbe1b384a4950735b28aca6325ff2 ** MAC (hex): 81df9e064f1de1d5f754c4e20f9286f9d81b856d3965677a9f2430cb9297ad1f ** IV (hex) : 81df9e064f1de1d5f754c4e20f9286f9 ** CIPHERTEXT (hex): dcd82038ef627d6cb2deb62d04c4ccbaa3a354633d960e46312c22791f039f23fd9782a1e3a63504c1e5b3a0770bb8d32fdf168738b6c03278f1391dd5d01e9aafee7be2c8136ee018feff6fc8cdb926df13a36e115ddca8254934f56b7f700768c94cb8388a8297834de9affcd959417ae3d6ec3251387904f50f51f06306cc4d36eefc51418dd3b2c5454910a23ec67a40a3b918d2a740e812929aae949d8dde2c41cbbb3a2b7c2103788421c147f4794d6a26947c15ef4a99ceb825d0c5aaa78b8737d0ef712ba8e269a9941b1af5d217dcdd9cd06727fbdc70fabe3f5a8c09acff4e76992be7f27c6b12ca84739f62a6da86e5b79103d632c0dc8ab3f91fddb3cfbe67084dc4b861c4ac7c86fb171a058c98c67cffdc40ff17ae1533361cc6fb7b63657af0408cf30bf9d6d97aaacf9d3ff443eee61f207228cd91769ce83a0709c1be1847884c6a8fdc86ede66aef8e34fc509c49edf30f743bdc8f9052961ee340924ec2d1caadc6fd286bb3e233c153cd08c1934127752dc28e0d12efa92a050c4061653edb1cbf2fd4b2ba4e038f0b44f5735f198e92571c029156f65f534bfc149f38d611829901372cfc0176b9d2f9ac6512b7f37941a02dff701df0bceadaacfc6935 ** <tt>my_multisig_wallet_for_signer_2.dat</tt>: <pre>81df9e064f1de1d5f754c4e20f9286f9d81b856d3965677a9f2430cb9297ad1fdcd82038ef627d6cb2deb62d04c4ccbaa3a354633d960e46312c22791f039f23fd9782a1e3a63504c1e5b3a0770bb8d32fdf168738b6c03278f1391dd5d01e9aafee7be2c8136ee018feff6fc8cdb926df13a36e115ddca8254934f56b7f700768c94cb8388a8297834de9affcd959417ae3d6ec3251387904f50f51f06306cc4d36eefc51418dd3b2c5454910a23ec67a40a3b918d2a740e812929aae949d8dde2c41cbbb3a2b7c2103788421c147f4794d6a26947c15ef4a99ceb825d0c5aaa78b8737d0ef712ba8e269a9941b1af5d217dcdd9cd06727fbdc70fabe3f5a8c09acff4e76992be7f27c6b12ca84739f62a6da86e5b79103d632c0dc8ab3f91fddb3cfbe67084dc4b861c4ac7c86fb171a058c98c67cffdc40ff17ae1533361cc6fb7b63657af0408cf30bf9d6d97aaacf9d3ff443eee61f207228cd91769ce83a0709c1be1847884c6a8fdc86ede66aef8e34fc509c49edf30f743bdc8f9052961ee340924ec2d1caadc6fd286bb3e233c153cd08c1934127752dc28e0d12efa92a050c4061653edb1cbf2fd4b2ba4e038f0b44f5735f198e92571c029156f65f534bfc149f38d611829901372cfc0176b9d2f9ac6512b7f37941a02dff701df0bceadaacfc6935</pre>
* Send to Signer 3: ** HMAC_KEY (hex): 1f51ea067c121e2f86af5e1d484905046bc63e861573157d8b1ae9e7e47e224b ** MAC (hex): 159a91100cacd123480b7d085c8bb32ec8eb06f0391b6dc8fac07ae67eb37b81 ** IV (hex) : 159a91100cacd123480b7d085c8bb32e ** CIPHERTEXT (hex): c7269d8be21d1cfe172e35aa106760f1fdc929fce19da8fb7f74f759efec1ee02796fb1e8b008cf177f60a2021570f17aeeb41f8636858654082734b90959b98fd08419f901683c4ca3e76b3e482fea4c67162775e0d80bcb45df729f646c1364a3d8a7d1ff961717b00897e877c1c0554d3502942149726806269c546ad2dd34ba286ddf5cd336b83aabf7091fa25e607faf7e54017d84113e1e3ec440b3704addea188b89293469306fc0a98570afdcf269026b2d2e760f466c1f75bcf75fdf030c0a692e5681fd4487e59d6e96451ff5b6b9f2521b8e95e796ef4ab0a917794d91a30fdac7ee9ddbd89d174831bd133ab12a74f52f6283ee2c5fe3d5a957a7c1a15530b2c5224f76d90057dc94f2ee34e28b037ae7f518cc6dfe725cd3e657648de82b200ea77830eb93219f883998d3207a4ef5902d1119b0cde6b364bc1effb86109d9c2babc8ab26dce90329779d8cd0d737e9825a25586aa3c8fa5317e3e433ff235b82f629de0504e3c992f8e8de299f62751bc1fcb2e75e0262c7a27be7068cea69b14f303e97c24b99ed29cae142564e285657704b4c411d0d4f8c58819e2c0e0ffc3667eb5a408aad8a3023a5f00875e7deab95dc365d8757f7b79815a4fd9e6de2b3 ** <tt>my_multisig_wallet_for_signer_3.dat</tt>: <pre>159a91100cacd123480b7d085c8bb32ec8eb06f0391b6dc8fac07ae67eb37b81c7269d8be21d1cfe172e35aa106760f1fdc929fce19da8fb7f74f759efec1ee02796fb1e8b008cf177f60a2021570f17aeeb41f8636858654082734b90959b98fd08419f901683c4ca3e76b3e482fea4c67162775e0d80bcb45df729f646c1364a3d8a7d1ff961717b00897e877c1c0554d3502942149726806269c546ad2dd34ba286ddf5cd336b83aabf7091fa25e607faf7e54017d84113e1e3ec440b3704addea188b89293469306fc0a98570afdcf269026b2d2e760f466c1f75bcf75fdf030c0a692e5681fd4487e59d6e96451ff5b6b9f2521b8e95e796ef4ab0a917794d91a30fdac7ee9ddbd89d174831bd133ab12a74f52f6283ee2c5fe3d5a957a7c1a15530b2c5224f76d90057dc94f2ee34e28b037ae7f518cc6dfe725cd3e657648de82b200ea77830eb93219f883998d3207a4ef5902d1119b0cde6b364bc1effb86109d9c2babc8ab26dce90329779d8cd0d737e9825a25586aa3c8fa5317e3e433ff235b82f629de0504e3c992f8e8de299f62751bc1fcb2e75e0262c7a27be7068cea69b14f303e97c24b99ed29cae142564e285657704b4c411d0d4f8c58819e2c0e0ffc3667eb5a408aad8a3023a5f00875e7deab95dc365d8757f7b79815a4fd9e6de2b3</pre>
==Acknowledgement==
Special thanks to Pavol Rusnak, Dmitry Petukhov, Christopher Allen, Craig Raw, Robert Spigler, Gregory Sanders, Ta Tat Tai, Michael Flaxman, Pieter Wuille and others for their feedback on the specification.
==References==
Original mailing list thread: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-February/018385.html
Hi all,
First of all thanks for your continued work on standardising multisig setup.
The use case I personally find most interesting is not a multi-party setup, but rather just combining a bunch of my own devices. Those might even be in the same room during the setup, only to be moved to my moon base later.
This means I've paid less attention to the encryption scheme, so I might set TOKEN=0, but nevertheless I am skeptical about it. The first step is for the Coordinator to generate a TOKEN, presumably using its own entropy. But IIUC anyone who intercepts that token can decrypt any future step in the setup process. This suggests a chicken-egg problem where you need some pre-existing secure communications channel.
To the list of concerns at the top of the BIP, I would add one: losing multisig setup context. E.g. in the event of a fire where you only recover your steel engraved mnemonic(s), but no longer have the wallet descriptors.
If you still have all devices and know (or guess) the threshold then BIP48 and sorted_multi descriptors will save you. But if you have a 2-of-3 setup and lost 1 device then without the metadata your coins are lost. In a future with musig(?) and miniscript increasingly the setup data is just as critical as the seeds.
A future standard (or extension of this one) should recommend an encryption convention for the descriptor data, ideally such that with *any* of the seeds you can decrypt a file that contains the full setup. That file could then just float redundantly around the internet and pieces of paper in various locations, without compromising privacy.
The proposed encryption system doesn't help with that though, because it's based on entropy from the Coordinator, rather than from the signers.
Smaller suggestions: * link to this new mail thread in the BIP * use magic bytes so .bsms so operating systems like Android / iOs can open the right app for them * don't use separate file extensions for encrypted vs unencrypted content, just indicate somehow that a given field is encrypted * although plain text files are handy for debugging, I think a binary format like PSBT is much powerful. Any device that can parse and write binary PSBT should be able to implement a similar parser / writer for a binary .bsms format. * BIP48 and sorted_multi descriptors are useful in a loss-of-metadata scenario. The BIP uses both in the examples, but doesn't explictly endorse these derivations. It also contradicts them: "If the Signer chooses the path, it should try to avoid reusing XPUBs for different wallets.". Maybe this is out of scope. * one way to resolve xpub reuse would be to make the "BIP48" path a function of the co-signer fingerprints and wallet threshold, but this requires an extra communication round * there should be a way for signers to communicate their capabilities, perhaps with a different xpub for each potential scheme. E.g. there's m/48' native SegWit now, MuSig and/or or Tapleaf based multisig in the future, or even generic Miniscript support. * the idea of only storing the receive descriptor, not the change descriptor, is fine by me, though I'd prefer an extension to the descriptor format to deal with this
Sjors
Quoted text (7 lines)
> Op 5 apr. 2021, om 09:02 heeft Hugo Nguyen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> het volgende geschreven: > > Hi all, > > Please find below the complete draft of the Bitcoin Secure Multisig Setup (BSMS) BIP. The spec has gone through a number of important updates in the last month or so. Thanks everyone who has participated in the review process. > > As a PR: https://github.com/bitcoin/bips/pull/1097
Hi Sjors Thanks for the feedback!
The first step is for the Coordinator to generate a TOKEN, presumably using
Quoted text (4 lines)
> its own entropy. But IIUC anyone who intercepts that token can decrypt any > future step in the setup process. This suggests a chicken-egg problem where > you need some pre-existing secure communications channel. >
The exchange of the TOKEN is frequently mistaken as the chicken-and-egg problem, but it is not so.
To understand why this isn't chicken-and-egg, and why the TOKEN actually adds value, consider *the scale of the communication operation needed to exchange the TOKEN*, and *the scale of the communication operation needed to gather data for the creation of the multisig wallet *(with or without the TOKEN):
1) The TOKEN itself is a single piece of data that is 64- or 96-bit. It is small enough to be easily exchanged (even memorized) and entered into various devices. It requires only a single round of communication, but can protect as many rounds of communication as needed.
2) The data needed to create the multisig wallet, on the other hand, are quite involving: (a) Each Signer needs to share its XPUB, which cannot be memorized (b) The XPUBs also come with their own metadata (c) The creation of the wallet requires at least two rounds of communications since the Signers need to voluntarily share their XPUBs first, only then can a Coordinator combine the XPUBs into a single multisig script and pass back the configuration to the Signers. (Note that without a Coordinator, you'll need O(N^2) rounds of communication). (d) Because Signers are typically off-line cold storage, the paths between the Signers / the Signers <> Coordinator likely involve multiple hops through various media, such as unsecure USB connection. This is the way most multisig solutions are currently being implemented. It means the XPUBs and the multisig configuration are vulnerable to leaking and/or modifications.
Note that (d) is especially problematic for remote multisig setups. The more remote, the more potential hops along the way, the more problematic.
So you can see that *the TOKEN ultimately reduces the problem of sharing a large amount of sensitive data back and forth, to the sharing of a single, small piece of data upfront.* An added advantage of this approach is that if the parties fail to establish a shared TOKEN, the scheme fails with no harm done.
The Coordinator, on the other hand, adds value by solving the O(n^2) communication problem. Some minimal amount of trust is needed for the Coordinator, but this can be greatly mitigated by a number of ways that we have defined in the spec, such as: * Signers must check that their XPUBs are included in the final descriptor * Signers must display to the user the multisig configuration: M/N, relative position(s) of XPUBs, etc. * Signers must display the full descriptor upon user request for manual inspection - this one is important because it means that the new scheme cannot be worse than the status quo. * Signers are recommended to display a preview of the first receive address(es).
All in all, the Coordinator's role helps ease the setup process, while its ability to pull off any shenanigans is greatly limited.
Best, Hugo
(Continue off last email: also keep in mind, that just like BIP174, Coordinator and Signer are abstract roles. This means in theory a Signer can be the Coordinator too. The same criteria for trust applies equally to a Signer and a Coordinator.)
The use case I personally find most interesting is not a multi-party setup,
Quoted text (3 lines)
> but rather just combining a bunch of my own devices. Those might even be in > the same room during the setup, only to be moved to my moon base later. >
And that's fair. Both use cases (local and remote multisig) are valid and currently being used. But IMO a standard should accommodate both.
Quoted text (4 lines)
> To the list of concerns at the top of the BIP, I would add one: losing > multisig setup context. E.g. in the event of a fire where you only recover > your steel engraved mnemonic(s), but no longer have the wallet descriptors. >
Good point.
Quoted text (7 lines)
> > If you still have all devices and know (or guess) the threshold then BIP48 > and sorted_multi descriptors will save you. But if you have a 2-of-3 setup > and lost 1 device then without the metadata your coins are lost. In a > future with musig(?) and miniscript increasingly the setup data is just as > critical as the seeds. >
How so? Each signer device should ideally have a copy of the multisig configuration. If you lose 1 device in a 2-of-3, you can still spend from the wallet? Unless I'm missing something here.
Quoted text (6 lines)
> A future standard (or extension of this one) should recommend an > encryption convention for the descriptor data, ideally such that with *any* > of the seeds you can decrypt a file that contains the full setup. That file > could then just float redundantly around the internet and pieces of paper > in various locations, without compromising privacy. >
Post-wallet-creation, each Signer can apply extra encryption on top of BSMS for the persistence of the configuration file any way it wants :) It doesn't contradict with the current spec.
Quoted text (3 lines)
> The proposed encryption system doesn't help with that though, because it's > based on entropy from the Coordinator, rather than from the signers. >
They are for different purposes. The TOKEN-based encryption is only needed temporarily for the setup.
Quoted text (3 lines)
> Smaller suggestions: > * link to this new mail thread in the BIP >
Will do.
Quoted text (9 lines)
> * use magic bytes so .bsms so operating systems like Android / iOs can > open the right app for them > * don't use separate file extensions for encrypted vs unencrypted content, > just indicate somehow that a given field is encrypted > * although plain text files are handy for debugging, I think a binary > format like PSBT is much powerful. Any device that can parse and write > binary PSBT should be able to implement a similar parser / writer for a > binary .bsms format. >
Will consider these points, but I prefer plaintext for wallet configuration. Human readability for the wallet configuration is a pro not a con IMO. Also helps when backing up.
Quoted text (9 lines)
> * BIP48 and sorted_multi descriptors are useful in a loss-of-metadata > scenario. The BIP uses both in the examples, but doesn't explictly endorse > these derivations. It also contradicts them: "If the Signer chooses the > path, it should try to avoid reusing XPUBs for different wallets.". Maybe > this is out of scope. > * one way to resolve xpub reuse would be to make the "BIP48" path a > function of the co-signer fingerprints and wallet threshold, but this > requires an extra communication round >
We discussed this in the linked PR ( https://github.com/nunchuk-io/bips/pull/1), and decided that enforcing against path reuse is out-of-scope. We give examples of sorted_multi and multi because different vendors support different things.
Quoted text (5 lines)
> * there should be a way for signers to communicate their capabilities, > perhaps with a different xpub for each potential scheme. E.g. there's m/48' > native SegWit now, MuSig and/or or Tapleaf based multisig in the future, or > even generic Miniscript support. >
I considered Signers signaling capabilities (for a different reason), but opted against it because it further complicates the scheme. Also BIP48-like proposals are made redundant with the use of output descriptors.
Quoted text (4 lines)
> * the idea of only storing the receive descriptor, not the change > descriptor, is fine by me, though I'd prefer an extension to the descriptor > format to deal with this >
That's not quite accurate. The spec stores the top-level descriptor (XPUB/*) along with the path restrictions (/0/*,/1/*), not the receive descriptor.
The path restrictions would allow you to extend on the spec. There's also a VERSION field.
Best, Hugo
Quoted text (16 lines)
> > Sjors > > > Op 5 apr. 2021, om 09:02 heeft Hugo Nguyen via bitcoin-dev < > bitcoin-dev@lists•linuxfoundation•org> het volgende geschreven: > > > > Hi all, > > > > Please find below the complete draft of the Bitcoin Secure Multisig > Setup (BSMS) BIP. The spec has gone through a number of important updates > in the last month or so. Thanks everyone who has participated in the review > process. > > > > As a PR: https://github.com/bitcoin/bips/pull/1097 > >
Thanks for the detailed response. Just 1 thing I needed to clarify:
Quoted text (8 lines)
> To the list of concerns at the top of the BIP, I would add one: losing multisig setup context. E.g. in the event of a fire where you only recover your steel engraved mnemonic(s), but no longer have the wallet descriptors. > > Good point. > > > If you still have all devices and know (or guess) the threshold then BIP48 and sorted_multi descriptors will save you. But if you have a 2-of-3 setup and lost 1 device then without the metadata your coins are lost. In a future with musig(?) and miniscript increasingly the setup data is just as critical as the seeds. > > How so? Each signer device should ideally have a copy of the multisig configuration. If you lose 1 device in a 2-of-3, you can still spend from the wallet? Unless I'm missing something here.
I was thinking about a scenario where all devices are destroyed. All you have left are the mnemonics. But indeed if at least one of your devices is still intact AND it has the configuration, you're also good.
But there are plenty of devices out there that can't do this. Those devices can still be useful, even if they can't fully check everything.
Sjors
here's what we do for multisig:
- each member generates their own public/private key pair first and publishes the pair to all other members - members are then verified using a secondary channel, like a phone call ... where the H128(pubk) is turned into BIP-words for manual/visual verification - multi-round DKG is used with appropriate commitments and verification of components (nice article: https://link.springer.com/content/pdf/10.1007/s00145-006-0347-3.pdf)
without that, there's simply no guarantee that you're not communicating with an attacker during setup.
On Tue, Feb 9, 2021 at 2:53 AM Hugo Nguyen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (119 lines)
> > Hi all, > I would like to propose a new BIP for Secure Multisig Setup. > This proposal has taken inputs from folks at Coldcard, Shift Crypto and Cobo -- listed below as co-authors. > > This was inspired by my own experience working with hardware wallets on the market, as well as existing research into the challenges of multisig. > > Cheers, > Hugo > > <pre> > BIP: To be determined > Layer: Applications > Title: Bitcoin Secure Multisig Setup (BSMS) > Author: Hugo Nguyen <hugo@nunchuk•io>, Peter Gray <peter@coinkite•com>, Marko Bencun <marko@shiftcrypto•ch>, Aaron Chen <aarondongchen@gmail•com>, Rodolfo Novak <rodolfo@coinkite•com> > Comments-Summary: No comments yet. > Comments-URI: > Status: Proposed > Type: Standards Track > Created: 2020-11-10 > License: BSD-2-Clause > </pre> > > ==Introduction== > > ===Abstract=== > > This document proposes a mechanism to set up multisig wallets securely. > > ===Copyright=== > > This BIP is licensed under the 2-clause BSD license. > > ===Motivation=== > > The Bitcoin multisig experience has been greatly streamlined under [https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki BIP-0174 (Partially Signed Bitcoin Transaction)]. However, what is still missing is a standardized process for setting up multisig wallets securely across different vendors. > > There are a number of concerns when it comes to setting up a multisig wallet: > > # Whether the multisig configuration, such as Signer membership, script type, derivation paths and number of signatures required, is correct and not tampered with. > # Whether Signer persists the multisig configuration in their respective storage, and under what format. > # Whether Signer's storage is tamper-proof. > # Whether Signer subsequently uses the multisig configuration to generate and verify receive and change addresses. > > An attacker who can modify the multisig configuration can steal or hold funds to ransom by duping the user into sending funds to the wrong address. > > This proposal seeks to address concerns #1 and #2: to mitigate the risk of tampering during the initial setup phase, and to define an interoperable multisig configuration format. > > Concerns #3 and #4 should be handled by Signers and is out of scope of this proposal. > > ==Specification== > > ===Prerequisites=== > This proposal assumes the parties in the multisig support [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32], [https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md the descriptor language] and encryption. > > ==Roles== > ===Coordinator=== > > The Coordinator initiates the multisig setup. The Coordinator determines what type of multisig is used and how many members and signatures are needed. If encryption is enabled, the Coordinator generates a secret token, to be shared among the parties for secure communication. The Coordinator gathers information from the Signers to generate a descriptor record. The Coordinator distributes the descriptor record back to the Signers. > > ===Signer=== > > The Signer is a participating member in the multisig. Its responsibilities include providing its XPUB to the Coordinator, verifying that its XPUB is included in the descriptor record and persisting the descriptor record in its storage. > > ==Setup Process== > > ===Round 1=== > > ====Coordinator==== > > * The Coordinator creates a multisig wallet creation session. The Coordinator determines the type of multisig script used and the signing configuration (<tt>M</tt> and <tt>N</tt>). > * If encryption is enabled, the Coordinator also generates a secret token, hereby denoted <tt>TOKEN</tt>. > * TOKEN is in ASCII format and must have a minimum of 8 characters. TOKEN should expire after some time period determined by the Coordinator, e.g., 24 hours. > * TOKEN acts as an encryption key among the parties. The method of encryption is AES, CTR mode. The encryption key can be calculated by performing a double hash operation on the TOKEN: <tt>ENCRYPTION_KEY = SHA256(SHA256(TOKEN))</tt>. > * A TOKEN value of <tt>-1</tt> means that encryption is disabled and all the encryption/decryption steps below can be skipped. > * The Coordinator shares the TOKEN with all participating Signers over a secure channel. > > ====Signer==== > > * The Signer generates a key record by prompting the user for the TOKEN and a derivation path. > * The first line in the record must be the <tt>TOKEN</tt>. If encryption is disabled, set the TOKEN to -1. The second line must be the <tt>KEY</tt>, whereas KEY is an XPUB. KEY must include key origin information and written in the descriptor-defined format, i.e.: <tt>[{master key fingerprint}/{derivation path}]{XPUB}</tt>. The third line must be a <tt>SIG</tt>, whereas SIG is the signature generated by using the corresponding private key to sign the first two lines. Finally, the Signer encrypts the entire record with ENCRYPTION_KEY. > > ===Round 2=== > > ====Coordinator==== > > * The Coordinator gathers key records from all participating Signers. Abort the setup if TOKEN has expired. > * For each key record, the Coordinator decrypts it using ENCRYPTION_KEY. The Coordinator verifies that the included SIG is valid given the KEY. > * If all key records look good, the Coordinator generates a descriptor record, which is simply the descriptor string plus a <tt>CHECKSUM</tt>, all in one line. The CHECKSUM has BECH32 encoding and is described at [https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums]. The Coordinator encrypts this descriptor record with ENCRYPTION_KEY. > * The Coordinator sends the encrypted descriptor record to all participating Signers. > > ====Signer==== > > * The Signer imports the descriptor record, decrypts it by prompting the user for TOKEN. > * The Signer calculates and verifies the descriptor’s CHECKSUM. Abort the setup if the CHECKSUM is incorrect. > * The Signer checks whether one of the KEYs in the descriptor belongs to it, using path and fingerprint information included in the descriptor. The check must perform an exact match on the KEYs, and not using shortcuts such as matching fingerprints (which is trivial to spoof). Abort the setup if it doesn’t detect its own KEY. > * For confirmation, the Signer must display to the user the descriptor's CHECKSUM, plus other configurations, such as M and N. The total number of Signers, N, is important to prevent a KEY insertion attack. All participating Signers should be able to display the same confirmation. > * If all checks pass, the Signer persists the descriptor record in its storage. The Signer should subsequently use the descriptor to generate and verify receive and change addresses. > > This completes the setup. > > ==QR Codes== > For signers that use QR codes to transmit data, key and descriptor records can be converted to QR codes, following [https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md the BCR standard]. > > ==Security== > > This proposal introduce two layers of protection. The first one is a temporary, secret token, used to encrypt the two rounds of communication between the Signers and the Coordinator. The second one is through the descriptor checksum and visual inspection of the descriptor itself. > > The token is only needed during the setup phase, and can be safely thrown away afterwards. The token does not guarantee that the Signer membership set is not modified, since that depends on the overall security of all parties in the setup, but it can make it significantly harder for an attacker to do so. > > There are three ways an attacker can modify the membership set: by changing an existing member, by removing an existing member, or by adding a new member. > > For the first two methods, one of the Signers will be able to detect that its membership has been changed or removed, and reject the final descriptor. Thus, it is vital that all participating Signers check that their membership is intact in the descriptor. Even one Signer failing to check for its membership means that the setup could be compromised. > > For the third type of attack, the descriptor checksum and visual inspection of the descriptor itself are the only way to guard against malicious members from being inserted into the set. > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists•linuxfoundation•org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
Hi Sjors,
Thanks for your comments.
Quoted text (1 line)
>Chicken-egg problem
I agree with Hugo's detailed response here.
Quoted text (1 line)
>Losing multisig setup context (in the event of a fire where you only recover your steel engraved mnemonic(s), but no longer have the wallet descriptors.)
Devices need to persist the descriptor, if they currently can't, they don't comply with this standard and they can't be used securely for multisig. There's no reasons the master seed and descriptor both can't be backed up outside of each device. I can't see a scenario where it would be possible to recover only the seed. (I don't know yet how Core will decide how to best backup this info, seeing as BIP39 was rejected).
Quoted text (1 line)
>BIP48
I agree with Hugo that BIP48 is redundant with descriptors, please see https://github.com/bitcoin/bips/pull/1089 for a proposed updated hierarchy for multisignature wallets.
Quoted text (1 line)
>An encryption convention for the descriptor data
I understand this concern. Like you mentioned previously, I too often set up multisignature wallets for clients where they are actually owned by the single party. A concern is that while the backup location owners cannot spend (due to the M-of-N restriction), they can view the wallet balance/history. As Hugo mentioned, you can apply any encryption you want after the setup, so a solution may be to use Shamir Secret Sharing (Blockchain Commons has done a lot of work on that here: https://github.com/BlockchainCommons/Airgapped-Wallet-Community/discussions/37#discussioncomment-287993)
Quoted text (1 line)
>Plain text vs binary
I too favor plain text
Robert Spigler Personal Fingerprint: BF0D 3C08 A439 5AC6 11C1 5395 B70B 4A77 F850 548F
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Friday, April 9, 2021 11:33 AM, Sjors Provoost via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (15 lines)
> Thanks for the detailed response. Just 1 thing I needed to clarify: > >>> To the list of concerns at the top of the BIP, I would add one: losing multisig setup context. E.g. in the event of a fire where you only recover your steel engraved mnemonic(s), but no longer have the wallet descriptors. >> >> Good point. >> >>> If you still have all devices and know (or guess) the threshold then BIP48 and sorted_multi descriptors will save you. But if you have a 2-of-3 setup and lost 1 device then without the metadata your coins are lost. In a future with musig(?) and miniscript increasingly the setup data is just as critical as the seeds. >> >> How so? Each signer device should ideally have a copy of the multisig configuration. If you lose 1 device in a 2-of-3, you can still spend from the wallet? Unless I'm missing something here. > > I was thinking about a scenario where all devices are destroyed. All you have left are the mnemonics. But indeed if at least one of your devices is still intact AND it has the configuration, you're also good. > > But there are plenty of devices out there that can't do this. Those devices can still be useful, even if they can't fully check everything. > > Sjors
Hi Hugo,
I appreciate the effort you and everyone else is making to improve multisig in bitcoin!
I like that this BIP gets rid of SLIP132 version bytes, as those have been de-facto deprecated in favor of output descriptors for some time. Having a standard for how to communicate descriptor records (BSMS 1.0) also seems like a nice positive.
The most commonly raised issues from [the 10x security guide](https://btcguide.github.io/) are about how to properly verify that all hardware wallets are participants in the user's multisig quorum (and with the correct m-of-n). This shows up in two big ways:
- The O(n^2) xpub validation problem creates a bad UX and is hard for non-advanced users. - The risk for stateless hardware wallets (like Trezor) to have their xpubs swapped out by a compromised Coordinator.
Unfortunately, this BIP does not improve either of these issues, while adding considerable complexity.
1. O(n^2) Xpub Validation
The proposed use of an output descriptor checksum has an obvious 40-bit MITM collision attack. A compromised Coordinator could trick a Signer into displaying an attacker's receive address, despite a correctly functioning Signers and the user properly validating the checksum ([github link](https://github.com/nunchuk-io/bips/pull/1/#issuecomment-801629857)).
Using a checksum with much higher entropy would reduce xpub validation to O(n) and create a very nice UX for signers. This would be a huge win for multisig! Instead, the recommended solution from the BIP is to validate all the key records manually, which is how multisig is currently done and what we desperately want to move away from. With a proper checksum, there’s no reason for a user to ever see an xpub.
Users should not be shown a checksum and asked to validate it in meatspace (across Signers) if an attacker’s address could still be substituted! Validating a single address across devices does solve this problem, but if you’re going to validate an address there’s no reason to display the checksum at all. However, validating an address is confusing to non-experts:
- Is it a wallet ID or a bitcoin address?
- Am I supposed to send funds to this address?
If creating a new checksum standard for the descriptor record is undesirable, we could use a child address (from an unhardened BIP32 path) and encode that in some way for end-users to verify it matches across all Signers. It would be strongly preferable for the encoding to be an unambiguously different format from a bitcoin address / BIP39 seed phrase, so that it’s clear it’s just a wallet ID. One non-ideal but simple solution is to use a hash function (i.e. dsha256) to calculate the digest of the child address, and display this in hexadecimal format. While hexadecimal is non-ideal for manual verification, it is already trivial for any bitcoin library to perform these steps.
2. Allow Support for Stateless Wallets
The current BIP states:
"If all checks pass, the Signer must persist the descriptor record in its storage."
While persistence has a lot of benefits, it is not a feature of the most sold multisig hardware wallet: Trezor. A simple solution here is to have each Signer sign the entire descriptor record at the end of round 2, not just its own key record in round 1. Then the data can be stored anywhere (including on the Signer itself) and played back to each Signer for validation when needed. The end-user would have no idea this was happening, but the device could refuse to display information it hasn’t fully validated (or at least add a warning message). Even a device with persistent storage would be better served using a signature, so that an evil maid couldn't tamper with the device (say in the no-encryption case for simplicity).
This existing vulnerability in stateless wallets is particularly bad for hosted multisig services like Casa/Unchained, where the service might control m-1 keys. It’s far easier for a hosted service to potentially trick non-expert users into displaying an attacker's receive address on their stateless Signer.
For example, assume the user is doing 2-of-3 multisig, where the Coordinator (service) controls 1 key. Here is how the Coordinator could trick their end-users:
- Coordinator swaps out 1 of the end-user’s xpubs, going from a 2-of-3 where the end-user has 2 seeds to a 2-of-3 where the Coordinator has 2 seeds.
- The end-user logs into the service to get a new receive address, and the service (Coordinator) displays malicious receive address X (as part of a 2-of-3).
- The end user connects stateless Signer 1 to the service (Coordinator), which under-the-hood gives stateless Signer 1 proof that it is included in this 2-of-3. Stateless singer 1 displays malicious receive address X!
- The end-user doesn't verify the address on Signer 2, as many users unfortunately don't -- perhaps it is in a far away location and the end-user (incorrectly) thinks that it’s already been validated in 2 places -- and makes a large deposit to receive address X. These funds now belong to the attacker and can be swept at any time!
If stateless Signer 1 required a signature to be replayed at step 3, stateless Signer 1 would refuse to display malicious receive address X (or at a minimum warn the end-user that it did not have enough info to properly validate the address).
This is also a concern for self-hosted multisig, I just used the hosted services as the best example.
It's also not just Trezor that is stateless. For example, I wrote [a simple CLI software multisig wallet as part of the buidl library](https://twitter.com/mflaxman/status/1321503036724989952) to be used mostly for emergency recovery. At 800 lines of code, it's too simple/minimal to touch the file system.
BIP39
While unrelated, the use of BIP39 words for session tokens seems like a big mistake, as end-users have learned over years that BIP39 words are for private key material. A small percent of users may backup their token BIP39 mnemonic and not their seed phrase BIP39 mnemonic! My suggestion is to just stick with the other two Token options: decimal and hex.
Conclusion
The main purpose/benefit of the BIP seems to be the encryption protocol. I wouldn't have strong objections if the BIP were simply renamed Bitcoin Multisig Encryption, as that more accurately reflects what it does. That said, I think this BIP is missing out on a real opportunity to improve security in setting up a multisig scheme, and if adopted in the current form will negatively impact multisig adoption.
I can't support this BIP in the current form, but I'd be happy to submit a PR if it's helpful.
Best,
Michael
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Monday, April 5, 2021 2:02 AM, Hugo Nguyen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (446 lines)
> Hi all, > > Please find below the complete draft of the Bitcoin Secure Multisig Setup (BSMS) BIP. The spec has gone through a number of important updates in the last month or so. Thanks everyone who has participated in the review process. > > As a PR: https://github.com/bitcoin/bips/pull/1097 > > A few notes: > * PBKDF2-SHA512 was chosen instead of PBKDF2-SHA256 for the key derivation function, due to widespread existing hardware support for PBKDF2-SHA512 > * Only one descriptor is stored in the multisig configuration - this simplifies wallet setup and recovery > (For the full review and relevant discussions, please check out https://github.com/nunchuk-io/bips/pull/1). > > Best, > Hugo > > <pre> > BIP: To be determined > Layer: Applications > Title: Bitcoin Secure Multisig Setup (BSMS) > Author: Hugo Nguyen <hugo at > nunchuk.io >>, Peter Gray <peter at > coinkite.com >>, Marko Bencun <marko at > shiftcrypto.ch >>, Aaron Chen <aarondongchen at > gmail.com >>, Rodolfo Novak <rodolfo at > coinkite.com >> > Comments-Summary: No comments yet. > Comments-URI: > Status: Proposed > Type: Standards Track > Created: 2020-11-10 > License: BSD-2-Clause > </pre> > > ==Introduction== > > ===Abstract=== > > This document proposes a mechanism to set up multisig wallets securely. > > ===Copyright=== > > This BIP is licensed under the 2-clause BSD license. > > ===Motivation=== > > The Bitcoin multisig experience has been greatly streamlined under [ > https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki > BIP-0174 > (Partially Signed Bitcoin Transaction)]. However, what is still missing is a standardized process for setting up multisig wallets securely across different vendors. > > There are a number of concerns when it comes to setting up a multisig wallet: > > # Whether the multisig configuration, such as Signer membership, script type, derivation paths and number of signatures required, is correct and not tampered with. > # Whether the keys or the multisig configuration are leaked during the setup. > # Whether the Signer persists the multisig configuration in their respective storage, and under what format. > # Whether the Signer's storage is tamper-proof. > # Whether the Signer subsequently uses the multisig configuration to generate and verify receive and change addresses. > > An attacker who can modify the multisig configuration can steal or hold funds for ransom by duping the user into sending funds to the wrong address. An attacker who cannot modify the configuration but can learn about the keys and/or the configuration can monitor transactions in the wallet, resulting in loss of privacy. > > This proposal seeks to address concerns #1, #2 and #3: to mitigate the risk of tampering during the initial setup phase, and to define an interoperable multisig configuration format. > > Concerns #4 and #5 should be handled by Signers and are out of scope of this proposal. > > ==Specification== > > ===Prerequisites=== > This proposal assumes the parties in the multisig support [ > https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki > BIP-0032], [ > https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki > BIP-0322], [ > https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md > the descriptor language] and [ > https://tools.ietf.org/html/rfc3686 > AES encryption]. > > ===File Extension=== > All descriptor and key records should have a <tt>.bsms</tt> file extension. Encrypted data should have a <tt>.dat</tt> extension. > > ===Roles=== > ====Coordinator==== > > The Coordinator initiates the multisig setup. The Coordinator determines what type of multisig is used and the exact policy script. If encryption is enabled, the Coordinator also distributes a shared secret or shared secrets to the parties involved for secure communication. The Coordinator gathers information from the Signers to generate a descriptor record. The Coordinator distributes the descriptor record back to the Signers. > > ====Signer==== > > The Signer is a participating member in the multisig. Its responsibilities include providing its key record -- which contains an Extended Public Key (XPUB) -- to the Coordinator, verifying that its XPUB is included in the descriptor record and persisting the descriptor record in its storage. > > ===Setup Process=== > > ====Round 1==== > > =====Coordinator===== > > * The Coordinator creates a new multisig wallet creation session. The Coordinator constructs the multisig script and its policy parameters, such as the required number of signatures and the total number of Signers (<tt>M</tt> and <tt>N</tt>). > * The session should expire after some time period determined by the Coordinator, e.g., 24 hours. The timeout allows the encryption key to have lower entropy. > * If encryption is enabled, the Coordinator distributes a secret <tt>TOKEN</tt> to each Signer over a secure channel. The Signer can use the <tt>TOKEN</tt> to derive an <tt>ENCRYPTION_KEY</tt>. Refer to the Encryption section below for details on the <tt>TOKEN</tt>, the key derivation function and the encryption scheme. Depending on the use case, the Coordinator can decide whether to share one common <tt>TOKEN</tt> for all Signers, or to have one per Signer. > * If encryption is disabled, the <tt>TOKEN</tt> is set to <tt>0</tt>, and all the encryption/decryption steps below can be skipped. > > =====Signer===== > > * The Signer initiates the multisig wallet creation session by setting the <tt>TOKEN</tt>. The Signer derives an <tt>ENCRYPTION_KEY</tt> from the <tt>TOKEN</tt>. The Signer can keep the session open until a different value for the <tt>TOKEN</tt> is set. > * The Signer generates a key record by prompting the user for a multisig derivation path and retrieves the XPUB at that derivation path. Alternatively, the Signer can choose a path on behalf of the user. If the Signer chooses the path, it should try to avoid reusing XPUBs for different wallets. > * The first line in the record must be the specification version (<tt>BSMS 1.0</tt> as of this writing). The second line must be the hex-encoded <tt>TOKEN</tt>. The third line must be the <tt>KEY</tt>. The <tt>KEY</tt> is an XPUB plus its key origin information, written in the descriptor-defined format, i.e.: <tt>[{master key fingerprint}/{derivation path}]{XPUB}</tt>. The fourth line is a text description of the key, 80 characters maximum. The fifth line must be a <tt>SIG</tt>, whereas <tt>SIG</tt> is the signature generated by using the private key associated with the XPUB to sign the first four lines. The signature should follow [ > https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki > BIP-0322], legacy format accepted. > * The Signer calculates the Message Authentication Code (<tt>MAC</tt>) for the record. The first 16 bytes of the <tt>MAC</tt> serves as the Initialization Vector (<tt>IV</tt>) for the encryption. > * The Signer encrypts the key record with the <tt>ENCRYPTION_KEY</tt> and <tt>IV</tt>. > * The Signer encodes the <tt>MAC</tt> and the ciphertext into hexadecimal format, then concatenates the results: <tt>(MAC || ciphertext)</tt>. > > ====Round 2==== > > =====Coordinator===== > > * The Coordinator gathers key records from all participating Signers. The Coordinator verifies that there are exactly <tt>N</tt> unique key records before the wallet setup session expires. > * For each key record, the Coordinator extracts the <tt>MAC</tt> from the data, sets <tt>IV</tt> to the first 16 bytes of the <tt>MAC</tt>, then decrypts the ciphertext using the <tt>ENCRYPTION_KEY</tt> and <tt>IV</tt>. > * The Coordinator verifies that the included <tt>MAC</tt> is valid given the plaintext. > * The Coordinator verifies that the key records have compatible specification versions. > * The Coordinator verifies that the included <tt>SIG</tt> is valid given the <tt>KEY</tt>. > * If all key records look good, the Coordinator fills in all necessary information to generate a descriptor record. > * The first line in the descriptor record must be the specification version (<tt>BSMS 1.0</tt> as of this writing). The second line must be a comma-separated list of accepted derivation paths that the Signers can use to generate addresses from the included XPUBs. The paths must start with <tt>/</tt> and use non-hardened derivation. For example, <tt>/0/*</tt> and <tt>/1/*</tt> are some common paths. If there are no restrictions, it must say <tt>No path restrictions</tt>. The third line must be the descriptor string plus a <tt>CHECKSUM</tt>, all in one line. The <tt>CHECKSUM</tt> has [ > https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums > BECH32 encoding]. > * The Coordinator calculates the <tt>MAC</tt> for the record. The first 16 bytes of the <tt>MAC</tt> serves as the <tt>IV</tt> for the encryption.. > * The Coordinator encrypts the descriptor record with the <tt>ENCRYPTION_KEY</tt> and <tt>IV</tt>. > * The Coordinator encodes the <tt>MAC</tt> and the ciphertext into hexadecimal format, then concatenates the results: <tt>(MAC || ciphertext)</tt>. > * The Coordinator sends the encrypted descriptor record to all participating Signers. > > =====Signer===== > > * The Signer imports the descriptor record. > * The Signer extracts the <tt>MAC</tt> from the data, sets <tt>IV</tt> to the first 16 bytes of the <tt>MAC</tt>, then decrypts the ciphertext using the <tt>ENCRYPTION_KEY</tt> (derived from the open session) and <tt>IV</tt>. > * The Signer verifies that the included <tt>MAC</tt> is valid given the plaintext. > * The Signer verifies that it can support the included specification version. > * The Signer verifies that it is compatible with the derivation path restrictions. > * The Signer verifies the descriptor’s <tt>CHECKSUM</tt>. > * The Signer verifies that it can support the descriptor. > * The Signer checks that its <tt>KEY</tt> is included in the descriptor, using path and fingerprint information provided. The check must perform an exact match on the <tt>KEY</tt>s and not using shortcuts such as matching fingerprints, which is trivial to spoof. > * For confirmation, the Signer must display to the user the <tt>CHECKSUM</tt>, the derivation path restrictions and the policy parameters, such as <tt>M</tt>, <tt>N</tt> and the position(s) of its own XPUB in the policy script. The total number of Signers, <tt>N</tt>, is important to prevent a <tt>KEY</tt> insertion attack. The position is important for scripts where key order matters. When applicable, all positions of the XPUB must be displayed. The full descriptor must also be available for review upon user request. > * When possible, the Signer should also show a preview of the first address(es) of the wallet. > * Parties must check with each other that all Signers have verified the descriptor and has the same confirmation (except for the key positions). > * If all checks pass, the Signer must persist the descriptor record in its storage. > > This completes the setup. > > ===Encryption=== > > ====The Token==== > We define three modes of encryption. > > # <tt>NO_ENCRYPTION</tt> : the <tt>TOKEN</tt> is set to <tt>0</tt>. Encryption is disabled. > # <tt>STANDARD</tt> : the <tt>TOKEN</tt> is a 64-bit nonce. > # <tt>EXTENDED</tt> : the <tt>TOKEN</tt> is a 96-bit nonce. > > The <tt>TOKEN</tt> can be converted to one of these formats: > * A decimal number (recommended). The number must not exceed the maximum value of the nonce. > * A mnemonic phrase using [ > https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki > BIP-0039] word list (6 words in <tt>STANDARD</tt> mode; 9 words in <tt>EXTENDED</tt> mode). > * A QR code. > * Other formats. > > The flexibility in the data format allows each Signer to customize the User Experience based on its respective capabilities. > > ====Key Derivation==== > The key derivation function is [ > https://tools.ietf.org/html/rfc2898 > PBKDF2], with PRF = SHA512. Specifically: > > <tt>DKey = PBKDF2(PRF, Password, Salt, c, dkLen)</tt> > > Whereas: > > * PRF = SHA512 > * Password = "No SPOF" > * Salt = <tt>TOKEN</tt> > * c = 2048 > * dkLen = 256 > * DKey = Derived <tt>ENCRYPTION_KEY</tt> > > ====Encryption Scheme==== > The encryption scheme is [ > https://tools.ietf.org/html/rfc3686 > AES-256-CTR]. > > <tt>MAC = HMAC-SHA256(HMAC_Key, hex-encoded TOKEN || Data)</tt> > > <tt>IV = First 16 bytes of MAC</tt> > > <tt>Ciphertext = AES-256-CTR-Encrypt(Plaintext, DKey, IV)</tt> > > <tt>Plaintext = AES-256-CTR-Decrypt(Ciphertext, DKey, IV)</tt> > > Whereas: > * DKey = <tt>ENCRYPTION_KEY</tt> > * HMAC_Key = SHA256(<tt>ENCRYPTION_KEY</tt>) > * Data = the plaintext, e.g. the entire key record in round 1 and the entire descriptor record in round 2 > > The <tt>MAC</tt> is to be sent along with the key and descriptor record, as specified above. Because it is a <tt>MAC</tt> over the entire plaintext, this is essentially an [ > https://en.wikipedia.org/wiki/Authenticated_encryption#Encrypt-and-MAC_(E&M) > Encrypt-and-MAC] form of authenticated encryption. > > ==QR Codes== > For signers that use QR codes to transmit data, key and descriptor records can be converted to QR codes, following [ > https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md > the BCR standard]. > > Also refer to [ > https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-015-account.md > UR Type Definition for BIP44 Accounts] and [ > https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-010-output-desc.md > UR Type Definition for Bitcoin Output Descriptors] for more details. > > ==Security== > > This proposal introduces two layers of protection. The first one is a temporary, secret <tt>TOKEN</tt>. The second one is the descriptor <tt>CHECKSUM</tt>. > > The <tt>TOKEN</tt> is used to encrypt the two rounds of communication between the Signer and the Coordinator. A <tt>MAC</tt> is also generated from the <tt>TOKEN</tt> and plaintext to authenticate the data being exchanged. The <tt>TOKEN</tt> is only needed during the setup phase, and can be safely discarded afterwards. > > The descriptor <tt>CHECKSUM</tt>, on the other hand, can be used to verify the integrity of the multisig configuration. An attacker who tampers with the multisig configuration must also change the descriptor <tt>CHECKSUM</tt>. Parties must check with each other that all Signers have the same <tt>CHECKSUM</tt>, along with the policy parameters, to reduce the chance of tampering. The <tt>CHECKSUM</tt> must be persisted along with the descriptor in each Signer’s storage. > > The <tt>TOKEN</tt> and the <tt>CHECKSUM</tt> can’t guarantee complete protection, since that depends on the overall security of all parties in the setup, but they can make it significantly harder for an attacker to tamper with the multisig configuration. > > ==Privacy== > Encryption helps improve the privacy of the wallet by avoiding sharing XPUBs and descriptors in plaintext. > > If the parties wish to have stronger privacy, it is recommended to use a higher number of bits for the <tt>TOKEN</tt>, and to completely erase knowledge of the <tt>TOKEN</tt> after the multisig wallet has been set up. > > ==Test Vectors== > > ===Mode: <tt>NO_ENCRYPTION</tt>=== > ====ROUND 1==== > * Coordinator > ** M-of-N: 2/2 > ** ADDRESS_TYPE: NATIVE_SEGWIT > ** TOKEN: 0 > > * Signer 1 > ** MASTER_KEY_FINGERPRINT: 539f3d89 > ** PRIVATE_KEY (m/48'/0'/0'/2'): KyoXqiwiz6qm21BSYebiZFfNF7obkhiJW6TdPMZTQQMF4kZtfD78 > ** XPUB (m/48'/0'/0'/2'): xpub6ETerig7tq89mtaD8Gau2xRWxouRMBy6XHqciA8GZzC2dJv3w6FxfgoegH4b2qYF4oG6VBrhpLrauPs5E1q58GLCnhKp6g9QsV9ZA7J5JNa > ** Legacy signature > ** <tt>signer_1_key.bsms</tt>: > <pre>BSMS 1.0 > 00 > [539f3d89/48'/0'/0'/2']xpub6ETerig7tq89mtaD8Gau2xRWxouRMBy6XHqciA8GZzC2dJv3w6FxfgoegH4b2qYF4oG6VBrhpLrauPs5E1q58GLCnhKp6g9QsV9ZA7J5JNa > Signer 1 key > IPXsnNSZb8M6H4fAWtpjAc75hyHHd89fskpM5o7qFg+mPDzEPc1k2mjuIpVIIzaCe45FwPfAAa91RaStfC5Sak0=</pre> > > * Signer 2 > ** MASTER_KEY_FINGERPRINT: f8b12aa6 > ** PRIVATE_KEY (m/48'/0'/0'/2'): L1zht7muKnUYFMdzC3jwXd78u8tGoKr46AXGh4waF9nphUYWq7ow > ** XPUB (m/48'/0'/0'/2'): xpub6EWPNhGSX86SN4J2DrBUaQ826o6V4egHqAJZUDJqnsthv9CcjBZV79u68M3YZkuTJnJBXfCrHuJy97fkVurntwgt3V7Ms5hXpJV2vS8fQZM > ** Legacy signature > ** <tt>signer_2_key.bsms</tt>: > <pre>BSMS 1.0 > 00 > [f8b12aa6/48'/0'/0'/2']xpub6EWPNhGSX86SN4J2DrBUaQ826o6V4egHqAJZUDJqnsthv9CcjBZV79u68M3YZkuTJnJBXfCrHuJy97fkVurntwgt3V7Ms5hXpJV2vS8fQZM > Signer 2 key > H38+lp9iaesBeCN05BDTH/SnmarlH6+X+Kmw1pgCk+c1Pc1evYIdBag9Nc0nsKhvPtfEbRt9r/qsUVZ5onCtBTc=</pre> > > ====ROUND 2==== > * Coordinator > ** <tt>my_multisig_wallet.bsms</tt>: > <pre>BSMS 1.0 > /0/*,/1/* > wsh(sortedmulti(2,[539f3d89/48'/0'/0'/2']xpub6ETerig7tq89mtaD8Gau2xRWxouRMBy6XHqciA8GZzC2dJv3w6FxfgoegH4b2qYF4oG6VBrhpLrauPs5E1q58GLCnhKp6g9QsV9ZA7J5JNa/*,[f8b12aa6/48'/0'/0'/2']xpub6EWPNhGSX86SN4J2DrBUaQ826o6V4egHqAJZUDJqnsthv9CcjBZV79u68M3YZkuTJnJBXfCrHuJy97fkVurntwgt3V7Ms5hXpJV2vS8fQZM/*))#fntxdj7p</pre> > > ===Mode: <tt>STANDARD</tt> Encryption=== > ====ROUND 1==== > * Coordinator > ** M-of-N: 2/2 > ** ADDRESS_TYPE: NATIVE_SEGWIT > ** TOKEN (hex): 1ed4ba49e96336b8 > *** TOKEN (decimal): 2221605342811469496 > *** TOKEN (mnemonic): burst place mystery spot cricket foster > ** ENCRYPTION_KEY (hex): 72185a0e25b4efc5d6ac0f8ed32b0165199100e32385040e3a48eb30164bf492 > > * Signer 1 > ** MASTER_KEY_FINGERPRINT: 98d79e95 > ** PRIVATE_KEY (m/48'/0'/0'/2'): KydC7hZFtWe56oQUAw14HvQ3gKeKVd3m8frFgVMxUqpuhKHvcmm3 > ** XPUB (m/48'/0'/0'/2'): xpub6DvvwHS5pd1D36xt4YBGJvtdThWXfn8L9qRj9DbFMExMeP6eBE6Aw9WyBC7XUQwiPPDFurirewsKZpYv68yTV5RBy7SZmw45QEkaLka5BCt > ** Legacy signature > ** <tt>signer_1_key.bsms</tt>: > <pre>BSMS 1.0 > 1ed4ba49e96336b8 > [98d79e95/48'/0'/0'/2']xpub6DvvwHS5pd1D36xt4YBGJvtdThWXfn8L9qRj9DbFMExMeP6eBE6Aw9WyBC7XUQwiPPDFurirewsKZpYv68yTV5RBy7SZmw45QEkaLka5BCt > Signer 1 key > HxtPoP0DrQSac/7ypcwC07R2s6jjpXR6Li2Q92zXj/FSIMQcV5yOU0/ONsDgHXamq0gD5DfPbvuVCp9ZJubclV4=</pre> > > * Signer 1 encryption > ** HMAC_KEY (hex): 4dab3988cbc683ad7a8c93d43f9b11a78b63a93d5e33ea19c603f4b7b87ac284 > ** MAC (hex): afe99e92f0eadc3308eb990045e90a4f54e9f59d22aae5034ac3d866d29c508d > ** IV (hex) : afe99e92f0eadc3308eb990045e90a4f > ** CIPHERTEXT (hex): 214ec9a861a238ba7f0412305a97a6e0faa332be15af09127e131d669e5d55d73891580a5808cea5d2bf39f43496d3c0f8236eff3854fcc7446daf9d2b58fd40d97ce3b1745de2959e29767039b99969821400eca0c3517fae56d2d24d5235a3430af1ed894b68681d706cce7c75adf35d8580603aa302bc01fef06d0336a37f19dd46100baa9e4eabd8796a810e13941ad0980c126ad55d6a4bbef11a7bf893b7d2ed8fb0d8324c4c9b512d4d1e75096c63511e15018fc832816b5639d58fc28c60c049487d04bd5a6cb32aa1381d0809660d54376b9f63325c18cfd1ac5024088e74cb703fe165972cc4485abb1feefe92a0b4ea297fe2f4f7416eeee1efc9b942540931ef > ** <tt>signer_1_key.dat</tt>: <pre>afe99e92f0eadc3308eb990045e90a4f54e9f59d22aae5034ac3d866d29c508d214ec9a861a238ba7f0412305a97a6e0faa332be15af09127e131d669e5d55d73891580a5808cea5d2bf39f43496d3c0f8236eff3854fcc7446daf9d2b58fd40d97ce3b1745de2959e29767039b99969821400eca0c3517fae56d2d24d5235a3430af1ed894b68681d706cce7c75adf35d8580603aa302bc01fef06d0336a37f19dd46100baa9e4eabd8796a810e13941ad0980c126ad55d6a4bbef11a7bf893b7d2ed8fb0d8324c4c9b512d4d1e75096c63511e15018fc832816b5639d58fc28c60c049487d04bd5a6cb32aa1381d0809660d54376b9f63325c18cfd1ac5024088e74cb703fe165972cc4485abb1feefe92a0b4ea297fe2f4f7416eeee1efc9b942540931ef</pre> > > * Signer 2 > ** MASTER_KEY_FINGERPRINT: 3e94b5a1 > ** PRIVATE_KEY (m/48'/0'/0'/2'): KyPh5XYjExjNHPiBjYhp8iAntAehrDziiwRv7y9Ln6eK9QU2xP55 > ** XPUB (m/48'/0'/0'/2'): xpub6E1W1DUYY29V2b8czCcpi36GG2uD33B11vwNopgTZwsVyfgAkA4kPCqLP5R4YzaRvzW17CQrDkgmDQbA848AdkR7W18nNvMKXzzCBSnZP9c > ** Legacy signature > ** <tt>signer_2_key.bsms</tt>: > <pre>BSMS 1.0 > 1ed4ba49e96336b8 > [3e94b5a1/48'/0'/0'/2']xpub6E1W1DUYY29V2b8czCcpi36GG2uD33B11vwNopgTZwsVyfgAkA4kPCqLP5R4YzaRvzW17CQrDkgmDQbA848AdkR7W18nNvMKXzzCBSnZP9c > Signer 2 key > ILR49QLy9+xkMS11TIXJRSMgOQOzGbAaooq4/ZRcd8VgM6j5upJMI0mjJHseQOMYSGk8FqjXZbMvBGyiX9wdutM=</pre> > > * Signer 2 encryption > ** HMAC_KEY (hex): 4dab3988cbc683ad7a8c93d43f9b11a78b63a93d5e33ea19c603f4b7b87ac284 > ** MAC (hex): 5c7cb2ac407cd60b1f2b86ef46077d3a312b6ce921df2a141347e8bf1e5c6573 > ** IV (hex) : 5c7cb2ac407cd60b1f2b86ef46077d3a > ** CIPHERTEXT (hex): f23e6c76ff45d308dea6014030a274127ad437228f1d5ec2431d2ea9e3cedd5b0a207a9efa6f926d5420205003f3cb9c4b82b2d595180e62a173a2e5aa0322de48a70a873f641bdae1764e6b1667c241e0fe03a4ccdc3fe0cfa5f75b239d6497c3b69dca17bb685ba70b307d1243836d8fb198ce727cfae4057ee0b4fdcb09f4ba5ae127f49c5de780edb4e40aec96303c8a7b98b1b8e53dd5e07e01d4f3ffd836763209a1f0cbc61adcfdc2951e77528ee7b6e68114c3a4bec38875d285021e68ae8aa913bb1e2e65dd52c649a0e98bfb4e8bab6dd10295c1167a0854ba44f094feb75d2fb00c944f07d4b47114f483df9838459316f3ddbc4a82e6507881931f8e20f5b805 > ** <tt>signer_2_key.dat</tt>: <pre>5c7cb2ac407cd60b1f2b86ef46077d3a312b6ce921df2a141347e8bf1e5c6573f23e6c76ff45d308dea6014030a274127ad437228f1d5ec2431d2ea9e3cedd5b0a207a9efa6f926d5420205003f3cb9c4b82b2d595180e62a173a2e5aa0322de48a70a873f641bdae1764e6b1667c241e0fe03a4ccdc3fe0cfa5f75b239d6497c3b69dca17bb685ba70b307d1243836d8fb198ce727cfae4057ee0b4fdcb09f4ba5ae127f49c5de780edb4e40aec96303c8a7b98b1b8e53dd5e07e01d4f3ffd836763209a1f0cbc61adcfdc2951e77528ee7b6e68114c3a4bec38875d285021e68ae8aa913bb1e2e65dd52c649a0e98bfb4e8bab6dd10295c1167a0854ba44f094feb75d2fb00c944f07d4b47114f483df9838459316f3ddbc4a82e6507881931f8e20f5b805</pre> > > ====ROUND 2==== > *Coordinator > ** <tt>my_multisig_wallet.bsms</tt>: > <pre>BSMS 1.0 > /0/*,/1/* > wsh(sortedmulti(2,[98d79e95/48'/0'/0'/2']xpub6DvvwHS5pd1D36xt4YBGJvtdThWXfn8L9qRj9DbFMExMeP6eBE6Aw9WyBC7XUQwiPPDFurirewsKZpYv68yTV5RBy7SZmw45QEkaLka5BCt/*,[3e94b5a1/48'/0'/0'/2']xpub6E1W1DUYY29V2b8czCcpi36GG2uD33B11vwNopgTZwsVyfgAkA4kPCqLP5R4YzaRvzW17CQrDkgmDQbA848AdkR7W18nNvMKXzzCBSnZP9c/*))#x0lx92qk</pre> > > *Coordinator encryption > ** HMAC_KEY (hex): 4dab3988cbc683ad7a8c93d43f9b11a78b63a93d5e33ea19c603f4b7b87ac284 > ** MAC (hex): df3d06db6c8b8a5f25de202e10ea225df6415d1ed0e36c64cc2be1b7e86c2a38 > ** IV (hex) : df3d06db6c8b8a5f25de202e10ea225d > ** CIPHERTEXT (hex): 2761e6bfe839586b4c90954200bc4ce6d39ef164c5d14997755575d1691ee249ffd20beda526f57a7424907f839c6c2e3ecd46889ede290a2c81de22d3f33a7fa5e55ec95c0e26005c596d0f6346f819823f361f9f9f54d1eae48b325240d66c5888bd5ebab843061dcdd73b675346da982646c83026694d757661d31c2d654fb263c9ab3e874a258bc234c48532f15e9450c982fcf161404746e9f23d25e17b74139cd799983fd0c7a7a0386a823d3789b4578879a764172cc8ef96ab003eee24f6288007d31e2b999aff5a6d30cc524a0111a99730a29cf28ae41dbff6ce21ca6bc1df37074228178048e835584e6e70dba941154d024cd03cb6c56d0bde441ce464aa749de5e814dd30e21b75f62e831ac1f28eda1a7ba7e122076789e284402c8ba85b5a0e864bce220e3c78fa2f465e2bcf6b1d378816319de99f99ce7068 > ** <tt>my_multisig_wallet.dat</tt>: <pre>df3d06db6c8b8a5f25de202e10ea225df6415d1ed0e36c64cc2be1b7e86c2a382761e6bfe839586b4c90954200bc4ce6d39ef164c5d14997755575d1691ee249ffd20beda526f57a7424907f839c6c2e3ecd46889ede290a2c81de22d3f33a7fa5e55ec95c0e26005c596d0f6346f819823f361f9f9f54d1eae48b325240d66c5888bd5ebab843061dcdd73b675346da982646c83026694d757661d31c2d654fb263c9ab3e874a258bc234c48532f15e9450c982fcf161404746e9f23d25e17b74139cd799983fd0c7a7a0386a823d3789b4578879a764172cc8ef96ab003eee24f6288007d31e2b999aff5a6d30cc524a0111a99730a29cf28ae41dbff6ce21ca6bc1df37074228178048e835584e6e70dba941154d024cd03cb6c56d0bde441ce464aa749de5e814dd30e21b75f62e831ac1f28eda1a7ba7e122076789e284402c8ba85b5a0e864bce220e3c78fa2f465e2bcf6b1d378816319de99f99ce7068</pre> > > ===Mode: <tt>EXTENDED</tt> Encryption=== > ====ROUND 1==== > *Coordinator > ** M-of-N: 2/3 > ** ADDRESS_TYPE: NESTED_SEGWIT > ** TOKEN for Signer 1 (hex): 654d63309464afcda558c6aa > *** TOKEN (decimal): 31351541690484562733651510954 > *** TOKEN (mnemonic): grab help slow churn enough traffic nice boat price > *** ENCRYPTION_KEY (hex): 4073adac2351e164b8d68039abd9d4b8e4d07adccfdf73ece6e236d60b107802 > ** TOKEN for Signer 2 (hex): b0344f51d5cb04083d598fa3 > *** TOKEN (decimal): 54532600447720520868878192547 > *** TOKEN (mnemonic): rabbit pen stamp process raccoon advice voice cradle person > *** ENCRYPTION_KEY (hex): 6bae6b670e257d7468c3e90194029dd468a2f39d8b9a3ff187b08209b1d409b6 > ** TOKEN for Signer 3 (hex): 163fd307195982c4c39d50bb > *** TOKEN (decimal): 6885829092987042066541138107 > *** TOKEN (mnemonic): bike write scrub crawl oblige give attack present rookie > *** ENCRYPTION_KEY (hex): c78b94589214b6dc98b337ba4ce54380553ed00a1e5b1955fc540ce3b30d6566 > > * Signer 1 > ** MASTER_KEY_FINGERPRINT: 110dc257 > ** PRIVATE_KEY (m/48'/0'/0'/1'): KzshDDEBhzyiwXHoyE7ZiLegzztEy54AG6Wq8N844LqHSQMHt4Ji > ** XPUB (m/48'/0'/0'/1'): xpub6EPQbDFezXYvVFHqnc8R7QUSE8hTepbyCXU7jJBT4dVm2rQHe1i6isqoj59qhyBiCdKquo6QsgMZNHvEz3BM4cNSszF25siTqLUCznBm8vk > ** Legacy signature > ** <tt>signer_1_key.bsms</tt>: > <pre>BSMS 1.0 > 654d63309464afcda558c6aa > [110dc257/48'/0'/0'/1']xpub6EPQbDFezXYvVFHqnc8R7QUSE8hTepbyCXU7jJBT4dVm2rQHe1i6isqoj59qhyBiCdKquo6QsgMZNHvEz3BM4cNSszF25siTqLUCznBm8vk > Signer 1 key > IDX6xLdM4XjetYPvVfpVBXAfT7oE3tHAOB4blZpbIst8bjJ+LbDeP4tZl4O8utAuys9igXE0G3kaHz1mg/+OU8w=</pre> > > * Signer 1 encryption > ** HMAC_KEY (hex): f43c359a4b3d7b2e01be73c54519b12545ca9a23a86f824aadf577b314a7caa7 > ** MAC (hex): 40b6b43e2f1bc01b748eb242235d7e09fa8a2fd6cebe35784cf3adf81910ec98 > ** IV (hex) : 40b6b43e2f1bc01b748eb242235d7e09 > ** CIPHERTEXT (hex): 0877987764401c27e6c60ed2f1bb89dff1dbc5e8204149f682d53049bffe39553f24af3928aa2f78ac2d04ac5baa0c3ec39aaccf0d258e7bb6659a7b92e92f2c2784a94f4df8e8af2270d9d411bfff2cfb9f71b4e1ac87561c7d2ac57ca86a1f9716d5da7571719d24830fc8d015a0daf04b3742439484488798335357f2eeaa8e2db2ba630f9dffd88236e327ab5bfcfb6e29ee3ef6cc18e0b71c1731465c2351e76b92f7b1bd28ef6eff5414c22aa6c80090fa59b973c22e3044e92dbf3688990a49a42828e52c1e686f1193dcdf7b7118930e01419fe938c6811c58c84c36d692fd52846f998bc328471f1e73c22261791a08cda096ee3ac8b37f31afd0b1d9c335ff9ac67ff230eb0d69f2d7 > ** <tt>signer_1_key.dat</tt>: <pre>40b6b43e2f1bc01b748eb242235d7e09fa8a2fd6cebe35784cf3adf81910ec980877987764401c27e6c60ed2f1bb89dff1dbc5e8204149f682d53049bffe39553f24af3928aa2f78ac2d04ac5baa0c3ec39aaccf0d258e7bb6659a7b92e92f2c2784a94f4df8e8af2270d9d411bfff2cfb9f71b4e1ac87561c7d2ac57ca86a1f9716d5da7571719d24830fc8d015a0daf04b3742439484488798335357f2eeaa8e2db2ba630f9dffd88236e327ab5bfcfb6e29ee3ef6cc18e0b71c1731465c2351e76b92f7b1bd28ef6eff5414c22aa6c80090fa59b973c22e3044e92dbf3688990a49a42828e52c1e686f1193dcdf7b7118930e01419fe938c6811c58c84c36d692fd52846f998bc328471f1e73c22261791a08cda096ee3ac8b37f31afd0b1d9c335ff9ac67ff230eb0d69f2d7</pre> > > * Signer 2 > ** MASTER_KEY_FINGERPRINT: 5c890401 > ** PRIVATE_KEY (m/48'/0'/0'/1'): L41Jnc9CdBtBJd18429MDGcTgP2DNoXaKyyGr271ndTprvrHXDQf > ** XPUB (m/48'/0'/0'/1'): xpub6EW1SmjSXq9YwVwcan5qWEncgx89SozMvGNpYF6hfZHYNTikNZ4gsXuVhHTi6xYJCkmY4X4wpPPS5Gr7aY39dVJMS2TGfihr25oaspKtU8q > ** Legacy signature > ** <tt>signer_2_key.bsms</tt>: > <pre>BSMS 1.0 > b0344f51d5cb04083d598fa3 > [5c890401/48'/0'/0'/1']xpub6EW1SmjSXq9YwVwcan5qWEncgx89SozMvGNpYF6hfZHYNTikNZ4gsXuVhHTi6xYJCkmY4X4wpPPS5Gr7aY39dVJMS2TGfihr25oaspKtU8q > Signer 2 key > H5kN6UHaK2xACB6iYdTxxQPD8qyFEYv9iMsQs5B0MRfCM7NA5GB+7EFgmBpSctwt6B122zWBr6mRjpYjKmj+7hs=</pre> > > * Signer 2 encryption > ** HMAC_KEY (hex): e0a20b5f5285fbaa35aad08fb70f5626c9abbe1b384a4950735b28aca6325ff2 > ** MAC (hex): 3a6deec8dbdbd6606a52c7d7e64eca4f972a293cbabac6f62736629fbe77928a > ** IV (hex) : 3a6deec8dbdbd6606a52c7d7e64eca4f > ** CIPHERTEXT (hex): bb0fb72f61b0c4858bd9c65235390b67651b94c4b0329238b0116dd6d3365ade33cb1c1b1619638968791a5d2d1d263d90280bdad8d9ca24c34a78e320076e0dccf59e7f729b541b44bbe40ba803dedd3b17c49765377cb2d913a856b86c3dd383dab475790e89226ed8ef2301574212d2809ed9c099aa67be434024ee2a4e82a146300acf755863da64807cb7bb2636f6616489636d254a870778d3540832aea44abac4328b5d90f3e6045ef36a526ce5d575f2305e3e4699dccbc713e9e68f50364036c1054c2a506aab77ea7c43a89536947c24330b09a62a90c3b4ae2d452f96ef34ec871af2c52d68ddede2503c87e2ba68d5cf9be589457879e06021ea6a6176f7dded820ba4c0e709e2a2 > ** <tt>signer_2_key.dat</tt>: <pre>3a6deec8dbdbd6606a52c7d7e64eca4f972a293cbabac6f62736629fbe77928abb0fb72f61b0c4858bd9c65235390b67651b94c4b0329238b0116dd6d3365ade33cb1c1b1619638968791a5d2d1d263d90280bdad8d9ca24c34a78e320076e0dccf59e7f729b541b44bbe40ba803dedd3b17c49765377cb2d913a856b86c3dd383dab475790e89226ed8ef2301574212d2809ed9c099aa67be434024ee2a4e82a146300acf755863da64807cb7bb2636f6616489636d254a870778d3540832aea44abac4328b5d90f3e6045ef36a526ce5d575f2305e3e4699dccbc713e9e68f50364036c1054c2a506aab77ea7c43a89536947c24330b09a62a90c3b4ae2d452f96ef34ec871af2c52d68ddede2503c87e2ba68d5cf9be589457879e06021ea6a6176f7dded820ba4c0e709e2a2</pre> > > * Signer 3 > ** MASTER_KEY_FINGERPRINT: 614cbf5f > ** PRIVATE_KEY (m/48'/0'/0'/1'): L2ccRLzH7GfVxWpU8YSY9y5UGyRoqW3UdeNT1vGfVbxAGhwU5qhD > ** XPUB (m/48'/0'/0'/1'): xpub6F9TfWTFcMYy5Ycd2ka2az1brJj78J2isLAWptZnCpFsesss5sZv5B8xsgt71ZXfhDWhUtf4vng4zY6HUVrQbDMPDYRLYvFFoLnAYfzgYPH > ** Legacy signature > ** <tt>signer_3_key.bsms</tt>: > <pre>BSMS 1.0 > 163fd307195982c4c39d50bb > [614cbf5f/48'/0'/0'/1']xpub6F9TfWTFcMYy5Ycd2ka2az1brJj78J2isLAWptZnCpFsesss5sZv5B8xsgt71ZXfhDWhUtf4vng4zY6HUVrQbDMPDYRLYvFFoLnAYfzgYPH > Signer 3 key > H0jf2JMtke5zDDIWys6fihOCA6QBmC5+hbgVB/c2mMPNPLB6tDXt0TFZU1f9wvaCR9762anKSc8CCqXLogw8V00=</pre> > > * Signer 3 encryption > ** HMAC_KEY (hex): 1f51ea067c121e2f86af5e1d484905046bc63e861573157d8b1ae9e7e47e224b > ** MAC (hex): 1a5624fcb39cebabb6174456173eec19b756bc916cf2c9d815e9bcce070898c4 > ** IV (hex) : 1a5624fcb39cebabb6174456173eec19 > ** CIPHERTEXT (hex): 48d6e139bdc8c19e93cbbf5b4478340c8cf08aa91c28803084d5f58618773f7e615e0134492b496c4e7c130351c0350701f686918033f621378552d7040efedd5539d38c258bf936475de775f23da3953fe3ba5bbbd24816b8902b87a9a09700c446b085119dedee2395dd69665e742f72f2fb6da4ebe3f4704eaf45486fbfb84d764b718cc0b756e72f72ab6069d47765bdd3ebd4074af4fa99a95691a659675ce5f72235c28ddf3c3d53179e598cddc967fc896adc6e97edeeffc85b9e44611df748d923ff3dd921ad4d6e98e0de12359a37558e326faf585ba57e73ab45bc4a49f6e8a756f365f5d204e70f7c7bed269e81e9524a41e5d4cbaad0b6b442d6eea1e5da1ca345cc665a0cffe2c3 > ** <tt>signer_3_key.dat</tt>: <pre>1a5624fcb39cebabb6174456173eec19b756bc916cf2c9d815e9bcce070898c448d6e139bdc8c19e93cbbf5b4478340c8cf08aa91c28803084d5f58618773f7e615e0134492b496c4e7c130351c0350701f686918033f621378552d7040efedd5539d38c258bf936475de775f23da3953fe3ba5bbbd24816b8902b87a9a09700c446b085119dedee2395dd69665e742f72f2fb6da4ebe3f4704eaf45486fbfb84d764b718cc0b756e72f72ab6069d47765bdd3ebd4074af4fa99a95691a659675ce5f72235c28ddf3c3d53179e598cddc967fc896adc6e97edeeffc85b9e44611df748d923ff3dd921ad4d6e98e0de12359a37558e326faf585ba57e73ab45bc4a49f6e8a756f365f5d204e70f7c7bed269e81e9524a41e5d4cbaad0b6b442d6eea1e5da1ca345cc665a0cffe2c3</pre> > > ====ROUND 2==== > * Coordinator > ** <tt>my_multisig_wallet.bsms</tt>: > <pre>BSMS 1.0 > /0/*,/1/* > sh(wsh(multi(2,[110dc257/48'/0'/0'/1']xpub6EPQbDFezXYvVFHqnc8R7QUSE8hTepbyCXU7jJBT4dVm2rQHe1i6isqoj59qhyBiCdKquo6QsgMZNHvEz3BM4cNSszF25siTqLUCznBm8vk/*,[5c890401/48'/0'/0'/1']xpub6EW1SmjSXq9YwVwcan5qWEncgx89SozMvGNpYF6hfZHYNTikNZ4gsXuVhHTi6xYJCkmY4X4wpPPS5Gr7aY39dVJMS2TGfihr25oaspKtU8q/*,[614cbf5f/48'/0'/0'/1']xpub6F9TfWTFcMYy5Ycd2ka2az1brJj78J2isLAWptZnCpFsesss5sZv5B8xsgt71ZXfhDWhUtf4vng4zY6HUVrQbDMPDYRLYvFFoLnAYfzgYPH/*)))#j3ykhz7f</pre> > > * Send to Signer 1: > ** HMAC_KEY (hex): f43c359a4b3d7b2e01be73c54519b12545ca9a23a86f824aadf577b314a7caa7 > ** MAC (hex): ee74a0f50943d7d1b65270028bb05133e87c832cdc1ef0a07c79db2093ca3432 > ** IV (hex) : ee74a0f50943d7d1b65270028bb05133 > ** CIPHERTEXT (hex): 8e3ba3dac0f979fad0d160bd00c8294ff1726d51b95ff3e1534e5a1900f3d7cd4f6d929985a94b9da2c11e4e0f7770cc53c6739fd099477323bd26a3eca9c8016e79848d15e274463424b8355cd73cced61f1816ac8bac87f8c650ee9052f50e347c52ad24b00794a9d5523714be2fdcf731f14b7a8d7c93eab44c258e1c417d2837b9676832e8ce7239dc28b4e1166803209947b8a875a99b9478ee94f7bc17399e886179ab2a0285dc11a3883f6fa439d0f2277dadbec8c355c379fc50e945897e1a738f6a55b09f6b8b6bdf6d4bc248219cbad3662a78a2f539c989e055e00b8efd42fbff978e1a5cc10f83df56117ece4d17f94a0a6d3803778ed53531419250c5a0fff6cad4ab401468dd054915b068cc8826ae1308a71b38060d68c9248d59eea11c2c52a66d5f6bc0d7ae6cb44305c36e56068456d293b70037902e7b05a3ee0af710201128dffc0c16c3306b66bd19b9ae5b91aded35ef33f07743e5b185a9f88a5c67d40270e3bbcf592167ceaf82ead693728d5129b50075edd5ce24863f3484b4b063599ed1327e1c87d0a2051fed3b1234a702722b686e4c9392a403b79726800dd6b691e516e44d9e836c190b10cf2bb262bba98293c97f2c323e59acd0a1f988c5 > ** <tt>my_multisig_wallet_for_signer_1.dat</tt>: <pre>ee74a0f50943d7d1b65270028bb05133e87c832cdc1ef0a07c79db2093ca34328e3ba3dac0f979fad0d160bd00c8294ff1726d51b95ff3e1534e5a1900f3d7cd4f6d929985a94b9da2c11e4e0f7770cc53c6739fd099477323bd26a3eca9c8016e79848d15e274463424b8355cd73cced61f1816ac8bac87f8c650ee9052f50e347c52ad24b00794a9d5523714be2fdcf731f14b7a8d7c93eab44c258e1c417d2837b9676832e8ce7239dc28b4e1166803209947b8a875a99b9478ee94f7bc17399e886179ab2a0285dc11a3883f6fa439d0f2277dadbec8c355c379fc50e945897e1a738f6a55b09f6b8b6bdf6d4bc248219cbad3662a78a2f539c989e055e00b8efd42fbff978e1a5cc10f83df56117ece4d17f94a0a6d3803778ed53531419250c5a0fff6cad4ab401468dd054915b068cc8826ae1308a71b38060d68c9248d59eea11c2c52a66d5f6bc0d7ae6cb44305c36e56068456d293b70037902e7b05a3ee0af710201128dffc0c16c3306b66bd19b9ae5b91aded35ef33f07743e5b185a9f88a5c67d40270e3bbcf592167ceaf82ead693728d5129b50075edd5ce24863f3484b4b063599ed1327e1c87d0a2051fed3b1234a702722b686e4c9392a403b79726800dd6b691e516e44d9e836c190b10cf2bb262bba98293c97f2c323e59acd0a1f988c5</pre> > > * Send to Signer 2: > ** HMAC_KEY (hex): e0a20b5f5285fbaa35aad08fb70f5626c9abbe1b384a4950735b28aca6325ff2 > ** MAC (hex): 81df9e064f1de1d5f754c4e20f9286f9d81b856d3965677a9f2430cb9297ad1f > ** IV (hex) : 81df9e064f1de1d5f754c4e20f9286f9 > ** CIPHERTEXT (hex): dcd82038ef627d6cb2deb62d04c4ccbaa3a354633d960e46312c22791f039f23fd9782a1e3a63504c1e5b3a0770bb8d32fdf168738b6c03278f1391dd5d01e9aafee7be2c8136ee018feff6fc8cdb926df13a36e115ddca8254934f56b7f700768c94cb8388a8297834de9affcd959417ae3d6ec3251387904f50f51f06306cc4d36eefc51418dd3b2c5454910a23ec67a40a3b918d2a740e812929aae949d8dde2c41cbbb3a2b7c2103788421c147f4794d6a26947c15ef4a99ceb825d0c5aaa78b8737d0ef712ba8e269a9941b1af5d217dcdd9cd06727fbdc70fabe3f5a8c09acff4e76992be7f27c6b12ca84739f62a6da86e5b79103d632c0dc8ab3f91fddb3cfbe67084dc4b861c4ac7c86fb171a058c98c67cffdc40ff17ae1533361cc6fb7b63657af0408cf30bf9d6d97aaacf9d3ff443eee61f207228cd91769ce83a0709c1be1847884c6a8fdc86ede66aef8e34fc509c49edf30f743bdc8f9052961ee340924ec2d1caadc6fd286bb3e233c153cd08c1934127752dc28e0d12efa92a050c4061653edb1cbf2fd4b2ba4e038f0b44f5735f198e92571c029156f65f534bfc149f38d611829901372cfc0176b9d2f9ac6512b7f37941a02dff701df0bceadaacfc6935 > ** <tt>my_multisig_wallet_for_signer_2.dat</tt>: <pre>81df9e064f1de1d5f754c4e20f9286f9d81b856d3965677a9f2430cb9297ad1fdcd82038ef627d6cb2deb62d04c4ccbaa3a354633d960e46312c22791f039f23fd9782a1e3a63504c1e5b3a0770bb8d32fdf168738b6c03278f1391dd5d01e9aafee7be2c8136ee018feff6fc8cdb926df13a36e115ddca8254934f56b7f700768c94cb8388a8297834de9affcd959417ae3d6ec3251387904f50f51f06306cc4d36eefc51418dd3b2c5454910a23ec67a40a3b918d2a740e812929aae949d8dde2c41cbbb3a2b7c2103788421c147f4794d6a26947c15ef4a99ceb825d0c5aaa78b8737d0ef712ba8e269a9941b1af5d217dcdd9cd06727fbdc70fabe3f5a8c09acff4e76992be7f27c6b12ca84739f62a6da86e5b79103d632c0dc8ab3f91fddb3cfbe67084dc4b861c4ac7c86fb171a058c98c67cffdc40ff17ae1533361cc6fb7b63657af0408cf30bf9d6d97aaacf9d3ff443eee61f207228cd91769ce83a0709c1be1847884c6a8fdc86ede66aef8e34fc509c49edf30f743bdc8f9052961ee340924ec2d1caadc6fd286bb3e233c153cd08c1934127752dc28e0d12efa92a050c4061653edb1cbf2fd4b2ba4e038f0b44f5735f198e92571c029156f65f534bfc149f38d611829901372cfc0176b9d2f9ac6512b7f37941a02dff701df0bceadaacfc6935</pre> > > * Send to Signer 3: > ** HMAC_KEY (hex): 1f51ea067c121e2f86af5e1d484905046bc63e861573157d8b1ae9e7e47e224b > ** MAC (hex): 159a91100cacd123480b7d085c8bb32ec8eb06f0391b6dc8fac07ae67eb37b81 > ** IV (hex) : 159a91100cacd123480b7d085c8bb32e > ** CIPHERTEXT (hex): c7269d8be21d1cfe172e35aa106760f1fdc929fce19da8fb7f74f759efec1ee02796fb1e8b008cf177f60a2021570f17aeeb41f8636858654082734b90959b98fd08419f901683c4ca3e76b3e482fea4c67162775e0d80bcb45df729f646c1364a3d8a7d1ff961717b00897e877c1c0554d3502942149726806269c546ad2dd34ba286ddf5cd336b83aabf7091fa25e607faf7e54017d84113e1e3ec440b3704addea188b89293469306fc0a98570afdcf269026b2d2e760f466c1f75bcf75fdf030c0a692e5681fd4487e59d6e96451ff5b6b9f2521b8e95e796ef4ab0a917794d91a30fdac7ee9ddbd89d174831bd133ab12a74f52f6283ee2c5fe3d5a957a7c1a15530b2c5224f76d90057dc94f2ee34e28b037ae7f518cc6dfe725cd3e657648de82b200ea77830eb93219f883998d3207a4ef5902d1119b0cde6b364bc1effb86109d9c2babc8ab26dce90329779d8cd0d737e9825a25586aa3c8fa5317e3e433ff235b82f629de0504e3c992f8e8de299f62751bc1fcb2e75e0262c7a27be7068cea69b14f303e97c24b99ed29cae142564e285657704b4c411d0d4f8c58819e2c0e0ffc3667eb5a408aad8a3023a5f00875e7deab95dc365d8757f7b79815a4fd9e6de2b3 > ** <tt>my_multisig_wallet_for_signer_3.dat</tt>: <pre>159a91100cacd123480b7d085c8bb32ec8eb06f0391b6dc8fac07ae67eb37b81c7269d8be21d1cfe172e35aa106760f1fdc929fce19da8fb7f74f759efec1ee02796fb1e8b008cf177f60a2021570f17aeeb41f8636858654082734b90959b98fd08419f901683c4ca3e76b3e482fea4c67162775e0d80bcb45df729f646c1364a3d8a7d1ff961717b00897e877c1c0554d3502942149726806269c546ad2dd34ba286ddf5cd336b83aabf7091fa25e607faf7e54017d84113e1e3ec440b3704addea188b89293469306fc0a98570afdcf269026b2d2e760f466c1f75bcf75fdf030c0a692e5681fd4487e59d6e96451ff5b6b9f2521b8e95e796ef4ab0a917794d91a30fdac7ee9ddbd89d174831bd133ab12a74f52f6283ee2c5fe3d5a957a7c1a15530b2c5224f76d90057dc94f2ee34e28b037ae7f518cc6dfe725cd3e657648de82b200ea77830eb93219f883998d3207a4ef5902d1119b0cde6b364bc1effb86109d9c2babc8ab26dce90329779d8cd0d737e9825a25586aa3c8fa5317e3e433ff235b82f629de0504e3c992f8e8de299f62751bc1fcb2e75e0262c7a27be7068cea69b14f303e97c24b99ed29cae142564e285657704b4c411d0d4f8c58819e2c0e0ffc3667eb5a408aad8a3023a5f00875e7deab95dc365d8757f7b79815a4fd9e6de2b3</pre> > > ==Acknowledgement== > > Special thanks to Pavol Rusnak, Dmitry Petukhov, Christopher Allen, Craig Raw, Robert Spigler, Gregory Sanders, Ta Tat Tai, Michael Flaxman, Pieter Wuille and others for their feedback on the specification. > > ==References== > > Original mailing list thread: > https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-February/018385.html
Hi Michael, Comments inline.
On Sat, Apr 10, 2021 at 7:34 PM Michael.flaxman < michael.flaxman@protonmail•com> wrote:
Quoted text (5 lines)
> Hi Hugo, > > I appreciate the effort you and everyone else is making to improve > multisig in bitcoin! >
Thanks.
Quoted text (53 lines)
> I like that this BIP gets rid of SLIP132 version bytes, as those have been > de-facto deprecated in favor of output descriptors for some time. Having a > standard for how to communicate descriptor records (BSMS 1.0) also seems > like a nice positive. > > The most commonly raised issues from the 10x security guide > <https://btcguide.github.io/> are about how to properly verify that all > hardware wallets are participants in the user's multisig quorum (and with > the correct m-of-n). This shows up in two big ways: > > 1. The O(n^2) xpub validation problem creates a bad UX and is hard for > non-advanced users. > 2. The risk for stateless hardware wallets (like Trezor) to have their > xpubs swapped out by a compromised Coordinator. > > Unfortunately, this BIP does not improve either of these issues, while > adding considerable complexity. > > *1. O(n^2) Xpub Validation* > > The proposed use of an output descriptor checksum has an obvious 40-bit > MITM collision attack. A compromised Coordinator could trick a Signer into > displaying an attacker's receive address, despite a correctly functioning > Signers and the user properly validating the checksum (github link > <https://github.com/nunchuk-io/bips/pull/1/#issuecomment-801629857>). > > Using a checksum with much higher entropy would reduce xpub validation to > O(n) and create a very nice UX for signers. This would be a huge win for > multisig! Instead, the recommended solution from the BIP is to validate all > the key records manually, which is how multisig is currently done and what > we desperately want to move away from. With a proper checksum, there’s no > reason for a user to ever see an xpub. > > Users should not be shown a checksum and asked to validate it in meatspace > (across Signers) if an attacker’s address could still be substituted! > Validating a single address across devices does solve this problem, but if > you’re going to validate an address there’s no reason to display the > checksum at all. However, validating an address is confusing to non-experts: > > - Is it a wallet ID or a bitcoin address? > - Am I supposed to send funds to this address? > > If creating a new checksum standard for the descriptor record is > undesirable, we could use a child address (from an unhardened BIP32 path) > and encode that in some way for end-users to verify it matches across all > Signers. It would be strongly preferable for the encoding to be an > unambiguously different format from a bitcoin address / BIP39 seed phrase, > so that it’s clear it’s just a wallet ID. One non-ideal but simple solution > is to use a hash function (i.e. dsha256) to calculate the digest of the > child address, and display this in hexadecimal format. While hexadecimal is > non-ideal for manual verification, it is already trivial for any bitcoin > library to perform these steps. >
As I have responded to your previous comment about the same on Github ( https://github.com/nunchuk-io/bips/pull/1), I do see the value of a longer checksum.
There are trade-offs when it comes to designing checksum. Mainly complexity and size. At one end of the spectrum you can have a single-byte XOR checksum. At the other end you can have something like HMAC-SHA256 (which we are using in the proposal to calculate the MACs for the key and descriptor records). And then there's everything in between. But we should know that nothing comes for free.
It's a good topic that warrants further discussion.
Confirming a single address is a promising direction, since it's something the user should do anyway prior to using the wallet. Currently the proposal recommends that the Signers show a preview of the first address(es) upon wallet creation. But we can elevate this and make it a mandatory part of the spec: have all Signers confirm that they have the same 1st receive address. If we go with this approach, the checksum can stay as-is, and only there for error detection. (We get the checksum for free with the descriptor language anyway, so there's no reason to remove it).
Also nice to see that you have come around and agree that moving away from manual inspection is desirable.
Quoted text (19 lines)
> *2. Allow Support for Stateless Wallets* > > The current BIP states: > > * "If all checks pass, the Signer must persist the descriptor record in > its storage."* > > While persistence has a lot of benefits, it is not a feature of the most > sold multisig hardware wallet: Trezor. A simple solution here is to have > each Signer sign the entire descriptor record at the end of round 2, not > just its own key record in round 1. Then the data can be stored anywhere > (including on the Signer itself) and played back to each Signer for > validation when needed. The end-user would have no idea this was happening, > but the device could refuse to display information it hasn’t fully > validated (or at least add a warning message). Even a device with > persistent storage would be better served using a signature, so that an > evil maid couldn't tamper with the device (say in the no-encryption case > for simplicity). >
I reiterate that I strongly disagree that going stateless is the direction we want to pursue when it comes to multisig.
In a multisig or any type of MPC smart contract, any Signer in the contract must know who the other co-Signers are at all times. You can choose to do this verification once at setup and persist this info on the Signer, or you'd have to re-do the verification for every single transaction. There is no other choice.
Signing the descriptor record is insufficient, while also introducing a great deal of complexity. Here are the problems: 1) The signature needs to be stored somewhere. Who stores it if it's not the Signer itself? What if it gets lost? (If the Signer stores its own signature, then the scheme is no longer stateless. You might as well store the full descriptor). 2) When the signature is "played back" to the Signer, a copy of the original descriptor must be included. Who stores the descriptor? What if it gets lost? This is an under-appreciated aspect of the stateful approach: every participant in the multisig has a full copy of the original contract, which adds resilience to the wallet backup / recovery process. 3) Because the full descriptor must be "played back" for every single transaction, this means every detail of the contract must be shared again and again, indefinitely. Not only does this add overhead (engineering and cognitive) to the spending process, it has massive privacy implications, since the descriptor contains everything you need to know about the wallets and its participants.
Here's an analogy in the physical world. Would you: a) Enter any type of written contract and b) Not keep a copy of the contract, forget about it, and c) Later on rely on your counter-parties or a third-party to provide you with the original contract and your signature, when the terms get carried out?
One would be insane to enter such a contract in the real world.
I realize that some vendors are currently not stateful, but I take this as an unfortunate fact, because multisig wasn't a priority when these hardware were originally designed. But that is no reason to keep going with a broken architecture. The industry is green enough that we still can learn and recover from these sorts of flaws.
Since you mentioned Trezor, I want to thank Pavol in particular here, because as Trezor CTO Pavol knows best that Trezor is currently stateless, but he's still on-board with the general idea here, AFAIU.
Bottom line: IMO, signers in a multisig MUST be stateful.
This existing vulnerability in stateless wallets is particularly bad for
Quoted text (47 lines)
> hosted multisig services like Casa/Unchained, where the service might > control m-1 keys. It’s far easier for a hosted service to potentially trick > non-expert users into displaying an attacker's receive address on their > stateless Signer. > > For example, assume the user is doing 2-of-3 multisig, where the > Coordinator (service) controls 1 key. Here is how the Coordinator could > trick their end-users: > > 1. Coordinator swaps out 1 of the end-user’s xpubs, going from a > 2-of-3 where the end-user has 2 seeds to a 2-of-3 where the Coordinator has > 2 seeds. > 2. The end-user logs into the service to get a new receive address, > and the service (Coordinator) displays malicious receive address X (as part > of a 2-of-3). > 3. The end user connects stateless Signer 1 to the service > (Coordinator), which under-the-hood gives stateless Signer 1 proof that it > is included in this 2-of-3. Stateless singer 1 displays malicious receive > address X! > 4. The end-user doesn't verify the address on Signer 2, as many users > unfortunately don't -- perhaps it is in a far away location and the > end-user (incorrectly) thinks that it’s already been validated in 2 places > -- and makes a large deposit to receive address X. These funds now belong > to the attacker and can be swept at any time! > > If stateless Signer 1 required a signature to be replayed at step 3, > stateless Signer 1 would refuse to display malicious receive address X (or > at a minimum warn the end-user that it did not have enough info to properly > validate the address). > > This is also a concern for self-hosted multisig, I just used the hosted > services as the best example. > > It's also not just Trezor that is stateless. For example, I wrote a > simple CLI software multisig wallet as part of the buidl library > <https://twitter.com/mflaxman/status/1321503036724989952> to be used > mostly for emergency recovery. At 800 lines of code, it's too > simple/minimal to touch the file system. > > *BIP39* > > While unrelated, the use of BIP39 words for session tokens seems like a > big mistake, as end-users have learned over years that BIP39 words are for > private key material. A small percent of users may backup their token BIP39 > mnemonic and not their seed phrase BIP39 mnemonic! My suggestion is to just > stick with the other two Token options: decimal and hex. >
Repost of my previous response. We discussed this at length on the linked Github PR: "We decided to keep the TOKEN at 6-9 words, not 12 or anything above precisely for this reason. Please note that the user has to back up their Signers first, before proceeding to setting up the multisig wallet. So there's no writing both things down at once or mixing of the two flows here.
I also find it hard to believe that someone who wants to invest in a safe multisig solution (and therefore must know at minimum what keys and multisig represent) will not know the difference between (permanent) 12 words and (one-time use) 6 words. Also note that the TOKEN can be used without using BIP39 mnemonic at all."
We also made the decimal format, not BIP39 mnemonic, the recommended encoding in the spec.
Best, Hugo
Hi Hugo,
First of all, thank you for the impressive work on leading the standardization efforts!
I believe one ought to more clearly distinguish the "Signer" (as in: one of the parties in the multisig setup), from the "*Signing device*" (which is likely a hardware wallet). BSMS defines a "Signer" as "a participating member in the multisig", therefore a person/entity who is likely using both a hardware wallet and some BSMS-friendly software wallet (e.g. the next version of Specter Desktop). It is therefore relevant to discuss which parts of the BSMS mechanism are implemented in the Signer's software wallet, and which should be in the Signer's hardware wallet. From the discussion, it appears to me that different people might have different expectations on what the signing device/HWW should do, so I would like to comment on this point specifically (while I reckon that it mostly falls within the realm of concerns #4 and #5 of the motivation paragraph, which are explicitly left out of scope).
I fully agree that a *Signer* must persist the full wallet's description, and should also create physical backups which include the full descriptor and the cosigner's information. I would disagree, however, if any standards were to force *hardware wallets* to persist any substantial amount of state other than the seed, as I believe that it gives no substantial advantage over externally stored signed data for many use cases.
The following is the *wallet registration flow* I am currently working on (in the context of adding support to multisig wallets at Ledger). The goal is to allow a *Signer* (the person) to persist a multisig setup in its storage, while achieving a similar level of security you would have if you were storing it on the hardware wallet itself (note that the following flow would happen as part of Round 2):
1) The desktop wallet of the requests the HWW to register a new multisig wallet. The request includes the full multisig wallet description, and some extra metadata (e.g.: a name to be associated to this multisig wallet). 2) The HWW validates the wallet and verifies it with the user with the trusted screen (as per BSMS Round 2); on confirmation, it returns a wallet id (which is a vendor-specific hash of all the wallet description + metadata) and signature 3) The desktop wallet stores the full wallet description/id/signature. (Optionally, a backup could be stored elsewhere).
Whenever an operation related to the multisig wallet is required (verifying a receiving address, or signing a spending transaction), the HWW first receives and verifies all the data stored at step 3 above (without any user interaction). Then it proceeds exactly the same way as if it had always stored the multisig wallet in their own storage. I think this is basically the same flow Michael Flaxman is suggesting here: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-April/018775.html
(Note that none of this is flow specific to Multisig wallet, as the same flow would be unchanged for any arbitrary supported script that needs to be "registered" on a stateless device, and can be generalized for MPC protocols)
The only caveat I can think of is that the script registration is never revocable if a signing key derived from the seed is used in step (2), which might or might not be desirable. One could instead prefer to use a different signing key that is destroyed if the device is wiped, which would therefore need to be stored on the device. Note that the only thing that is lost is the on-device multisig wallet registration, which could easily be repeated from a backup.
On Sun, 11 Apr 2021 at 19:11, Hugo Nguyen via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (10 lines)
> I reiterate that I strongly disagree that going stateless is the direction > we want to pursue when it comes to multisig. > > In a multisig or any type of MPC smart contract, any Signer in the > contract must know who the other co-Signers are at all times. You can > choose to do this verification once at setup and persist this info on the > Signer, or you'd have to re-do the verification for every single > transaction. There is no other choice. > >
Signing the descriptor record is insufficient, while also introducing a
Quoted text (6 lines)
> great deal of complexity. Here are the problems: > 1) The signature needs to be stored somewhere. Who stores it if it's not > the Signer itself? What if it gets lost? (If the Signer stores its own > signature, then the scheme is no longer stateless. You might as well store > the full descriptor). >
In the flow I describe above, the desktop wallet would indeed store the signed descriptor record and wallet metadata. So yes, the *Signer* as in *the party in the protocol* stores it, but not the signing device*. *The same method could be used to store state temporarily between round 1 and 2, where the only *state* on the hardware wallet would be the TOKEN, while everything else is stored (encrypted and signed) on the Signer's desktop.
Quoted text (6 lines)
> 2) When the signature is "played back" to the Signer, a copy of the > original descriptor must be included. Who stores the descriptor? What if it > gets lost? This is an under-appreciated aspect of the stateful approach: > every participant in the multisig has a full copy of the original contract, > which adds resilience to the wallet backup / recovery process. >
"Playing back" the signature and wallet's setup data to the hardware wallet would indeed happen transparently from the Signer's wallet software. If the Signer lost this data due to malware, faulty hardware, etc., the user would indeed have to recover from backup, which seems ok to me.
Quoted text (7 lines)
> 3) Because the full descriptor must be "played back" for every single > transaction, this means every detail of the contract must be shared again > and again, indefinitely. Not only does this add overhead (engineering and > cognitive) to the spending process, it has massive privacy implications, > since the descriptor contains everything you need to know about the wallets > and its participants. >
I agree with some of these concerns, but I observe: - The engineering overhead in handling externally-stored-signed-data is paid once, and would mostly fall on the hardware wallet vendor. External software only cares about storing certain data and sending it back later. - Storing xpubs/descriptors in the desktop software that interacts with the HWW is already common practice, and necessary for using any watch-only wallet.
Summarizing, I argue that the stateful/stateless characteristic of a hardware wallet does not really affect (modulo some extra work) the ability to participate in the BSMS ceremony, whose *Signers* should indeed be stateful. Some more clarifications on the trust assumptions might help at clarifying the best possible software/hardware implementation tradeoffs, either in this or a follow-up BIP.
Best, Salvatore Ingala
Hello Salvatore,
On Mon, Apr 12, 2021 at 8:03 AM Salvatore Ingala <salvatore.ingala@gmail•com> wrote:
Quoted text (9 lines)
> Hi Hugo, > > First of all, thank you for the impressive work on leading the > standardization efforts! > > I believe one ought to more clearly distinguish the "Signer" (as in: one > of the parties in the multisig setup), from the "*Signing device*" (which > is likely a hardware wallet). >
Actually, in the current spec, a "Signer" is *any software/hardware that possesses the private keys and can sign using those keys* -- it doesn't have to be hardware. "Signer" does not mean the human user. I will clarify the definition and clear up any ambiguous language in the spec. Thanks for bringing this to my attention!
Quoted text (5 lines)
> BSMS defines a "Signer" as "a participating member in the multisig", > therefore a person/entity who is likely using both a hardware wallet and > some BSMS-friendly software wallet (e.g. the next version of Specter > Desktop). >
As mentioned above, "Signer" does not refer to the user or any entity that does not have the private keys / signing capability.
Quoted text (39 lines)
> It is therefore relevant to discuss which parts of the BSMS mechanism are > implemented in the Signer's software wallet, and which should be in the > Signer's hardware wallet. > From the discussion, it appears to me that different people might have > different expectations on what the signing device/HWW should do, so I would > like to comment on this point specifically (while I reckon that it mostly > falls within the realm of concerns #4 and #5 of the motivation paragraph, > which are explicitly left out of scope). > > I fully agree that a *Signer* must persist the full wallet's description, > and should also create physical backups which include the full descriptor > and the cosigner's information. I would disagree, however, if any standards > were to force *hardware wallets* to persist any substantial amount of > state other than the seed, as I believe that it gives no substantial > advantage over externally stored signed data for many use cases. > > The following is the *wallet registration flow* I am currently working on > (in the context of adding support to multisig wallets at Ledger). The goal > is to allow a *Signer* (the person) to persist a multisig setup in its > storage, while achieving a similar level of security you would have if you > were storing it on the hardware wallet itself (note that the following flow > would happen as part of Round 2): > > 1) The desktop wallet of the requests the HWW to register a new multisig > wallet. The request includes the full multisig wallet description, and some > extra metadata (e.g.: a name to be associated to this multisig wallet). > 2) The HWW validates the wallet and verifies it with the user with the > trusted screen (as per BSMS Round 2); on confirmation, it returns a wallet > id (which is a vendor-specific hash of all the wallet description + > metadata) and signature > 3) The desktop wallet stores the full wallet description/id/signature. > (Optionally, a backup could be stored elsewhere). > > Whenever an operation related to the multisig wallet is required > (verifying a receiving address, or signing a spending transaction), the HWW > first receives and verifies all the data stored at step 3 above (without > any user interaction). Then it proceeds exactly the same way as if it had > always stored the multisig wallet in their own storage. >
Now that we're clear on definitions, then it should become obvious that redefining the "Coordinator-Signer" pair as "a Signer" does not address the underlying problem. (What you call "the desktop wallet" here is a Coordinator, not a Signer).
As long as the Signer does not own up the task of storing the wallet configuration, it must rely indefinitely on others for critical data when working in a multisig wallet, as I have explained in my last email.
Best, Hugo
Quoted text (1 line)
>
Though I am ACK on that we need to solve the problem of xpub privacy and reuse, I'm NACK on this solution. It is currently too complex and doesn't really solve the problem.
I believe that the ultimate solution will be some form of multi-round cryptographic commitment scheme, and as musig threshold signatures with Taproot/Schnoor also require multi-round scheme, we should start thinking now about how maybe we can leverage that work to address this problem as well. However, I'm not a cryptographer and don't have a specific solution in this area to offer.
In the meantime, there are some possible measures we can take as new best practices. This is not a formal list, and I'm open to other suggestions, but each are currently relatively easy and are functional with some existing wallets that CAN support state. Let us get it right with stateful wallets, then we can return back to better best practices for stateless wallets like Trezor, Ledger, etc.
A) We should accept that users must to backup their multisig account maps (descriptor with only xpubs) along with their cosigner key material to be able to recover funds. In the Airgap Community we make this very easy with a simple UR code that works efficiently as a QR. I personally keep multiple copies of this account map in multiple locations, as it is less of a risk (mostly privacy) if one of the locations is compromised.
B) Cosigner wallets and transaction coordinator services should not share the master xpub, only the derived co-signer xpubs required for that specific account. Currently too many libraries, wallets and coordinators only function if they get the master xpub — these should be updated to not require them.
C) In many current wallets, the master xpub fingerprint is required — that master fingerprint is also a privacy risk and should not be used. For instance, the current practice of offering what the Airgap Community calls a `crypto-hdkey` [604b93f2/48'/1'/0'/2'] with the master fingerprint root, could instead be to only offer a single parent fingerprint [f93749a7/2'] from that grandparent master key. Thus different fingerprints can be offered for each account, and only the signer knows the actual master fingerprint and its children.
D) Given C, when creating a new multisig account, a transaction coordinator may request a specific master fingerprint and/or a fixed 48' derivation xpub from a cosigner wallet, but these are only hints. If it gets back a different fingerprint or derivation, it should accept it. In the case of the Airgap Community's specifications, in our "crypto-request" we actually specifically allow for wildcard requests which makes this easy and explicit. Yes, only stateful signers can know to return an xpub something other than the fingerprint and m/48'/1'/0'/2' default, but a transaction coordinator should accept it if it receives it.
E) Transaction coordinators should send the cosigner "policy" (basically the multisign descriptor without any keys in it) along with any request to derive a new xpub for that new account. Stateful wallets can use this policy to know later if they are asked to sign a PSBT that does not match this policy.
F) Transaction coordinators should also send the final "account map" to all the cosigner wallets as a best practice as well. This would replace the temporary "policy" in D. If a PSBT request to sign using a key doesn't match the original account map, the cosigner wallet can reject it.
These best practices don't solve the problem with stateless wallets like Trezor, but they are possible now with the new generation of multisig hardware and software wallets, such as Foundation Devices, CoboVault, Sparrow, Bluwallet and my Gordian reference wallet tools. We have available NOW working interoperable specifications, reference code, and example apps that support these best practices, and some are already supported by multiple wallets in the Airgapped Wallet Community hosted by Blockchain Commons at https://github.com/blockchainCommons/airgapped-Wallet-Community.
I've put a copy of this rough proposal in our Airgapped Wallet Community discussion area if you have suggestions or alternative best practices.
[Initial proposal for best practice to avoid XPUB reuse in multisig account creation]( https://github.com/BlockchainCommons/Airgapped-Wallet-Community/discussions/53 )
-- Christopher Allen, Blockchain Commons
I don't quite understand your NACK.
The following are measures you say we should take as best practices, which I believe are all implemented:
Quoted text (1 line)
>A) We should accept that users must to backup their multisig account maps (descriptor with only xpubs) along with their cosigner key material to be able to recover funds.
BSMS requires that the descriptor persist in storage and be able to be displayed when requested by the user. It is already industry standard that the same apply to cosigner key material. Backing up both is good practice. (My BIP for a new key hierarchy enforces this as well (https://github.com/bitcoin/bips/pull/1089))
Quoted text (1 line)
>B) Cosigner wallets and transaction coordinator services should not share the master xpub
Again, check out my updated hierarchy for multisignature wallets, which enforces this and works very well with BSMS.
Quoted text (1 line)
>C) In many current wallets, the master xpub fingerprint is required
I am confused by this - the descriptor language standardizes the master xpub fingerprint in the key origin information?
Quoted text (1 line)
>E) Transaction coordinators should send the cosigner "policy"
There is no cosigner "policy" in this standard, but the same checks are implemented (N unique key records, key is included in descriptor, plus valid MAC, valid signatures, valid checksum, etc).
Quoted text (1 line)
>F) Transaction coordinators should also send the final "account map" to all the cosigner wallets
This is done
Robert Spigler
Personal Fingerprint: BF0D 3C08 A439 5AC6 11C1 5395 B70B 4A77 F850 548F
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Monday, April 12, 2021 2:45 PM, Christopher Allen via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> wrote:
Quoted text (25 lines)
> Though I am ACK on that we need to solve the problem of xpub privacy and reuse, I'm NACK on this solution. It is currently too complex and doesn't really solve the problem. > > I believe that the ultimate solution will be some form of multi-round cryptographic commitment scheme, and as musig threshold signatures with Taproot/Schnoor also require multi-round scheme, we should start thinking now about how maybe we can leverage that work to address this problem as well. However, I'm not a cryptographer and don't have a specific solution in this area to offer. > > In the meantime, there are some possible measures we can take as new best practices. This is not a formal list, and I'm open to other suggestions, but each are currently relatively easy and are functional with some existing wallets that CAN support state. Let us get it right with stateful wallets, then we can return back to better best practices for stateless wallets like Trezor, Ledger, etc. > > A) We should accept that users must to backup their multisig account maps (descriptor with only xpubs) along with their cosigner key material to be able to recover funds. In the Airgap Community we make this very easy with a simple UR code that works efficiently as a QR. I personally keep multiple copies of this account map in multiple locations, as it is less of a risk (mostly privacy) if one of the locations is compromised. > > B) Cosigner wallets and transaction coordinator services should not share the master xpub, only the derived co-signer xpubs required for that specific account. Currently too many libraries, wallets and coordinators only function if they get the master xpub — these should be updated to not require them. > > C) In many current wallets, the master xpub fingerprint is required — that master fingerprint is also a privacy risk and should not be used. For instance, the current practice of offering what the Airgap Community calls a `crypto-hdkey` [604b93f2/48'/1'/0'/2'] with the master fingerprint root, could instead be to only offer a single parent fingerprint [f93749a7/2'] from that grandparent master key. Thus different fingerprints can be offered for each account, and only the signer knows the actual master fingerprint and its children. > > D) Given C, when creating a new multisig account, a transaction coordinator may request a specific master fingerprint and/or a fixed 48' derivation xpub from a cosigner wallet, but these are only hints. If it gets back a different fingerprint or derivation, it should accept it. In the case of the Airgap Community's specifications, in our "crypto-request" we actually specifically allow for wildcard requests which makes this easy and explicit. Yes, only stateful signers can know to return an xpub something other than the fingerprint and m/48'/1'/0'/2' default, but a transaction coordinator should accept it if it receives it. > > E) Transaction coordinators should send the cosigner "policy" (basically the multisign descriptor without any keys in it) along with any request to derive a new xpub for that new account. Stateful wallets can use this policy to know later if they are asked to sign a PSBT that does not match this policy. > > F) Transaction coordinators should also send the final "account map" to all the cosigner wallets as a best practice as well. This would replace the temporary "policy" in D. If a PSBT request to sign using a key doesn't match the original account map, the cosigner wallet can reject it. > > These best practices don't solve the problem with stateless wallets like Trezor, but they are possible now with the new generation of multisig hardware and software wallets, such as Foundation Devices, CoboVault, Sparrow, Bluwallet and my Gordian reference wallet tools. We have available NOW working interoperable specifications, reference code, and example apps that support these best practices, and some are already supported by multiple wallets in the Airgapped Wallet Community hosted by Blockchain Commons at https://github.com/blockchainCommons/airgapped-Wallet-Community. > > I've put a copy of this rough proposal in our Airgapped Wallet Community discussion area if you have suggestions or alternative best practices. > > [Initial proposal for best practice to avoid XPUB reuse in multisig account creation](https://github.com/BlockchainCommons/Airgapped-Wallet-Community/discussions/53) > > -- Christopher Allen, Blockchain Commons