Open pythcoiner opened 1 year ago
my first draft implementation of miniscript workflow on seedsigner is available here, the flow can be summarized as:
graph TB
classDef user fill:#3c3d3e, color:#fff;
classDef test fill:#46d367, color:#000;
classDef signer fill:#7fd310, color:#000;
classDef wallet fill:#ffaa7f, color:#000;
L1(user action)
L1:::user
L2(wallet action)
L2:::wallet
L3(signer action)
L3:::signer
L4{signer\nlogic}
L4:::test
L5[signer display]
graph TB
classDef user fill:#3c3d3e, color:#fff;
classDef test fill:#46d367, color:#000;
classDef signer fill:#7fd310, color:#000;
classDef wallet fill:#ffaa7f, color:#000;
W0(Display descriptor QR)
W0:::wallet -->
S0(Scan descriptor)
S0:::signer -->
S1{has PoR?}
S1:::test
S1 -- yes --> S10[Check policy alias] -- ACK --> S11
S1 -- no --> S20[Check policy] -->
U21(User control policy)
U21:::user -- ACK -->
S22[Save?] -- save --> S210[Display descriptor + PoR QRCode]
S210 --> W00(Scan descriptor + PoR)
W00:::wallet --> W000(store PoR)
W000:::wallet
S22 -- continue --> S11[Scan PSBT]
S210 -- continue --> S11 -->
W12(Display PSBT QR)
W12:::wallet -->
S13(Scan PSBT)
S13:::signer -->
S14[Show PSBT details] -->
U15(check psbt)
U15:::user -- ACK -->
S15(sign PSBT)
S15:::signer -->
S16[Show signed PSBT QR] -->
W17(Scan signed PSBT)
W17:::wallet -- broadcast --> W18(Broadcast)
W18:::wallet
few remarks:
1) I think to UX improvements we need to split this process into 2 parts:
A) Liana supply JSON data (descriptor w/out PoR) encoded into Multi QRCode for descriptor registration purpose
{
"label": "liana",
"descr_alias": <descriptor alias>,
"descriptor": <descriptor>,
"por": "",
"keys_aliases": {
<alias1>: <Xpub1>,
<alias2>: <Xpub2>,
<alias3>:<Xpub3>,
},
}
here the por
(Proof of Registration) field is left empty, then the signer will understand we only want to run the descriptor registration process
B) Liana supply JSON data (descriptor w/ PoR + PSBT) encoded into Multi QRCode for PSBT signing purpose
{
"label": "liana",
"descr_alias": <descriptor alias>,
"descriptor": <descriptor>,
"por": <PoR>,
"keys_aliases": {
<alias1>: <Xpub1>,
<alias2>: <Xpub2>,
<alias3>:<Xpub3>,
},
"psbt": <PSBT>,
}
For A)
and B)
:
"keys_aliases" is a dict of key:value
pair where the key is the alias and the value is the Xpub, these data can be used for UX improvement on signing device side (for example display the sending path: and_v(v:pkh(Alice),older(65535))
instead and_v(v:pkh([842a626e/48'/1'/0'/2']tpubDENBboujRvpkS8SgZsrpqG2BCUBoaAc4c57jHFe1NwKAtfVjDZDUadQKYv4pkAEF2afPv6TtQ2BoYFJAPLbuKpL1usiySERZekGo4JmnWhh/<0;1>/*),older(65535))
)
2) Regarding QR data encoding, the amount of data transferred is not huge. Still, almost the air-gapped signing devices have pretty low-resolution screens & cameras, so data should be sent through dynamic multi QRCodes rather than a single 'big' QRCode, AFAIK, there is 2 encoding used by air-gapped signing devices:
Specter
format used by Specter DIY
and SeedSigner
, this encoding is pretty simple and we just had to split
the data in several chunks of fixed size and add a p<m>of<n>
label as header.Blockchain Commons UR Types
format is used by almost all air-gapped signing devices (including Blockstream Jade
and SeedSigner
), this encoding looks quite more complex (I don't dig deep into this format implementations, but it use CBOR-encoded data structures ), and I don't know whereas there is some Rust
implementation of it (SeedSigner used the Foundation and selfcustody implementations togetherafter a quick check i found this crate implementing Blockchain Commons UR Types
Thank you very much for the investigative work !
The label
field usage is not clear for me. Can it be removed or is it part of a communication standard ?
If i understand correctly descriptor_alias
would be equivalent of the wallet name
required by a Ledger device, so as a open question: can we rename it for wallet_name
or is it bad naming ?
keys_aliases
seems to be a good improvement for descriptor readability but we need to be careful as device cannot trust laptop and user must verify external xpubs.
alias
:key
with hopefully the their
/our
labeling like ledger is doing
Requirement for this labeling would be that Seedsigner loaded the seed before registering the descriptor, which is maybe obvious because Seedsigner needs to provide a PoR by signing the data with a key. About the label field, I just left it there because it is used by seedsigner QRCode decoding function to determine that the data are representing a descriptor.
I just check to export some wallet descriptors from Sparrow
via QRCode:
To Specter Desktop
(single sig) (single QRCode):
{
"label": "pythcoiner",
"blockheight": <block_height>,
"descriptor": "wpkh([<fingerprint>]<xpub>)#<checksum>"
}
To Specter Desktop
(multi-sig) (single QRCode)
{
"label": "pythcoiner",
"blockheight": <block_height>,
"descriptor": "wsh(sortedmulti(2,[<fingerprint>/48h/0h/1h/2h]<xpub>,[<fingerprint>/48h/0h/1h/2h]<xpub>))#<checksum>"
}
To Specter DIY
(multi-sig) (single QRCode):
addwallet pythcoiner&wsh(sortedmulti(2,[<fingerprint>/48h/0h/1h/2h]<xpub>,[<fingerprint>/48h/0h/1h/2h]<xpub>))
To Passport
/Blockstream Jade
/Keystone
(multi-sig) (UR:Bytes format encoding):
# <Wallet Name> Multisig setup file (created by Sparrow)
#
Name: pythcoiner
Policy: 2 of 2
Derivation: m/48'/0'/1'/2'
Format: P2WSH
<fingerprint>: <xpub>
<fingerprint>: <xpub>
To Blue Wallet
(multi-sig) (single QRCode):
# Blue Wallet Multisig setup file (created by Sparrow)
#
Name: pythcoiner
Policy: 2 of 2
Derivation: m/48'/0'/1'/2'
Format: P2WSH
<fingerprint>: <xpub>
<fingerprint>: <xpub>
To BSMS
(multi-sig) (UR:Bytes format encoding)
BSMS 1.0
wsh(sortedmulti(2,[<fingerprint>/48h/0h/1h/2h]<xpub>,[<fingerprint>/48h/0h/1h/2h]<xpub>))
/0/*,/1/*
<bc1_adress>
The label field usage is not clear for me. Can it be removed or is it part of a communication standard ? If i understand correctly
descriptor_alias
would be equivalent of the walletname
required by a Ledger device, so as a open question: can we rename it forwallet_name
or is it bad naming ?
As the descriptor shows in my last post, I think it's cleaner to keep only the label
field for the wallet name (Specter
/SeedSigner
) and keep Name
field for other ones.
keys_aliases
seems to be a good improvement for descriptor readability but we need to be careful as device cannot trust laptop and user must verify external xpubs.
Yes, that's why I suggest supplying key aliases as a separate table. In my seedsigner implementation, I not yet handle them (actually, in the registration process, I first display a letter alias (A, B, C, etc) with the xpub, then after displaying the descriptor with xpubs replaced by alias). You can have a look here.
- for descriptor registration, If I understand correctly your proposal: User will first see the template of the descriptor with the keys_aliases and then verify the dict of
alias
:key
with hopefully thetheir
/our
labeling like ledger is doing
I actually display first the alias:xpub
pairs, then the 'simplified' descriptor (alias instead xpubs).
About their
/our
labeling, I do not yet notice that on the Ledger, but obviously it's a good point.
Requirement for this labeling would be that Seedsigner loaded the seed before registering the descriptor, which is maybe obvious because Seedsigner needs to provide a PoR by signing the data with a key.
Right, it's the way I actually follow, the key is needed to check that we have 'control' on at least one xpub prior to building the PoR. About the PoR, what I actually do is first concatenate (mnemonic seed + descriptor + alias) and then hash160(), as @darosior told me (if I understand well), Ledger also doing some king hashing instead of signing (i guess it's faster with Nano limited resources), but I not yet take time to ask @bigspider as I should have.
- for signing process, user just want change outputs to be labelled with the descriptor alias, do we need to display the descriptor content or is it just a nice to have ? My first opinion is to have less information required with the PoR and the descriptor_alias and descriptor are enough.
Actually, if a valid PoR is supplied in QRCode, I just notice the descriptor alias to the user for a check, then label my own spent inputs as 'from me' and outputs as 'to myself'.
Ledger's PoR looks like this:
k = SLIP21Key(m/"LEDGER-Wallet policy")
policy_id = SHA256(wallet_policy.serialize())
policy_hmac = HMAC-SHA256(key = k, message = policy_id)
Note that the serialization (and therefore the policy_id
) also commits to the name of the policy that is shown to the user when they register, not just the descriptor; that's important as it allows to distinguish different policies without the user having to check the descriptor after the registration (as long as they don't register multiple policies with the same name).
HMAC is a lot faster than signing, and it's recommended in this case − no advantage in asymmetric cryptography since the hardware device is both signer and verifier.
There might be some other relevant info about the approach in the BIP proposal: https://github.com/bitcoin/bips/blob/bb98f8017a883262e03127ab718514abf4a5e5f9/bip-wallet-policies.mediawiki − although it doesn't quite focus on the registration part.
Right, it's the way I actually follow, the key is needed to check that we have 'control' on at least one xpub prior to building the PoR. About the PoR, what I actually do is first concatenate (mnemonic seed + descriptor + alias) and then hash160(), as @darosior told me (if I understand well), Ledger also doing some king hashing instead of signing (i guess it's faster with Nano limited resources), but I not yet take time to ask @bigspider as I should have.
En passant: careful with concatenate-and-hash approaches: if you concatenate fields with variable length, it is in general vulnerable to collision attacks. That's solved by length-prefixing anything that is variable length, e.g. for the above: <seed (fixed length)> <length(descriptor)> <descriptor> <length(alias)> <alias>
is guaranteed to not have collisions unless the hash function is broken, while <seed (fixed length)> <descriptor> <alias>
has collisions (probably hard to exploit in this case, but you never know).
Note that the serialization (and therefore the
policy_id
) also commits to the name of the policy that is shown to the user when they register, not just the descriptor; that's important as it allows to distinguish different policies without the user having to check the descriptor after the registration (as long as they don't register multiple policies with the same name).
Thanks for your quick answer, I already commit to the name (alias) of policy and also thinking about committing to the alias of each key.
HMAC is a lot faster than signing, and it's recommended in this case − no advantage in asymmetric cryptography since the hardware device is both signer and verifier.
I need to look more into HMAC (I'm not a math nor crypto guy :sweat_smile:)
There might be some other relevant info about the approach in the BIP proposal: https://github.com/bitcoin/bips/blob/bb98f8017a883262e03127ab718514abf4a5e5f9/bip-wallet-policies.mediawiki − although it doesn't quite focus on the registration part.
Will read it one (many) more time!
En passant: careful with concatenate-and-hash approaches: if you concatenate fields with variable length, it is in general vulnerable to collision attacks. That's solved by length-prefixing anything that is variable length, e.g. for the above:
<seed (fixed length)> <length(descriptor)> <descriptor> <length(alias)> <alias>
is guaranteed to not have collisions unless the hash function is broken, while<seed (fixed length)> <descriptor> <alias>
has collisions (probably hard to exploit in this case, but you never know).
Will care about that, thanks to be in our world Salvatore!
I start working on a rust implementation of an encoder/decoder for QRCode data here (only specter format for now, the next step will be to handle UR format), maybe I should turn it into a WIP PR? @darosior @edouardparis Btw, it's the first time I have implemented something w/ Rust, so feel free to kick my ass if I do some bullshit! :joy:
Here are some notes about UR encoding: Trying export PSBT from sparrow I got 5 UR encoded chunks:
UR:CRYPTO-PSBT/1-5/LPADAHCFADIDCYCHJSBZZEHDFLHKADHEJOJKIDJYZMADAEGMAOAEAEAEADFYDRDLMUFNGLDWMHFZUYDACFTKEYEODLPFFMROLRREFZAXDKRDCTZTJOIAJTMTWDADAEAEAEAEZCZMZMZMADDICTADAEAEAEAEAECMAEBBYTLKMDMUDTSN
UR:CRYPTO-PSBT/2-5/LPAOAHCFADIDCYCHJSBZZEHDFLJSAXRTNDENJNMUJZNSFEHTMDYLWMCAJLDEFWAEAEAEAEGWADAAECLTTKAXETPSWMRFLAAEAEAXEECEKNGLRHFRHLWMMOEEUEHLFGIEYAKNSGFRKNMYSWASMOIYFLGOGRMWTBWYKTZOAOBZGRBTFZFR
UR:CRYPTO-PSBT/3-5/LPAXAHCFADIDCYCHJSBZZEHDFLUEBELAGLBBEMKBNYWFATVTLRAHUEWPWNTPBEHSWFNBKBMTADLYUTBDVEYKJTIHBEONSWRLJTGHAEAELAADAEAELAAXAEAELAAEADADCTPFDIADAEAEAEAEAECMAEBBIDZOCLIOLGROJODKOECWROSN
UR:CRYPTO-PSBT/4-5/LPAAAHCFADIDCYCHJSBZZEHDFLKOROHPRDOETNPSDIKTWDCESAADAXAAADAEAEAECPAMAOVEOEWKSSMDUEBGMTAOPFUYUTHERECABZDATYKPIDLOHHPKCMKGJNLFETVYYLTDKGCSONSWRLJTGHAEAELAADAEAELAAXAEAELAVWDRVTVY
UR:CRYPTO-PSBT/5-5/LPAHAHCFADIDCYCHJSBZZEHDFLAEAEAEAEAEAEAEAEAECPAOAOYNKKHGDEYLKIGUINREJSKINNHPBWUEAXCHHKATDSGDMYFXJOJZADKOHKVDISUOMKCSONSWRLJTGHAEAELAADAEAELAAXAEAELAAEAEAEAEADAEAEAEAEAELFNNKTWT
which might be combined to turn into a PSBT:
cHNidP8BAFICAAAAAUQqL5M8TiyQQNslGc8yMy+wPriEtUADJLof/HBjbpbqAQAAAAD9////AScfAQAAAAAAFgAU+YxxA8CbNm2TbJxFWpX36x1vKEIAAAAATwEENYfPAzis67yAAAADNBx6Trk7XeuSNN5dRmT4eso7eo/GCZJmR1VLlNbud/sCFd4QgE4UN36a8wfghAXe7PHYEGHzoH6WAYHdC+T1bmUQpca3blQAAIABAACAAwAAgAABAR+wJwEAAAAAABYAFGL7IWeNuHAkdrhbuqLarCd36hzCAQMEAQAAACIGAuSi9MSV3hKWArDb3V+1HRUl1HViiFyqFnttgjjh99J7GKXGt25UAACAAQAAgAMAAIAAAAAAAAAAAAAiAgL2eVco931TabVxfZ5bE94DF1kHJlCPQ3BsAXZZ52jcmBilxrduVAAAgAEAAIADAACAAAAAAAEAAAAAcHNidP8BAFICAAAAAUQqL5M8TiyQQNslGc8yMy+wPriEtUADJLof/HBjbpbqAQAAAAD9////AScfAQAAAAAAFgAU+YxxA8CbNm2TbJxFWpX36x1vKEIAAAAATwEENYfPAzis67yAAAADNBx6Trk7XeuSNN5dRmT4eso7eo/GCZJmR1VLlNbud/sCFd4QgE4UN36a8wfghAXe7PHYEGHzoH6WAYHdC+T1bmUQpca3blQAAIABAACAAwAAgAABAR+wJwEAAAAAABYAFGL7IWeNuHAkdrhbuqLarCd36hzCAQMEAQAAACIGAuSi9MSV3hKWArDb3V+1HRUl1HViiFyqFnttgjjh99J7GKXGt25UAACAAQAAgAMAAIAAAAAAAAAAAAAiAgL2eVco931TabVxfZ5bE94DF1kHJlCPQ3BsAXZZ52jcmBilxrduVAAAgAEAAIADAACAAAAAAAEAAAAA
Thanks for the information, very interesting! I will try to have a look before the end of the week
We are very interested in standardizing the format and serialization of wallet setups. Because we're engraving descriptors on steel plates, we're particularly interested in compact encodings.
Some notes:
To our mind, a (new) standard should:
Ideally, also
Given a serialization, the question of QR encoding is a separate concern. Choosing the Commons UR format is a straightforward choice, because it's already in widespread use.
Blockchain Commons UR Types format is used by almost all air-gapped signing devices (including Blockstream Jade and SeedSigner), this encoding looks quite more complex (I don't dig deep into this format implementations, but it use CBOR-encoded data structures ), and I don't know whereas there is some Rust implementation of it (SeedSigner used the Foundation and selfcustody implementations together
Indeed, the UR format is quite complex. However, you can avoid a CBOR encoder by encoding the payload as a CBOR binary blob which is just a byte, a length and the payload itself. The fountain encoding part of UR is another complexity; fortunately it's optional and can be ignored (BlueWallet does this).
Hi @pythcoiner. Even if you're not comfortable with CBOR, the UR structures should be quite usable, because they should hide those CBOR details behind the tagged, interoperable UR format.
We have a comprehensive set of documents on UR here, and admittedly it leans hard on how the UR converts to CBOR, so maybe we need something that talks about just the UR format?
https://developer.blockchaincommons.com/ur/
(Let me know if there's something you think is missing from the docs that would make them more approachable.)
We do have a new set of Rust libraries that are in Community Review, which means we're currently taking feedback on not just how they work, but also whether their API is what you expect, and whether they're doing the job you need.
The UR library is here: https://github.com/BlockchainCommons/bc-ur-rust
The rest of the stack, and a place for any feedback, is here: https://github.com/BlockchainCommons/Gordian-Developer-Community/discussions/116
Hi all! I just want to chime in here with some thoughts. IMO, the BC envelope format is pretty simple in its construction and enables a lot of powerful use cases (that go well beyond descriptors too). This video gives a great overview of some of the possibilities:
https://www.youtube.com/watch?v=OcnpYqHn8NQ
Although the BC envelope standard is not yet widespread, the same would be true of any other new standard we might define. Working with a group like Blockchain Commons to document and manage whatever standard we arrive at is pretty valuable, IMO.
The "complexity" of CBOR is mostly hidden behind existing CBOR libraries, but having implemented a subset of CBOR myself previously, the code is pretty straightforward. Implementations are available for all popular languages, though, so nobody needs to write this code, just the code that builds the messages on top of CBOR:
The other question raised above is whether descriptors should be encoded as strings or as CBOR or in some other binary format. I'm unsure what the motivation was to deprecate the BC CBOR encoding above, but having a deconstructed binary format does seem valuable vs. a string that has to be parsed.
We've posted a sketch BIP: https://github.com/BlockchainCommons/Research/issues/135.
For everyone interested in joining the discussion, we'll be at the next Gordian Developer community meeting Nov. 1. to present the BIP sketch.
Our BIP proposal is here: https://github.com/seedhammer/bips/blob/master/bip-psbt-descriptors.mediawiki. I'm looking into proof of registration and whether it can be added to the proposal or in another.
Ledger's PoR looks like this:
k = SLIP21Key(m/"LEDGER-Wallet policy") policy_id = SHA256(wallet_policy.serialize()) policy_hmac = HMAC-SHA256(key = k, message = policy_id)
Note that the serialization (and therefore the
policy_id
) also commits to the name of the policy that is shown to the user when they register, not just the descriptor; that's important as it allows to distinguish different policies without the user having to check the descriptor after the registration (as long as they don't register multiple policies with the same name). HMAC is a lot faster than signing, and it's recommended in this case − no advantage in asymmetric cryptography since the hardware device is both signer and verifier.
For standardization of proof of registrations, I'm not convinced a symmetric HMAC is the best choice. Some advantages of actual, asymmetric signatures:
For standardization of proof of registrations, I'm not convinced a symmetric HMAC is the best choice. Some advantages of actual, asymmetric signatures:
i think the PoR do not have to be standardized, but the PoR should be an optional field that the software wallet/coordinator can use.
- The coordinator software can ensure that the descriptor has been authorized and not been tampered with.
- The user can transfer the descriptor to other (watch-only or coordinator) devices without worrying about tampering.
to me the only purpose of the PoR field in our context is to allow the signer to 'outsource' the storage of the PoR in the way to stay stateless. nothing else than the signer have to check the PoR is genuine I guess. If the PoR is valid the signer should only not ask user to review the descriptor.
- With MuSig2 (I believe) it's possible to construct a constant sized proof registration that includes all co-signers.
i don't see any reason to doing that as each PoR is the proof the descriptor have been reviewed for a specific private key context, but maybe I missing something?
btw i'm interested to have @bigspider thought about this BIP proposal
- Similar implementation complexity, because the wallet software already includes signing logic.
HMACs (and therefore SLIP-21) are quite easy to implement, much easier than signatures and BIP32 derivations. The running time for BIP32 derivation + signature verification on embedded hardware can be noticeable (tenths of a second), while HMACs ans SLIP-21 are instant even on the weakest hardware. Also, HMAC-256 is only 32 bytes.
- The coordinator software can ensure that the descriptor has been authorized and not been tampered with.
- The user can transfer the descriptor to other (watch-only or coordinator) devices without worrying about tampering.
Both are true for HMACs, too. More generally, when the signer is also the verifier, there is no difference in cryptographic properties between HMACs and signatures.
- With MuSig2 (I believe) it's possible to construct a constant sized proof registration that includes all co-signers.
Even ignoring the implementation complexity, that would force some non-trivial cooperation (and two rounds of communication) among all cosigners for an action that seems inherently an individual action to me (that is: registering a new wallet on a signing device).
i think the PoR do not have to be standardized, but the PoR should be an optional field that the software wallet/coordinator can use.
Some people (e.g. at Unchained Capital, who integrated with them in the context of multisig) did show interest in standardizing the PoR, in order to enable portability across vendors. I think it would be nice in theory, but agreeing on a standard has quite high coordination cost and I'm not sure the benefits in this situation are substantial.
Also, I'm not sure everyone would agree with the approach I chose (fully stateless PoR derived from the seed, unrevocable) versus other approaches, for example:
I don't think revocation is very useful in this context, but surely some people will disagree.
Note that PoR has no use in software wallets - rather, they just have to store it for the hardware signer precisely to protect them from the software wallet.
to me the only purpose of the PoR field in our context is to allow the signer to 'outsource' the storage of the PoR in the way to stay stateless. nothing else than the signer have to check the PoR is genuine I guess. If the PoR is valid the signer should only not ask user to review the descriptor.
+1
btw i'm interested to have @bigspider thought about this BIP proposal
There is definitely some shared grounds between this proposal and the work I've been doing and the approach from wallet policies:
However, I'm wary of adding to the PSBT other purposes other than whatever is needed in signing flows. The design space of all the possible signing flows is already very large and mostly not yet standardized.
A standard to add descriptors/wallet policies to PSBTs should imho:
Unfortunately, any way of adding descriptors to the PSBT inevitably adds redundancy with the existing PSBT fields, as information is going to be duplicated (e.g. it's present among the PSBT fields, but it could also be deduced from the descriptors); that clashes with the desire of minimizing the PSBTs, which seems crucial for QR-based signing flows.
I don't think this redundancy can be avoided without a new PSBT version.
Some people (e.g. at Unchained Capital, who integrated with them in the context of multisig) did show interest in standardizing the PoR, in order to enable portability across vendors. I think it would be nice in theory, but agreeing on a standard has quite high coordination cost and I'm not sure the benefits in this situation are substantial.
Also, I'm not sure everyone would agree with the approach I chose (fully stateless PoR derived from the seed, unrevocable) versus other approaches, for example:
- PoR based on a key stored on the device; not fully stateless, but all PoR can be invalidated if desired
- just store individual registered policies on the device (can revoke individual registration)
I mean I don't think the PoR should be standardized in the BIP proposal from @seedhammer IMHO, to be standardized somewhere else I don't have a strong opinion.
- Similar implementation complexity, because the wallet software already includes signing logic.
HMACs (and therefore SLIP-21) are quite easy to implement, much easier than signatures and BIP32 derivations. The running time for BIP32 derivation + signature verification on embedded hardware can be noticeable (tenths of a second), while HMACs ans SLIP-21 are instant even on the weakest hardware. Also, HMAC-256 is only 32 bytes.
- The coordinator software can ensure that the descriptor has been authorized and not been tampered with.
- The user can transfer the descriptor to other (watch-only or coordinator) devices without worrying about tampering.
Both are true for HMACs, too. More generally, when the signer is also the verifier, there is no difference in cryptographic properties between HMACs and signatures.
How can a watch-only or coordinator without seeds derive the symmetric SLIP21 keys?
- With MuSig2 (I believe) it's possible to construct a constant sized proof registration that includes all co-signers.
Even ignoring the implementation complexity, that would force some non-trivial cooperation (and two rounds of communication) among all cosigners for an action that seems inherently an individual action to me (that is: registering a new wallet on a signing device).
I'm not sure whether it's true in practice, but the idea is that the complexity in implementation and communication rounds is paid during the initial setup of the descriptor among signers anyway.
i don't see any reason to doing that as each PoR is the proof the descriptor have been reviewed for a specific private key context, but maybe I missing something?
AFAIK, a MuSig(2) (or FROST) descriptor can be made constant size regardless of number of co-signers. It would be nice that the PoR be constant size as well.
i think the PoR do not have to be standardized, but the PoR should be an optional field that the software wallet/coordinator can use.
That would be unfortunate, in that we'll lose interoperability among different signer brands. If that's the intent, why not use the PSBT_GLOBAL_PROPRIETARY field?
That would be unfortunate, in that we'll lose interoperability among different signer brands. If that's the intent, why not use the PSBT_GLOBAL_PROPRIETARY field?
my mean your BIP proposal target the communication
level but should not target to care about how is process
the PoR.
as mentioned ealier, in my mind, the PoR is just a way to keep signer stateless
but signer can recognize that the descriptor have already been reviewed (and assigned an alias?) by user
btw i'm also interested to have though from @benma, @scgbckbone about PoR, do you have such thing in your miniscript signing workflow?
@stepansnigirev, i think the specter DIY is not stateless about the PoR thing, but i'm also interested about you though.
@FoundationKen i think miniscript signing is on your roadmap, so interested also by your though.
How can a watch-only or coordinator without seeds derive the symmetric SLIP21 keys?
The PoR is both created and verified by the signing devices, as both actions require access to the private keys. The software wallets / coordinators only store the PoR.
That would be unfortunate, in that we'll lose interoperability among different signer brands. If that's the intent, why not use the PSBT_GLOBAL_PROPRIETARY field?
my mean your BIP proposal target the
communication
level but should not target to care abouthow is process
the PoR.
The BIP should care about format because of interoperability. If I switch hardware signing device models I shouldn't have to redo the PoR.
How can a watch-only or coordinator without seeds derive the symmetric SLIP21 keys?
The PoR is both created and verified by the signing devices, as both actions require access to the private keys. The software wallets / coordinators only store the PoR.
Being able to tell the user from the wallet/coordinator UI that a particular descriptor is signed seems like a useful feature to me.
If I switch hardware signing device models I shouldn't have to redo the PoR.
I think we should have to redo PoR if using key on different HW as some vendor can (maybe) commit to the signer unique id in their PoR calculation process (remember PoR is just prrof that user have rewieved the descriptor)
Being able to tell the user from the wallet/coordinator UI that a particular descriptor is signed seems like a useful feature to me.
I'm interested by the usecase you had in mind?
If I switch hardware signing device models I shouldn't have to redo the PoR.
I think we should have to redo PoR if using key on different HW as some vendor can (maybe) commit to the signer unique id in their PoR calculation process (remember PoR is just prrof that user have rewieved the descriptor)
Good point, but whatever extra data to commit to can be added to the PSBT key data, no?
Being able to tell the user from the wallet/coordinator UI that a particular descriptor is signed seems like a useful feature to me.
I'm interested by the usecase you had in mind?
I would like to verify the integrity of the descriptor when generating receive addresses.
Good point, but whatever extra data to commit to can be added to the PSBT key data, no?
what you mean by 'added to the PSBT key'?
I would like to verify the integrity of the descriptor when generating receive addresses.
in my mind we using Hardware Signers because we assume that our software wallet/ coordinator can be corrupted, if so the corrupted software can display the descriptor as genuine even if not, whatever proof you have.... so user should only trust an adress verified on the Hardware Signer, its less convenient but the only safe way i guess.
here an interesting post from @kloaec around this topic
Good point, but whatever extra data to commit to can be added to the PSBT key data, no?
what you mean by 'added to the PSBT key'?
A PSBT map entry contains two values, the key data and the value data. The extra commitment data could be stored in the key data, and the signature itself in the value data.
I would like to verify the integrity of the descriptor when generating receive addresses.
in my mind we using Hardware Signers because we assume that our software wallet/ coordinator can be corrupted, if so the corrupted software can display the descriptor as genuine even if not, whatever proof you have.... so user should only trust an adress verified on the Hardware Signer, its less convenient but the only safe way i guess.
Using a signer for verifying addresses is a secure way to generate addresses, but has two important downsides: (1) less convenience and (2) temptation to leave the signer in a more exposed location thus increasing the risk of theft.
Consider the cold storage wallet that receives much more often than it spends. I argue its safer to generate addresses by having your signed descriptor on, say, a laptop and a phone and always pairwise compare the generated addresses before using them. The descriptor signature ensures that an attacker cannot tamper with the descriptor in transit.
With respect to the complexity of an asymmetric signature, I suppose we can re-use https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki ?
I open this issue for brainstorm about the optimal workflow for signing with
airgapped
wallet using communication overQRCode
scanning (Seedsigner/Jade/SpecterDIY/???)I think for now only specter DIY handle
miniscript
( but seedsigner also useembit
python library who handle miniscript)An issue also have been open on seedsigner project about that. I'm interested about your thought about which way to go and which way to not go.
i'm doing some experimentation on a seedsigner, will try to show more about that in few days.