wizardsardine / liana

The missing safety net for your coins
https://wizardsardine.com/liana
BSD 3-Clause "New" or "Revised" License
305 stars 53 forks source link

Handle compatibility w/ airgapped QRCode communicant wallet #539

Open pythcoiner opened 1 year ago

pythcoiner commented 1 year ago

I open this issue for brainstorm about the optimal workflow for signing with airgapped wallet using communication over QRCode scanning (Seedsigner/Jade/SpecterDIY/???)

I think for now only specter DIY handle miniscript ( but seedsigner also use embit 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.

pythcoiner commented 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
pythcoiner commented 1 year ago

few remarks:

pythcoiner commented 1 year ago

after a quick check i found this crate implementing Blockchain Commons UR Types

edouardparis commented 1 year ago

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.

pythcoiner commented 1 year ago

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>
pythcoiner commented 1 year ago

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 ?

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.

pythcoiner commented 1 year ago

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.

pythcoiner commented 1 year ago
  • 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 the their/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.

pythcoiner commented 1 year ago
  • 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'.

bigspider commented 1 year ago

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.

bigspider commented 1 year ago

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).

pythcoiner commented 1 year ago

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.

pythcoiner commented 1 year ago

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!

pythcoiner commented 1 year ago

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:

pythcoiner commented 1 year ago

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
edouardparis commented 1 year ago

Thanks for the information, very interesting! I will try to have a look before the end of the week

seedhammer commented 11 months ago

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).

shannona commented 11 months ago

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

FoundationKen commented 11 months ago

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:

https://cbor.io/impls.html

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.

seedhammer commented 11 months ago

We've posted a sketch BIP: https://github.com/BlockchainCommons/Research/issues/135.

seedhammer commented 11 months ago

For everyone interested in joining the discussion, we'll be at the next Gordian Developer community meeting Nov. 1. to present the BIP sketch.

seedhammer commented 8 months ago

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.

seedhammer commented 8 months ago

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:

pythcoiner commented 8 months ago

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?

pythcoiner commented 8 months ago

btw i'm interested to have @bigspider thought about this BIP proposal

bigspider commented 8 months ago
  • 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).

bigspider commented 8 months ago

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.

pythcoiner commented 8 months ago

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.

seedhammer commented 8 months ago
  • 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?

pythcoiner commented 8 months ago

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.

bigspider commented 8 months ago

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.

seedhammer commented 8 months ago

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.

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.

pythcoiner commented 8 months ago

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)

pythcoiner commented 8 months ago

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?

seedhammer commented 8 months ago

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.

pythcoiner commented 8 months ago

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

seedhammer commented 8 months ago

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.

seedhammer commented 8 months ago

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 ?