Signmessage doesn’t work with segwit addresses #10542

issue karelbilek openend this issue on June 6, 2017
  1. karelbilek commented at 5:06 pm on June 6, 2017: contributor

    Describe the issue

    Signmessage doesn’t work on “segwit addresses” (what BIP141/BIP49 calls “P2WPKH-nested-in-P2SH”).

    Steps to reproduce

    On testnet (or on litecoin :)):

    1. NEW_ADDRESS=$(bitcoin-cli getnewaddress)
    2. SEGWIT_ADDRESS=$(bitcoin-cli addwitnessaddress $NEW_ADDRESS)
    3. bitcoin-cli signmessage $SEGWIT_ADDRESS "shiny"

    Expected behaviour

    Signature is printed

    Actual behaviour

    0error code: -3
    1error message:
    2Address does not refer to key
    

    What version of bitcoin-core are you using?

    v0.14.1

    self-compiled from github repo

    Machine specs:

    • OS: Linux
    • CPU: can reproduce on x86 and x64 CPUs
  2. fanquake added the label RPC/REST/ZMQ on Jun 6, 2017
  3. karelbilek commented at 5:53 pm on June 6, 2017: contributor

    Looking at the code, it seems to me that verification will have the exact same problem. That is,

    addr.GetKeyID(keyID)

    will return false.

  4. achow101 commented at 6:05 pm on June 6, 2017: member
    The address is a p2sh address, it doesn’t have an associated public or private key to sign and verify messages with.
  5. karelbilek commented at 6:07 pm on June 6, 2017: contributor

    I don’t understand

    It does have associated private key - the same private key as the first address I get from bitcoin-cli getnewaddress. I was under the impression that is what addwitnessaddress does (as was explained to me here - https://bitcoin.stackexchange.com/questions/52961/can-i-get-the-wallet-in-bitcoind-to-use-p2sh-segwit-on-testnet )

  6. achow101 commented at 6:21 pm on June 6, 2017: member
    Yes, but it is still technically a P2SH address and is treated as such. The underlying script has a private key associated with it, but not the address itself.
  7. sipa commented at 6:29 pm on June 6, 2017: member

    The confusion here comes from the ambiguitiy in whether an address is an identifier of a key, or a shorthand for a script.

    In the time when there was only one type of addresses, this was an innocent confusion to have: every address was indeed a shorthand for a P2PKH script, but also uniquely identified a private/public keypair. This is exploited in the signmessage command. It works with keys, not addresses, but uses addresses to refer to these keys.

    Since P2SH, and certainly now with P2WSH/P2WPKH, this no longer works. You can’t sign with an arbitrary P2SH address - even if you have the key for it - since the receiver wouldn’t have the public key to verify with.

  8. luke-jr commented at 6:45 pm on June 6, 2017: member

    IMO it is intentional that the old sign/verify message does not work with P2SH/newer addresses. If someone wants to do message signing as a non-obsolete thing, I would recommend writing a BIP that specifies how to handle it for newer address formats, and fixes the confusion surrounding it (I have seen people try to use signed messages to prove they sent bitcoins, which the current stuff does NOT prove.)

    In the meantime, perhaps verifymessage ought to throw an error rather than returning false?

  9. karelbilek commented at 6:46 pm on June 6, 2017: contributor

    You can’t sign with an arbitrary P2SH address

    But you can sight with your P2SH address that you have private key to, right?

    And similarly, if the receiver knows that the address is “nested witness address”, he can check whether a given public key belongs to that address.

    I am not talking about arbitrary P2SH addresses, but really when the receiver knows it’s “nested witness” address.

  10. achow101 commented at 6:52 pm on June 6, 2017: member

    But you can sight with your P2SH address that you have private key to, right?

    No, you can’t.

    And similarly, if the receiver knows that the address is “nested witness address”, he can check whether a given public key belongs to that address.

    I am not talking about arbitrary P2SH addresses, but really when the receiver knows it’s “nested witness” address.

    There is no way for the software that is verifying the signature to know whether the public key corresponds to a nested-p2wpkh address. It simply does not know what p2sh address it would correspond to since a public key can be a part of multiple p2sh addresses. The reason it works for p2pkh is because a public key can only correspond to one p2pkh address.

  11. karelbilek commented at 6:57 pm on June 6, 2017: contributor
    Oh. I thought (pubkey) -> (nested-p2wpkh address) function is deterministic, based on BIP 141.
  12. sipa commented at 6:59 pm on June 6, 2017: member

    Oh. I thought (pubkey) -> (nested-p2wpkh address) function is deterministic, based on BIP 141.

    It is.

    And it would in theory be possible to make signmessage work for a P2SH-P2WPKH address, in cases where the verifier knows the embedded pubkeyhash already. But in that case you don’t need “sign with a witness address” functionality - you could just sign with the embedded key (see validateaddress), and have the verifier check that.

    The point is to not further the misunderstanding that signmessage signs with an address - it never did. It signs with a keyhash, and verify with a keyhash.

  13. karelbilek commented at 8:01 pm on June 6, 2017: contributor

    So, in theory, the current behaviour could be “emulated” by using some different format, where the address would have to be P2SH-PWPKH and the pubkeyhash would be the part of the signature somehow.

    However, that would need some new standards for the new types of addresses, as @luke-jr noted. And it’s a question if it’s worth it.

    Got it. Thanks for the comments. Should I close the issue now?

  14. karelbilek commented at 9:41 pm on June 6, 2017: contributor

    nope I still misunderstood all the formats, sorry. It could still be possible now I think.

    Since you have to recover pubkey from the signature right now, you can go to pubkeyhash and scripthash, given you somehow know the script format (in this case, p2sh-p2wpkh).

    The signer would sign the message with his private key; the verifier would try that the pubkey in the signature generates the given address through p2sh, which would mean the signature is valid.

    The only problem I can think of is that you are then proving both the ownership of the p2pkh and the p2s-p2wpkh addresses, but it doesn’t really matter.

  15. gmaxwell commented at 9:41 pm on June 6, 2017: contributor

    We constructed a new kind of signmessage for elements which is conceptually a lot better and supports arbitrary scripts– but it immediately runs into a problem that softfork semantics only work within the context of a consensus network… it’s not clear how to handle them.

    E.g. if a new softfork is defined on bitcoin and you make a pubkey that uses it… old verifiers need to return indeterminate– before segwit script versioning this was intractable but it could be done now.

  16. karelbilek commented at 6:22 pm on July 17, 2017: contributor

    just for interest - our users (Trezor) are asking for this feature (on Litecoin addresses) and we will maybe have to write some custom format for this

    see discussion here

    https://github.com/trezor/trezor-mcu/issues/169

  17. prusnak commented at 11:12 am on July 18, 2017: contributor

    trezor/trezor-mcu#169

    TL;DR: As a quick solution we are thinking about using introducing more v values to distinguish among various address formats:

    35-38 p2sh segwit pubkey (base58) 39-42 segwit pubkey (bech32)

  18. karelbilek commented at 5:37 pm on July 25, 2017: contributor
    sign/verify for p2wpkh-in-p2sh is now implemented in trezor firmware (only in code now). See the linked discussion.
  19. Sjors commented at 12:43 pm on December 9, 2017: member
    New dev mailinglist discussion here.
  20. jakubtrnka commented at 3:17 pm on December 18, 2017: none
    I’m currently working on it
  21. prusnak commented at 3:24 pm on December 18, 2017: contributor
    @jakubtrnka working on what?
  22. karelbilek commented at 3:24 pm on December 18, 2017: contributor
    @jakubtrnka are you working on BIP?
  23. sipa commented at 7:34 pm on December 18, 2017: member

    @prusnak I’m totally fine with extending signmessage using just new header bytes as you’re suggesting:

    35-38 p2sh segwit pubkey (base58) 39-42 segwit pubkey (bech32)

    As SegWit keys are always compressed you only need 4 for each, indeed.

  24. jakubtrnka commented at 9:51 pm on December 18, 2017: none
    @karel-3d @prusnak At first I’m going to implement verification for P2SH encapsulated P2WPKH. If that works then also “signmessage”. This is not a problem. ECDSA enables to recover public key from signature as described in § 4.1.6 . is actually very similar procedure of how “normal” message/address verification works, am I right? The public key is reconstructed from signature, hashed and compared. Right now the only way I found to verify such signatures is in Trezor web wallet. I didn’t find anyone else working on this.
  25. NilByte commented at 11:48 am on February 11, 2018: none
    Shouldn’t this be assigned to someone? Seems pretty important not to leave those migrating to SegWit addresses at a disadvantage compared to those sticking to legacy addresses.
  26. Willtech commented at 1:21 pm on March 13, 2018: contributor

    Please add the following reference to the use cases for this important feature in the GUI and add the appropriate tags/labels:
    https://bitcoin.stackexchange.com/a/72281/75001

    The desired result for this use case is that a message can be signed for any address in a given wallet verifying that the signer does indeed have the priv key for a given signing address in their wallet and, the balance of said address can then be inspected using blockchain.info or similar. Important for proof of holdings.

    I do not expect that blockchain.info will necessarily let you lookup the base address for a SegWit or Bech32 address? I can understand that it may be necessary for this use to possibly provide an additional field for the encoded resultant address (can be automatically populated) which if used should and different to the signing address (using GUI terminology) should be verified to be a correct resultant against the signing address or equal to it and, appended to the message before signing. The signed message will then be increased by two new lines and one address. (hopefully in the format bitcoin:{address}) This will need a mechanism to prevent fraud. - Or, can blockchain.info be updated to work if it currently won’t?

    Does blockchain.info show balances for addresses that are in cold storage?

    Yes.

    … is there any way for me in another country to confirm that what my colleague views is actually accurate and correct?

    Since they use Bitcoin Core, yes, there is a way to verify that they hold the addresses that they claim. Have them sign a message with each address that they claim to have the holdings on, using Bitcoin Core you can verify that they indeed have those addresses and check them on blockchain.info to find the current balance.

    Only works in Bitcoin Core currently for addresses starting with a ‘1’ (not Segwit addresses starting with a ‘3’ and not Bech32 addresses starting with ‘bc1’ - the developers are aware of this and I will remind them shortly.)

    In Bitcoin Core, your transaction opposite goes to File -> Sign Message and signs any message with one of the holding addresses. Copy the message, address and signature and send to you via probably plain text format email is the easiest. Repeat for each additional address holding the balance of BTC that they are offering to sell.

    In Bitcoin Core, you go to File -> Verify Message and key the details provided EXACTLY - spaces, new lines and all characters must be an EXACT match. Click on verify and voilà.

    I prefer the form of signed message as follows (don’t key the top and bottom bar rows for the message, just the contents and you can check this yourself, the bottom row is the signature). I like to key the address used for verifying as a part of the message but that is not strictly necessary:

    ------------------------------
    Something that I want to sign.
    
    bitcoin:1PMUf9aaQ41M4bgVbCAPVwAeuKvj8CwxJg
    ------------------------------
    Signture:
    IGaXlQNRHHM6ferJ+Ocr3cN9dRJhIWxo+n9PGwgg1uPdOLVYIeCuaccEzDygVgYPJMXqmQeSaLaZVoG6FMHPJkg=
    

    This contains all of the compact information necessary to verify the message.

    Example of verified message:
    verified message

  27. luke-jr commented at 1:28 pm on March 13, 2018: member
    @Willtech Addresses do not have balances at all, and signed messages do not prove what that website claims they do.
  28. EvilJordan commented at 4:18 pm on March 13, 2018: none
    So… this just isn’t going to happen?
  29. Sjors commented at 4:24 pm on March 13, 2018: member
    @EvilJordan we are eagerly awaiting your pull request…
  30. EvilJordan commented at 4:26 pm on March 13, 2018: none
    @Sjors I wish I was smart enough to write one!
  31. Willtech commented at 8:52 pm on March 13, 2018: contributor

    @luke-jr So a signed message does not prove that I have the key for that address in my wallet? And, I cannot use a block explorer like blockchain.info to find the current balance of utxo’s for an address? Feel free to offer a suggested edit to my answer.

    I had hoped this would be easily sorted out after reading earlier the comments by @sipa

  32. luke-jr commented at 8:58 pm on March 13, 2018: member

    @Willtech That’s correct, it does not prove you have the key, only that you are the recipient of any bitcoins sent to it. In particular, shared wallets (eg, MtGox, Coinbase, etc) should and do allow you to sign for your addresses, even though when you send to them, the UTXOs created do not belong to you specifically.

    As with balances, addresses also do not have UTXOs. Once they receive coins, the UTXO created no longer has any relation to the address that received the coins.

  33. Willtech commented at 9:28 pm on March 13, 2018: contributor

    @luke-jr In this case, the person puporting to offer some Bitcoin’s for sale is a Bitcoin Core user. I can understand that the situation may be confusing if the wallet is with a web wallet provider, with address amalgamation and possibly multiple wallet accounts under one key set that you do not own.

    Surely utxo’s stay associated to the receiving address? Okay, once again with web wallets, utxo’s on the receiving address may have no relationship to your balance but, once again, you do not own the priv keys.

    I think that the whole idea of a web wallet is nice for people but I am yet to see an implementation that I like.

  34. luke-jr commented at 9:44 pm on March 13, 2018: member

    The message-verifier cannot prove the message-signer is using any particular software. And it’s not a good idea to rely on accidental/unintended behaviour anyway.

    Addresses are intentionally explicitly opaque and disconnected from UTXOs and balances.

  35. Willtech commented at 9:55 pm on March 13, 2018: contributor

    @luke-jr Okay, but then the message just should not verify if the same message signing rules are not used.

    If I send 1BTC to {address} of mine then utxo does not move until I spend it. That is not opaque, unless you are once again referring to amalgamated web wallets. Utxo balances are distinct from wallet balances.

  36. luke-jr commented at 9:57 pm on March 13, 2018: member
    @Willtech Core does not guarantee the behaviour you assume either. The message signing rules for signmessage guarantee only that the signer will receive coins sent to the address in question. It does not guarantee possession of a balance or UTXOs in any sense.
  37. Willtech commented at 10:00 pm on March 13, 2018: contributor
    @luke-jr How do you sign without the priv key proving ownership of the address and, in the case of a full node wallet, ownership of the utxo’s?
  38. sipa commented at 10:08 pm on March 13, 2018: member
    Owning money and having access to private keys that can spend coins are independent concepts. Exchanges have private keys for UTXOs money they hold on behalf of their customers. They can clearly sign messages using those keys, but they certainly don’t own all those coins.
  39. luke-jr commented at 1:17 am on March 14, 2018: member
    @Willtech I’m not sure what you’re asking. There is no mechanism that supports proving present ownership of UTXOs/coins (for messages, anyway).
  40. Willtech commented at 7:59 am on March 14, 2018: contributor
    Well yes, but I am really only speaking about Bitcoin Core as in the use case. That’s where we are after all.
  41. jakubtrnka commented at 2:47 pm on March 26, 2018: none
    @luke-jr Why would we need to prove ownership of specific UTXO? Neither do I understand how you mean that signature does not prove ownership of keys. I thought the whole idea of message signing is to prove the ability to spend UTXOs associated with specific keys, therefore key hashes, therefore addresses. So why not to allow to verify message-signatures associated with those public keys if it’s possible given whatever address?
  42. dooglus commented at 5:45 am on January 14, 2019: contributor

    When attempting to sign a message with a bech32 address, Bitcoin Core complains that the address doesn’t refer to a key. But it does. As a result I am unable to verify signatures made by users of the Electrum wallet (which can sign using bech32 addresses). I heard the Trezor also has similar functionality.

    I made the following change to allow signing and verifying messages with bech32 addresses in Core. It appears to be compatible with Electrum’s signatures.

    diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
    index 18c867bff..a8e75ddc7 100644
    --- a/src/rpc/misc.cpp
    +++ b/src/rpc/misc.cpp
    @@ -179,7 +179,11 @@ static UniValue verifymessage(const JSONRPCRequest& request)
     
         const CKeyID *keyID = boost::get<CKeyID>(&destination);
         if (!keyID) {
    -        throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
    +        const WitnessV0KeyHash *witnessV0KeyHash = boost::get<WitnessV0KeyHash>(&destination);
    +        if (!witnessV0KeyHash) {
    +            throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
    +        }
    +        keyID = (CKeyID *)(witnessV0KeyHash);
         }
     
         bool fInvalid = false;
    diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
    index 38397a394..a01b17ce8 100644
    --- a/src/wallet/rpcwallet.cpp
    +++ b/src/wallet/rpcwallet.cpp
    @@ -540,7 +540,11 @@ static UniValue signmessage(const JSONRPCRequest& request)
     
         const CKeyID *keyID = boost::get<CKeyID>(&dest);
         if (!keyID) {
    -        throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
    +        const WitnessV0KeyHash *witnessV0KeyHash = boost::get<WitnessV0KeyHash>(&dest);
    +        if (!witnessV0KeyHash) {
    +            throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
    +        }
    +        keyID = (CKeyID *)(witnessV0KeyHash);
         }
     
         CKey key;
    
  43. ripper234 commented at 5:47 am on August 9, 2019: none

    Hi all,

    Any updates on this issue? It’s been 8 months since the last comment.

  44. dooglus commented at 1:59 pm on August 9, 2019: contributor

    If you don’t like my fix in the comment immediately before yours, you can always take a two-step approach. First get the privkey from the address, and then sign your message using the privkey.

    1. dumpprivkey "address"
    2. signmessagewithprivkey "privkey" "message"
    

    If this is something you need to do frequently I’d recommend scripting it. Something like this perhaps:

    signmessage() {
        if [[ $# != 2 ]]; then
            echo "usage: signmessage <address> <message>" 1>&2; return
        fi
    
        address=$1; message=$2
    
        privkey=$(bitcoin-cli dumpprivkey $address)
        if (($?)); then
            echo "error getting privkey" 1>&2; return
        fi
    
        bitcoin-cli signmessagewithprivkey $privkey "$message"
        if (($?)); then
            echo "error signing message" 1>&2; return
        fi
    }
  45. Willtech commented at 2:04 pm on August 23, 2019: contributor
    It seems that some believe the use case for sign message is discredited and intend that nothing will happen, the feature will eventually be removed. FWIW I disagree.
  46. sipa commented at 5:02 pm on August 23, 2019: member
    See #16440.
  47. wspi commented at 2:32 pm on September 2, 2019: none

    If you don’t like my fix in the comment immediately before yours, you can always take a two-step approach. First get the privkey from the address, and then sign your message using the privkey.

    01. dumpprivkey "address"
    12. signmessagewithprivkey "privkey" "message"
    

    If this is something you need to do frequently I’d recommend scripting it. Something like this perhaps:

     0signmessage() {
     1    if [[ $# != 2 ]]; then
     2        echo "usage: signmessage <address> <message>" 1>&2; return
     3    fi
     4
     5    address=$1; message=$2
     6
     7    privkey=$(bitcoin-cli dumpprivkey $address)
     8    if (($?)); then
     9        echo "error getting privkey" 1>&2; return
    10    fi
    11
    12    bitcoin-cli signmessagewithprivkey $privkey "$message"
    13    if (($?)); then
    14        echo "error signing message" 1>&2; return
    15    fi
    16}
    

    @dooglus when you sign with the private key (signmessagewithprivkey), how do you verify it?

    verifymessage is not able to verify it

  48. dooglus commented at 4:13 pm on September 2, 2019: contributor
    @wspi I use this patch to verify it.
  49. SomberNight commented at 6:50 pm on October 25, 2019: contributor

    About BIP322, was any consideration given to light clients? How are they supposed to implement that?

    ISTM that a full-fledged consensus validator and a script interpreter is needed. Only full nodes have that.

    Are light clients expected to do template matching, and otherwise return INCONCLUSIVE to basically everything?

  50. andronoob commented at 12:17 pm on December 28, 2019: none
    I beg your pardon, but, how would future versions of Bitcoin Core/Electrum/Trezor etc deal with the existing signatures of SegWit addressses signed by Trezor or Electrum? Should them be simply treated as invalid in the future, or not?
  51. andronoob commented at 12:22 pm on December 28, 2019: none
    To be frank, I think it has been already quite weird for SegWit addresses to have such a “difference” with legacy addresses, that SegWit cannot do message signing, but legacy addresses can do it.
  52. SomberNight commented at 1:52 pm on December 28, 2019: contributor

    how would future versions of Bitcoin Core/Electrum/Trezor etc deal with the existing signatures of SegWit addressses signed by Trezor or Electrum?

    That does not seem to be a particularly large concern to me. Validators can just test both the old scheme and the new. Old signatures can rather easily be accepted by future validators. ——– Original Message ——– On 28 Dec 2019, 13:17, andronoob wrote:

    I beg your pardon, but, how would future versions of Bitcoin Core/Electrum/Trezor etc deal with the existing signatures of SegWit addressses signed by Trezor or Electrum? Should them be simply treated as invalid in the future, or not?

    — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

  53. dscotese commented at 3:37 am on October 26, 2020: contributor

    I note that @dooglus seems to have shown that this is an issue that can be fixed. I also note that my Mycelium wallet on Android is able to sign a message using a segwit native address, and then verify it, and also fail the verification if I make an edit to the message.

    Is this in a pull request, and if not, why not? @luke-jr and @yllierop reacted to it thumbs-down and confused without explanation or questions.

    The reason this is valuable to me is that signing an address with itself is a good way for someone requesting a withdrawal to prove that they will receive the coins sent to it, and many people, seeing the value of the more compact segwit native addresses will want to use them for such withdrawals.

  54. luke-jr commented at 4:45 am on October 26, 2020: member

    @luke-jr and @yllierop reacted to it thumbs-down and confused without explanation or questions.

    The current signmessage functionality is confusing to users who often think it proves something it does not (specifically, that the signer controls a private key or has ownership of some number of bitcoins). This issue should be addressed (ideally by providing a way to prove what users want to prove) for any new signed message standards (the existing standard only supports “1”-addresses).

    The reason this is valuable to me is that signing an address with itself is a good way for someone requesting a withdrawal to prove that they will receive the coins sent to it, and many people, seeing the value of the more compact segwit native addresses will want to use them for such withdrawals.

    What is the use case for proving you will receive a withdrawl? This sounds like KYC, which isn’t something we want to encourage?

  55. sipa commented at 5:12 am on October 26, 2020: member

    @dscotese The reason for not going with such an approach is that it needs changes every time a new address format/policy gets adopted (like we’ll need one for taproot if/when it starts being used). Furthermore, it’s inherently restricted to single-key addresses which is problematic for multiple reasons (the verifier shouldn’t need to care what the prover uses, and standards limited to single-key uses may disincentivize people from adopting safer multisig construction).

    A proposal to deal with this in a generic way is in BIP322, which has recently picked up some steam. It treats addresses simply as the script they represent, and requires a signature that is verified using the script interpreter itself. This means that in theory it should work for whatever script/address.

  56. dscotese commented at 10:13 pm on October 27, 2020: contributor

    What is the use case for proving you will receive a withdrawl? This sounds like KYC, which isn’t something we want to encourage? It is KYC, but for holding knowledge (the private key), not for an identity attached to a human being. The purpose is that once you prove to me that you have a certain piece of knowledge, you can show that whoever holds that piece of knowledge created a particular lightning invoice for the amount I owe to whoever holds that piece of knowledge, so that once I pay it (and have the preimage from the hash in the invoice), I have solid proof that my debt is paid. The tech I seek is NOT for identification in a way that can be used against people, but in a way that can make payers safe from claims that a payment went to the wrong party. If you know of a better way, please let me know. Thanks!

  57. luke-jr commented at 10:20 pm on October 27, 2020: member

    How does it prove your debt is paid?

    Since you bring up Lightning, wouldn’t it be better actually if you can sign a message as the recipient of a specific Lightning invoice? (Being able to sign as a segwit address recipient doesn’t actually prove anything for Lightning AFAICT)

  58. dscotese commented at 0:43 am on October 28, 2020: contributor

    Say that I have the preimage of an invoice. That proves I paid the invoice, right? Suppose I also have the invoice, and a signature of it. That proves that some data was used to create the signature of an invoice which has been paid (so it doesn’t prove that I paid it, just that it was paid). Suppose the data used to sign the invoice is a private key that belongs to someone. That proves that the owner of that private key signed the invoice. Paying the invoice is not necessarily the same as paying them, so you’re right that it doesn’t prove they were paid. It proves someone was paid and that they got an invoice from that someone. They may be able to invent a reason to sign an invoice that isn’t for a debt to themselves, so perhaps what gets signed needs to be the invoice and a message like “Signing this message and invoice relieves github user dscotese of his debt of ___ to the signer if the invoice gets paid: lnbc…” Of course, people can sign things without them being true, so it still doesn’t prove anything, but I would have proof that they provided me with instructions to pay off my debt, and I followed them. The rest, I think, would be on them.

    Does that answer the question?

    If I sign a message as the recipient of a Lightning Invoice (which I then pay), that doesn’t prove that the invoice came from the person I owe, so that wouldn’t be better. I may have misunderstood something. I want to prove that the invoice came from the person I owe. In order to recognize them, I asked for a public key when we first met. If I get something signed with that key, I know the something was seen and approved by the right person.

  59. luke-jr commented at 1:09 pm on October 28, 2020: member
    Signed messages don’t prove anything about the private key.
  60. NilByte commented at 4:38 pm on October 28, 2020: none

    How is this supposed to be interpreted then?

    Capture

  61. luke-jr commented at 4:54 pm on October 28, 2020: member
    Exactly as it says? The signature proves the message is signed by the person bitcoins sent to the address will belong to. Nothing more.
  62. dscotese commented at 6:59 pm on October 29, 2020: contributor

    Signed messages don’t prove anything about the private key.

    It’s assumed that the private key is owned by the person who does the signing. Ownership is an important aspect of some things, private keys being one of them, as I view things. I think you meant something else, but I can’t figure out what.

  63. sipa commented at 7:08 pm on October 29, 2020: member

    I think what Luke means is this, but correct me if I’m wrong:

    Signing a message with an address proves that whoever can spend money sent to that address agrees with that message.

    Since currently the only supported address types are ones that correspond to a single-key policies, that indeed implies that a message signature also corresponds to “the holder of the private key corresponding to said address agrees with the message”. This is however just a technicality. In BIP322 you can have message signatures from a multisig address (where just a threshold signs, and there is no “the” private key), or if you’d have an address that corresponds to script OP_TRUE, anyone would be able to “sign” for it, as anyone would be able to spend from it.

    So I think the point is that in an ideal world, someone verifying a message signature shouldn’t know or care about the fact that there is a single private key corresponding to that address. Due to a current implementation detail that is however still the case in practice.

  64. luke-jr commented at 8:07 pm on October 29, 2020: member

    It’s assumed that the private key is owned by the person who does the signing.

    This assumption is wrong. Third party and shared wallets are supposed to allow users to sign messages with the addresses they deposit/receive with.

  65. EndrII commented at 2:41 pm on April 10, 2021: none
    Any news about fix this issue?
  66. karelbilek commented at 4:24 am on April 12, 2021: contributor

    I’m no longer involved in Bitcoin so I am not sure.

    But I think the consensus here is - btc developers don’t like “sign message” feature for conceptual reasons (I’m not sure if for a good reason but I don’t care that much anymore :D ), they grudgingly keep it working on “legacy” addresses because of backwards compatibility, and they won’t add it for new address formats.

    So I don’t think this will ever get fixed. I’ll keep it open because some folks always come and say they want it, so, whatever.

  67. EndrII commented at 6:16 am on April 12, 2021: none
    oh no, its very useful feature causerie this is only method for confirming that a person is my payer,
  68. sipa commented at 6:20 am on April 12, 2021: member
    There is on-and-off work on BIP322, which should provide this function for all types of addresses (segwit, and future ones), but there isn’t much progress on it right now.
  69. EndrII commented at 6:22 am on April 12, 2021: none
    @sipa thanks. I hope this will be implemented soon, as this function is very important to me at the moment.
  70. luke-jr commented at 4:31 pm on April 12, 2021: member

    oh no, its very useful feature causerie this is only method for confirming that a person is my payer,

    That’s half the point to not extending this further: This feature DOESN’T confirm a person is your payer!

  71. ghost commented at 5:11 pm on April 12, 2021: none

    This feature DOESN’T confirm a person is your payer!

    I have read all the comments in this issue and now I am confused. I have used this in Electrum few times. One example:

    Poloniex support asked me to sign message with a bitcoin address which was used for withdrawal in past. I had issues accessing my account so this was done to verify I own this Poloniex account without doing any KYC.

    Signing message with a bitcoin address and verifying it is possible right now using Electrum wallet and even Joinmarket added it in https://github.com/JoinMarket-Org/joinmarket-clientserver/pull/841

    So what is being used when users sign the message in electrum and what is being verified? Can someone else sign a message with this bitcoin address using Electrum? tb1qr3m8k7ps0cehz6dcwz0fyhsdv9h9dlcmxusz4m If yes, then maybe signing option is useless. If no, it does prove that I own the private key for this address isn’t it? Or at least I am willing to associate myself with this bitcoin address and someone can send me BTC to the address used for signing.

    I understand this comment and it makes sense: #10542 (comment) and also comment by sipa that there is no public key to verify for segwit addresses.

    Again two questions:

    1. Then how is it working in Electrum and Joinmarket?
    2. Is this a workaround? To sign messages with private key: #10542 (comment) and verify with #10542 (comment) ?
  72. sipa commented at 5:47 pm on April 12, 2021: member

    @prayank23 Presumably @luke-jr is referring to the fact that a signature with address A and message M means that whoever has control over address A (i.e. the ability to move coins sent to that address) agrees with that message. You can’t use it to determine who the sender is however, because Bitcoin addresses do not have a sender address; they only have input coins and those coins may have an address they were previously under control of. In the case of a service provider that has one wallet shared by multiple users, the apparent “sender” address may belong to a different user (i.e., sending to it would credit someone else). Another example: using “sender” address signatures in a payjoin transaction would permit your joining partners to sign for you, as they too have an address that looks like a “sender”.

    As far as what Electrum and other software does: they’re probably extending the old signmessage format to segwit addresses in an ad-hoc manner (just a bit to indicate “p2wpkh” for example). This is trivial to do, but we’ve been loathe to do something like this, because it doesn’t scale. It cannot support multisig, and would need continuous updates to support new address schemes (e.g. Taproot) leading to a compatibility nightmare. There is a solution to this: BIP322, which defines a signmessage format that works for all address types and all future schemes. However, developmemt seems to have stalled around it.

  73. luke-jr commented at 5:56 pm on April 12, 2021: member

    a signature with address A and message M means that whoever has control over address A (i.e. the ability to move coins sent to that address) agrees with that message

    This isn’t true. The UTXOs created when address A received, may be in a shared wallet, and sent by someone entirely unrelated to address A. And this is by design - it isn’t a bug in the signer.

    Signed messages today prove the message is agreed on by the person who receives with address A. They cannot be used to prove anything about a sender.

  74. sipa commented at 6:01 pm on April 12, 2021: member

    @luke-jr Yes, I agree with what you’re saying; I don’t think I’m saying anything else. A signature with address A means whoever can receive on address A agrees with the message. That implies they are who will receive coins sent there, and have the ability to send them further.

    It does not mean anything about transactions that look like they have “input address” A.

  75. ghost commented at 6:46 pm on April 12, 2021: none

    Thanks @sipa and @luke-jr

    There is a solution to this: BIP322, which defines a signmessage format that works for all address types and all future schemes. However, developmemt seems to have stalled around it.

    Will research more about this. I had a follow up question not sure if it’s offtopic.

    Can signing and verifying of messages be used for 2FA or normal authentication? Example: few darknet websites had this option to save your PGP public key when you sign up and user needs to decrypt random messages on each login which were encrypted using this key. Can bitcoin address replace PGP public key in this case? So a user will add one bitcoin address during registration. A random string is shared on each login, user needs to sign it with bitcoin address and it will be verified for successful authentication.

    LNURL-AUTH is also interesting which can be used to register/login with LN wallet. Not sure about the technical details but few libraries available to test it: https://github.com/fiatjaf/awesome-lnurl#libraries and it involves signing of challenges.

  76. Willtech commented at 6:01 am on January 2, 2024: contributor

    Key is not address is fine the address is a cryptographic construct the feature is to be able to use the address to sign and verify messages.

    I remember Satoshi saying Bitcoin is better because it has chance, you could ask someone to sign a message and reveal a little bit of information.

  77. adiabat commented at 9:06 pm on February 22, 2024: none

    Not sure whether to open a new issue but it probably fits in here.

    Screenshot_2024-02-22_15-41-38

    Maybe some day there will be a way to sign messages again. Until then, could we at least tell users that it’s not supported? For example, changing the top text from “You can sign messages/agreements with your addresses” to “You can sign messages/agreements with your legacy (P2PKH) addresses”

    And changing the error from “The entered address does not refer to a key.” (which is incorrect, as P2WPKH refers to a key just as much as P2PKH does, and I’d say P2TR refers to a key even more!) to “Message signing for segwit addresses (addresses starting with bc1/tb1) is not supported in this version of Bitcoin Core.”

    It’s easy enough to change the error message while it’s unsupported.

    This came to my attention as I was helping someone who was worried that they had lost their keys (a reasonable worry given the red error message!) - they were trying to use the sign message function on an offline computer to make sure their wallet & passwords still worked.

  78. Willtech commented at 12:11 pm on April 4, 2024: contributor

    @adiabat It is supported someone has to work on the feature and produce some programming the repository will publish meeting the consensus

    Why do you think the feature was included in the earlier release?

    Bitcoin is honest and I mean it must be entirely the reason signing a message was introduced was to provide some proof of an owner of an address even when they are communicating privately. The only people who don’t want it are apt to try that anyone cannot provide any proof. Actually if there is proof it is better anyone can look on the public ledger to see that there is proof of a balance.

    Professor. Damian A. James Williamson Wills

  79. Willtech commented at 1:55 pm on April 4, 2024: contributor

    Also, signmessage works in V0.18.1

    https://bitcoincore.org/bin/bitcoin-core-0.18.1/ @NilByte

    How is this supposed to be interpreted then?

    Capture

    Suppose it counts as a signature if you are owner of the private key.

    Professor. Damian A. James Williamson Wills

  80. willcl-ark referenced this in commit 0fea73fc74 on May 2, 2024
  81. hebasto referenced this in commit fb9f150759 on May 7, 2024
  82. hebasto closed this on May 7, 2024

  83. hebasto referenced this in commit 4e56df8f91 on May 7, 2024

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-01 13:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me