summaryrefslogtreecommitdiff
path: root/af/3be43404c3d6cdeec1aaa931e075f434a3906e
blob: 3554cbdac43cc7e126af9d8d68bbdaa383ba7ca0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
Return-Path: <hugo@nunchuk.io>
Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])
 by lists.linuxfoundation.org (Postfix) with ESMTP id B3FC8C000A
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun, 11 Apr 2021 16:45:17 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
 by smtp4.osuosl.org (Postfix) with ESMTP id 9F66240284
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun, 11 Apr 2021 16:45:17 +0000 (UTC)
X-Virus-Scanned: amavisd-new at osuosl.org
X-Spam-Flag: NO
X-Spam-Score: -1.224
X-Spam-Level: 
X-Spam-Status: No, score=-1.224 tagged_above=-999 required=5
 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1,
 HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_SOFTFAIL=0.665,
 T_KAM_HTML_FONT_INVALID=0.01] autolearn=no autolearn_force=no
Authentication-Results: smtp4.osuosl.org (amavisd-new);
 dkim=pass (2048-bit key) header.d=nunchuk-io.20150623.gappssmtp.com
Received: from smtp4.osuosl.org ([127.0.0.1])
 by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
 with ESMTP id dXReHC_0vh-L
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun, 11 Apr 2021 16:45:15 +0000 (UTC)
X-Greylist: whitelisted by SQLgrey-1.8.0
Received: from mail-pg1-x535.google.com (mail-pg1-x535.google.com
 [IPv6:2607:f8b0:4864:20::535])
 by smtp4.osuosl.org (Postfix) with ESMTPS id F3C9A4027F
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun, 11 Apr 2021 16:45:14 +0000 (UTC)
Received: by mail-pg1-x535.google.com with SMTP id y32so7505407pga.11
 for <bitcoin-dev@lists.linuxfoundation.org>;
 Sun, 11 Apr 2021 09:45:14 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=nunchuk-io.20150623.gappssmtp.com; s=20150623;
 h=mime-version:references:in-reply-to:from:date:message-id:subject:to
 :cc; bh=RXr4VaPOizdqeFrh4VluRkroIHMe/TedsL9bXk7QNmA=;
 b=LNpG79HAg9rjQ4Pqz4GZsnfmbggfICouNLIAKwZjhjn9SfWcdktmRZpPvxdZnz0BbI
 8dUAi9HY1yhU1Te1s56a7I73QKfCCsIGTcS695xVD6KS5GwYS7bRXn/tbMJJnZPY37OF
 TWJyPJFPzvmU0fYpQeFSe9dRVO+JC2deltpbr6FCiMEfIqooHMFTYo9+JdcNjQpNLMUo
 N4nDEgYgWkWln8V5kZ5XFTENNLV6GvT/gIOW5tZ8DyhnNsTJ4u0fzIROw+iniIQJqOGl
 kk+Wc1VCcxUFTIQ9bnSEP1jj/mIjE9mdG+pzsS81vJ4i5Tus32H20SD9g/Iejcsl5Kwx
 X6/g==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20161025;
 h=x-gm-message-state:mime-version:references:in-reply-to:from:date
 :message-id:subject:to:cc;
 bh=RXr4VaPOizdqeFrh4VluRkroIHMe/TedsL9bXk7QNmA=;
 b=sY0IiHm4DydhAAzCLucTo8z2yOQSqP6Ajq4BbVOklFcEZyPmY6otl0ip7u9ovtFn51
 /r+8ZGwDdDuddG1yV3eMBrwS/mNHk6l8jDG4tQ1nFp4MEbryOtPyw4anUJUDltNxxvnz
 qTbdHZL5360iMyIwkM/W/ezyOayrWwDkufl7dolBWEdaTGXNdN2lumLSKU8JjksKjXtC
 BusVa5V300OGB/XA7ecvdj0i33+oPcjU0GhXAOBwj1AxiXBQoXnnypxdCujxDqz/+R2m
 KahpR671q8OmT9aKPxYmhlXQfsZCTv1HhGM+woax3qN2dYH8ncIp2SMrp40hmEMYDVZx
 06xw==
X-Gm-Message-State: AOAM5301LiYK0qmsDyJkW5NDBl7Oe+MJ+XOSqUygpgmkCaYjsQtzTO4a
 Cw0Ng42NK2/pUtZNYbsDvb+ivw3IeZES29oDwfzA4g==
X-Google-Smtp-Source: ABdhPJx+WB2HIy36EAogFwmfaBT750a7LLWqfLbBB2w7O4NzQC7H/5ZIWYlUFxzOXMneJuui7CeyBUtS2PxzEBwKsh4=
X-Received: by 2002:a63:d43:: with SMTP id 3mr22938208pgn.5.1618159514356;
 Sun, 11 Apr 2021 09:45:14 -0700 (PDT)
MIME-Version: 1.0
References: <CAPKmR9uyY70MhmVCh=C9DeyF2Tyxibux1E_bLPo00aW_h+OjLw@mail.gmail.com>
 <CAPKmR9v=RK7byF0z0hKiLiA=Zm3ZZKbu3vEiuBuzQSXFwa+izw@mail.gmail.com>
 <s7sT6UplllXDfiCyf2HWJvEdz-1Gp9D5bvpwtAcmXEq2sRYm99FZZXJEFs-fDuhLKyxpgEvMrKa3P5OIRznxHLUqMjMIaUs-s5CGsx7zO_Q=@protonmail.com>
In-Reply-To: <s7sT6UplllXDfiCyf2HWJvEdz-1Gp9D5bvpwtAcmXEq2sRYm99FZZXJEFs-fDuhLKyxpgEvMrKa3P5OIRznxHLUqMjMIaUs-s5CGsx7zO_Q=@protonmail.com>
From: Hugo Nguyen <hugo@nunchuk.io>
Date: Sun, 11 Apr 2021 09:45:00 -0700
Message-ID: <CAPKmR9v7xX7ASXAUkNXwjM5ExEF8xs5ihKw6MiY=RXk6o5s2Ng@mail.gmail.com>
To: "Michael.flaxman" <michael.flaxman@protonmail.com>
Content-Type: multipart/alternative; boundary="0000000000000b20c905bfb51f60"
X-Mailman-Approved-At: Sun, 11 Apr 2021 17:11:03 +0000
Cc: Bitcoin Protocol Discussion <bitcoin-dev@lists.linuxfoundation.org>
Subject: Re: [bitcoin-dev] Proposal: Bitcoin Secure Multisig Setup
X-BeenThere: bitcoin-dev@lists.linuxfoundation.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: Bitcoin Protocol Discussion <bitcoin-dev.lists.linuxfoundation.org>
List-Unsubscribe: <https://lists.linuxfoundation.org/mailman/options/bitcoin-dev>, 
 <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=unsubscribe>
List-Archive: <http://lists.linuxfoundation.org/pipermail/bitcoin-dev/>
List-Post: <mailto:bitcoin-dev@lists.linuxfoundation.org>
List-Help: <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=help>
List-Subscribe: <https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev>, 
 <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=subscribe>
X-List-Received-Date: Sun, 11 Apr 2021 16:45:17 -0000

--0000000000000b20c905bfb51f60
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Hi Michael,
Comments inline.

On Sat, Apr 10, 2021 at 7:34 PM Michael.flaxman <
michael.flaxman@protonmail.com> wrote:

> Hi Hugo,
>
> I appreciate the effort you and everyone else is making to improve
> multisig in bitcoin!
>

Thanks.


> I like that this BIP gets rid of SLIP132 version bytes, as those have bee=
n
> 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 int=
o
> 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 a=
ll
> the key records manually, which is how multisig is currently done and wha=
t
> we desperately want to move away from. With a proper checksum, there=E2=
=80=99s no
> reason for a user to ever see an xpub.
>
> Users should not be shown a checksum and asked to validate it in meatspac=
e
> (across Signers) if an attacker=E2=80=99s address could still be substitu=
ted!
> Validating a single address across devices does solve this problem, but i=
f
> you=E2=80=99re going to validate an address there=E2=80=99s no reason to =
display the
> checksum at all. However, validating an address is confusing to non-exper=
ts:
>
>    - 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=E2=80=99s clear it=E2=80=99s just a wallet ID. One non-ideal b=
ut 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.


> *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 happenin=
g,
> but the device could refuse to display information it hasn=E2=80=99t full=
y
> 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
> hosted multisig services like Casa/Unchained, where the service might
> control m-1 keys. It=E2=80=99s far easier for a hosted service to potenti=
ally 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=E2=80=99s xpubs, going from=
 a
>    2-of-3 where the end-user has 2 seeds to a 2-of-3 where the Coordinato=
r 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 tha=
t it
>    is included in this 2-of-3. Stateless singer 1 displays malicious rece=
ive
>    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=E2=80=99s already been validated=
 in 2 places
>    -- and makes a large deposit to receive address X. These funds now bel=
ong
>    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 (o=
r
> at a minimum warn the end-user that it did not have enough info to proper=
ly
> 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 fo=
r
> private key material. A small percent of users may backup their token BIP=
39
> mnemonic and not their seed phrase BIP39 mnemonic! My suggestion is to ju=
st
> 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

--0000000000000b20c905bfb51f60
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr">Hi Michael,<br>Comments inline.</div><br>=
<div class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Sat, Ap=
r 10, 2021 at 7:34 PM Michael.flaxman &lt;<a href=3D"mailto:michael.flaxman=
@protonmail.com">michael.flaxman@protonmail.com</a>&gt; wrote:<br></div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t:1px solid rgb(204,204,204);padding-left:1ex"><div>Hi Hugo,<br></div><div>=
<br></div><div>I appreciate the effort you and everyone else is making to i=
mprove multisig in bitcoin!<br></div></blockquote><div><br>Thanks.<br>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>I  like tha=
t this BIP gets rid of SLIP132 version bytes, as those have been de-facto d=
eprecated in favor of output descriptors for some time. Having a standard f=
or how to communicate descriptor records (BSMS 1.0) also seems like a nice =
positive.<br></div><div><br></div><div>The most commonly raised issues from=
 <a rel=3D"nofollow" title=3D"https://btcguide.github.io/" href=3D"https://=
btcguide.github.io/" target=3D"_blank">the 10x security guide</a>=C2=A0are =
about how to properly verify that all hardware wallets are participants in =
the user&#39;s multisig quorum (and with the correct m-of-n). This shows up=
 in two big ways:<br></div><ol><li>The O(n^2) xpub validation problem creat=
es a bad UX and is hard for non-advanced users.<br></li><li>The risk for st=
ateless hardware wallets (like Trezor) to have their xpubs swapped out by a=
 compromised Coordinator.<br></li></ol><div>Unfortunately, this BIP does no=
t improve either of these issues, while adding considerable complexity.<br>=
</div><div><br></div><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0p=
t;margin-bottom:0pt"><span style=3D"background-color:transparent"><span sty=
le=3D"color:rgb(0,0,0)"><b><span style=3D"font-family:Arial"><span style=3D=
"font-size:11pt">1. O(n^2) Xpub Validation</span></span></b></span></span><=
br></p><div><br></div><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0=
pt;margin-bottom:0pt"><span style=3D"background-color:transparent"><span st=
yle=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"><span style=3D"f=
ont-size:11pt">The proposed use of an output descriptor checksum has an obv=
ious 40-bit MITM collision attack. A compromised Coordinator could trick a =
Signer into displaying an attacker&#39;s receive address, despite a correct=
ly functioning Signers and the user properly validating the checksum (<a re=
l=3D"nofollow" title=3D"https://github.com/nunchuk-io/bips/pull/1/#issuecom=
ment-801629857" href=3D"https://github.com/nunchuk-io/bips/pull/1/#issuecom=
ment-801629857" target=3D"_blank">github link</a>).</span></span></span></s=
pan><br></p><div><br></div><p dir=3D"ltr" style=3D"line-height:1.38;margin-=
top:0pt;margin-bottom:0pt"><span style=3D"background-color:transparent"><sp=
an style=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"><span style=
=3D"font-size:11pt">Using a checksum with much higher entropy would reduce =
xpub validation to O(n) and create a very nice UX for signers. This would b=
e a huge win for multisig! Instead, the recommended solution from the BIP i=
s to validate all the key records manually, which is how multisig is curren=
tly done and what we desperately want to move away from. With a proper chec=
ksum, there=E2=80=99s no reason for a user to ever see an xpub.</span></spa=
n></span></span><br></p><div><br></div><p dir=3D"ltr" style=3D"line-height:=
1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"background-color:tran=
sparent"><span style=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"=
><span style=3D"font-size:11pt">Users should not be shown a checksum and as=
ked to validate it in meatspace (across Signers) if an attacker=E2=80=99s a=
ddress could still be substituted! Validating a single address across devic=
es does solve this problem, but if you=E2=80=99re going to validate an addr=
ess there=E2=80=99s no reason to display the checksum at all. However, vali=
dating an address is confusing to non-experts:</span></span></span></span><=
br></p><ul><li dir=3D"ltr"><span style=3D"background-color:transparent"><sp=
an style=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"><span style=
=3D"font-size:11pt">Is it a wallet ID or a bitcoin address?</span></span></=
span></span><br></li><li dir=3D"ltr"><span style=3D"background-color:transp=
arent"><span style=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"><=
span style=3D"font-size:11pt">Am I supposed to send funds to this address?<=
/span></span></span></span><br></li></ul><p dir=3D"ltr" style=3D"line-heigh=
t:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"background-color:tr=
ansparent"><span style=3D"color:rgb(0,0,0)"><span style=3D"font-family:Aria=
l"><span style=3D"font-size:11pt">If creating a new checksum standard for t=
he 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 enco=
ding to be an unambiguously different format from a bitcoin address / BIP39=
 seed phrase, so that it=E2=80=99s clear it=E2=80=99s 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 alre=
ady trivial for any bitcoin library to perform these steps.</span></span></=
span></span></p></blockquote><div><br>As I have responded to your previous =
comment about the same on Github (<a href=3D"https://github.com/nunchuk-io/=
bips/pull/1">https://github.com/nunchuk-io/bips/pull/1</a>), I do see the=
=C2=A0value of a longer=C2=A0checksum.<br><br>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 calc=
ulate the MACs for the key and descriptor records). And then there&#39;s ev=
erything in between. But we should know=C2=A0that nothing comes for free.<b=
r><br>It&#39;s a good topic that=C2=A0warrants further discussion.<br><br>C=
onfirming a single address is a promising direction,=C2=A0since it&#39;s so=
mething 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 par=
t 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,=C2=A0an=
d only there for error detection. (We get the checksum for free with the de=
scriptor language anyway, so there&#39;s no reason to remove it).<br><br>Al=
so nice to see that you have come around and agree that moving away from ma=
nual inspection is desirable.=C2=A0<br><br></div><blockquote class=3D"gmail=
_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204=
,204);padding-left:1ex"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top=
:0pt;margin-bottom:0pt"><br></p><p dir=3D"ltr" style=3D"line-height:1.38;ma=
rgin-top:0pt;margin-bottom:0pt"><span style=3D"background-color:transparent=
"><span style=3D"color:rgb(0,0,0)"><b><span style=3D"font-family:Arial"><sp=
an style=3D"font-size:11pt">2. Allow Support for Stateless Wallets</span></=
span></b></span></span><br></p><div><br></div><p dir=3D"ltr" style=3D"line-=
height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"background-col=
or:transparent"><span style=3D"color:rgb(0,0,0)"><span style=3D"font-family=
:Arial"><span style=3D"font-size:11pt">The current BIP states:</span></span=
></span></span><br></p><div><br></div><p dir=3D"ltr" style=3D"line-height:1=
.38;margin-left:36pt;margin-top:0pt;margin-bottom:0pt"><span style=3D"backg=
round-color:transparent"><span style=3D"color:rgb(0,0,0)"><i><span style=3D=
"font-family:Arial"><span style=3D"font-size:11pt">=C2=A0&quot;If all check=
s pass, the Signer must persist the descriptor record in its storage.&quot;=
</span></span></i></span></span><br></p><div><br></div><p dir=3D"ltr" style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"backg=
round-color:transparent"><span style=3D"color:rgb(0,0,0)"><span style=3D"fo=
nt-family:Arial"><span style=3D"font-size:11pt">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 des=
criptor 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) an=
d 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 in=
formation it hasn=E2=80=99t fully validated (or at least add a warning mess=
age). Even a device with persistent storage would be better served using a =
signature, so that an evil maid couldn&#39;t tamper with the device (say in=
 the no-encryption case for simplicity).</span></span></span></span></p></b=
lockquote><div><br>I reiterate that I strongly disagree that going stateles=
s is the direction we want to pursue when it comes to multisig.<br><br>In a=
 multisig or any type of MPC smart contract, any Signer in the contract mus=
t 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&#39=
;d have to re-do the verification for every single transaction. There is no=
 other choice.<br><br>Signing the=C2=A0descriptor record is insufficient, w=
hile also=C2=A0introducing a great deal of complexity. Here are the problem=
s:<br>1) The signature needs to be stored somewhere. Who stores it if it&#3=
9;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 st=
ore the=C2=A0full descriptor).<br>2) When the signature is &quot;played bac=
k&quot; 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-appreciat=
ed aspect of the stateful approach: every participant in the multisig has a=
 full copy of the original contract, which adds resilience to the wallet ba=
ckup / recovery process.<br>3) Because the full descriptor must be &quot;pl=
ayed back&quot; for every single transaction, this means every detail of th=
e contract must be shared again and again,=C2=A0indefinitely. 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.<br><br>Here&#39;s =
an analogy in the physical world. Would you:<br>a) Enter any type of writte=
n contract and<br>b)=C2=A0Not keep a copy of the contract, forget about it,=
=C2=A0and <br>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 g=
et carried out?<br><br>One would be insane to enter such a contract in the =
real world.<br><br>I realize that some vendors are currently not stateful, =
but I take this as an unfortunate fact, because multisig wasn&#39;t a prior=
ity 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.<br><br>Since you me=
ntioned Trezor, I want to thank Pavol in particular here, because as Trezor=
 CTO Pavol knows best that Trezor is currently stateless, but he&#39;s stil=
l on-board with the general idea here, AFAIU.=C2=A0<br><br>Bottom line: IMO=
, signers in a multisig MUST be stateful.<br><br></div><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(2=
04,204,204);padding-left:1ex"><p dir=3D"ltr" style=3D"line-height:1.38;marg=
in-top:0pt;margin-bottom:0pt"><span style=3D"background-color:transparent">=
<span style=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"><span st=
yle=3D"font-size:11pt">This existing vulnerability in stateless wallets is =
particularly bad for hosted multisig services like Casa/Unchained, where th=
e service might control m-1 keys. It=E2=80=99s far easier for a hosted serv=
ice to potentially trick non-expert users into displaying an attacker&#39;s=
 receive address on their stateless Signer.</span></span></span></span><br>=
</p><div><br></div><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;=
margin-bottom:0pt"><span style=3D"background-color:transparent"><span style=
=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"><span style=3D"font=
-size:11pt">For example, assume the user is doing 2-of-3 multisig, where th=
e Coordinator (service) controls 1 key. Here is how the Coordinator could t=
rick their end-users:</span></span></span></span><br></p><ol><li dir=3D"ltr=
"><span style=3D"background-color:transparent"><span style=3D"color:rgb(0,0=
,0)"><span style=3D"font-family:Arial"><span style=3D"font-size:11pt">Coord=
inator swaps out 1 of the end-user=E2=80=99s xpubs, going from a 2-of-3 whe=
re the end-user has 2 seeds to a 2-of-3 where the Coordinator has 2 seeds.<=
/span></span></span></span><br></li><li dir=3D"ltr"><span style=3D"backgrou=
nd-color:transparent"><span style=3D"color:rgb(0,0,0)"><span style=3D"font-=
family:Arial"><span style=3D"font-size:11pt">The end-user logs into the ser=
vice to get a new receive address, and the service (Coordinator) displays m=
alicious receive address X (as part of a 2-of-3).</span></span></span></spa=
n><br></li><li dir=3D"ltr"><span style=3D"background-color:transparent"><sp=
an style=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"><span style=
=3D"font-size:11pt">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!</span></span></span></span><br></li><li dir=3D"ltr"><span style=
=3D"background-color:transparent"><span style=3D"color:rgb(0,0,0)"><span st=
yle=3D"font-family:Arial"><span style=3D"font-size:11pt">The end-user doesn=
&#39;t verify the address on Signer 2, as many users unfortunately don&#39;=
t -- perhaps it is in a far away location and the end-user (incorrectly) th=
inks that it=E2=80=99s already been validated in 2 places -- and makes a la=
rge deposit to receive address X. These funds now belong to the attacker an=
d can be swept at any time!</span></span></span></span><br></li></ol><p dir=
=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span =
style=3D"background-color:transparent"><span style=3D"color:rgb(0,0,0)"><sp=
an style=3D"font-family:Arial"><span style=3D"font-size:11pt">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 t=
he end-user that it did not have enough info to properly validate the addre=
ss).</span></span></span></span><br></p><div dir=3D"ltr"><br></div><div dir=
=3D"ltr"><span style=3D"background-color:transparent"><span style=3D"color:=
rgb(0,0,0)"><span style=3D"font-family:Arial"><span style=3D"font-size:11pt=
">This is also a concern for self-hosted multisig, I just used the hosted s=
ervices as the best example.</span></span></span></span><br></div><div dir=
=3D"ltr"><br></div><div dir=3D"ltr"><span style=3D"background-color:transpa=
rent"><span style=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"><s=
pan style=3D"font-size:11pt">It&#39;s also not just Trezor that is stateles=
s. For example, I wrote <a rel=3D"nofollow" title=3D"https://twitter.com/mf=
laxman/status/1321503036724989952" href=3D"https://twitter.com/mflaxman/sta=
tus/1321503036724989952" target=3D"_blank">a simple CLI software multisig w=
allet as part of the buidl library</a>=C2=A0to be used mostly for emergency=
 recovery. At 800 lines of code, it&#39;s too simple/minimal to touch the f=
ile system.</span></span></span></span><br></div><div dir=3D"ltr"><br></div=
><div dir=3D"ltr"><span style=3D"background-color:transparent"><span style=
=3D"color:rgb(0,0,0)"><span style=3D"font-family:Arial"><span style=3D"font=
-size:11pt"><b>BIP39</b></span></span></span></span><br></div><div dir=3D"l=
tr"><br></div><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt=
" dir=3D"ltr"><span style=3D"background-color:transparent"><span style=3D"c=
olor:rgb(0,0,0)"><span style=3D"font-family:Arial"><span style=3D"font-size=
:11pt">While unrelated, the use of BIP39 words for session tokens seems lik=
e 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 B=
IP39 mnemonic and not their seed phrase BIP39 mnemonic! My suggestion is to=
 just stick with the other two Token options: decimal and hex.</span></span=
></span></span></p></blockquote><div><br>Repost of my previous response. We=
 discussed this at length on the linked=C2=A0Github PR:<br>&quot;We decided=
 to keep the TOKEN at 6-9 words, not 12 or anything above precisely for thi=
s reason. Please note that the user has to back up their Signers first, bef=
ore proceeding to setting up the multisig wallet. So there&#39;s no writing=
 both things down at once or mixing of the two flows here.<br><br>I also fi=
nd it hard to believe that someone who wants to invest in a safe multisig s=
olution (and therefore must know at minimum what keys and multisig represen=
t) 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 mnem=
onic at all.&quot;<br><br>We also made the decimal format, not BIP39 mnemon=
ic, the recommended encoding in the spec.<br><br>Best,<br>Hugo<br>=C2=A0</d=
iv></div></div>

--0000000000000b20c905bfb51f60--