5

I Know for the P2PK locking script it was like this

[pubkey] <OP_CHECKSIG>

and then an unlocking script is provided as simple as this:

[sig]

But if it works like this, others can simply grab the [sig] and cash out everything in your address!

Is there some misconceptions I have?

6

When you sign the transaction with your private key, you include the hash of the entire transaction data as a message. This means the signature which is generated is specific to that transaction itself and any modification to the transaction will render the signature invalid. In this case, the user who has signed the transaction has already specified the address to which the bitcoins have to be sent. Any modification in the address will change the message digest, thus invalidating the signature.

Moreover, Bitcoin operates on an UTXO model rather than an account/address based model. Everytime you send bitcoins you consume previously unspent outputs in its entirety and create new unspent outputs. For example, let us say you have 1BTC UTXO. When you want to spend for a 0.1 BTC coffee, you will consume the entire 1 BTC UTXO, send 0.1 BTC to the coffee shop and 0.9 BTC back to yourself. This 0.9 BTC output is different from the 1 BTC output that you controlled previously.

In a transaction, these unspent outputs are specified in the transaction with the identifiers: txid and vout. After the user's transaction gets confirmed, the txid which was referenced in the previous transaction no longer remains unspent. Thus, it is not possible to re-use the same signature even if you are sending to the same addresses again.

| improve this answer | |
  • But from here bitcoin.stackexchange.com/questions/92504/… I got the point that transactions don’t need to be signed, to be signed (the signature Is usually in unlocking script) is the previous outputs. Btw, as OP_checksig only deals with two parameters (pub key and sig) what operations is used to check if the sig does match an entire transaction? – gudako Dec 25 '19 at 9:44
  • OP_CHECKSIG takes as input a signature and a public key from the stack, and replaces them with either a 0 or a 1, depending on whether that signature is valid for that public key, with (simplified) the spending transaction as message. If a script without OP_CHECKSIG (or similar) is used, then indeed the input can be copied to spend any coins on that address. However, this is not under control of the attacker: the receiver would have needed to accept coins on an address that did not have any signature checking operations. – Pieter Wuille Dec 25 '19 at 10:24
  • @PieterWuille does the OP_CHECKSIG check if the signature's signed message is the transaction? – gudako Dec 25 '19 at 10:47
  • 2
    Your question is poorly phrased, as that is not how signatures work, but for all intents and purposes: yes. Signature verification is a function that is given the public key, the signature AND the message (so the message has to be known ahead of time to the verifier, it is not contained in and cannot be extracted from the signature), and returns false or true. In the case of OP_CHECKSIG, the message passed to the verifier is computed based on the data in the spending transaction. – Pieter Wuille Dec 25 '19 at 10:50
1

To elaborate on this part of Ugam Kamat's excellent answer: "When you sign the transaction with your private key, you include the hash of the entire transaction data as a message."

The function that turns the transaction into a hash to be signed is not just any hash function; in the code it's called a "sighash" or "signature hash". Each signature contains encoded flags called "sighashflags" which answer the question: " Which parts of the transaction shall be hashed, and which parts shall be ok to modify without invalidating the signature?"

The way signature hashing works pre-segwit is a bit messy, and I don't remember it well enough to lay it out in detail, but you can find it in the source code for the class CTransactionSignatureSerializer.

Post-segwit, there is a specification for the signature hash function in BIP 143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki . (It also describes some of the issues the old version a bit, under "motivation")

The SIGHASH_NOINPUT proposal (see e.g. https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki , although I'm not sure how current that is) would allow a new type of signature hashing, which does not include the transaction inputs into the signature. This would, in fact, allow the same signature to be reused multiple times to cash out coins from the same address! HOWEVER, there are still restrictions that would make it not as bad as you fear: (1) The outputs are still signed, so the person replaying the signature can't change the destination of the coins. (2) The signer has to CHOOSE to use this mode; an attacker can't change the sighashflags of a signature.

Even despite those restrictions, there were concerns that people could be harmed by using this mode without understanding all the possible consequences. I'm not sure what the current state of the proposal is.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.