4

When a P2PKH transaction is created there are two main parts: the transaction input and the transaction output. I understand that the transaction input requires a signature that unlocks a previous UTXO for that specific address.

So in simple terms we have

transaction = transaction input(UTXO+sig) + transaction output(destination address and amount)

What prevents someone from intercepting the transaction and replacing the 'transaction output' with their own address?

4

Your assumption in the following equation

transaction = transaction input(UTXO+sig) + transaction output is wrong.

Correct would be

transaction = UTXO + sig[tx data + hash(UTXO)] + output

  • UTXO + sig[tx data + hash(UTXO) is added for each input
  • output is added for each output

This is JSON format of transaction that I have recently created and not yet broadcasted. You may notice that it has 1 input and 1 output.

{
    "hash": "7decf07997e58980b666e3cda17d4a930a21c8e99cad84c587a0e59d06b2dc86",
    "ver": 1,
    "vin_sz": 1,
    "vout_sz": 1,
    "lock_time": 0,
    "size": 191,
    "in": [
        {
            "prev_out": {
                "hash": "5cbbbb09f4323badb86d32ef4b8929ce757c078bc399c2ec499daaf8f51c455e",
                "n": 1
            },
            "scriptSig": "304402203a0a2a31e906997d8beed8ca5a81bd303f9fff2475cb0400983eef0fb718a573022069103db03857fb8c7b204e3ed3706ea6fa729708bc85492a7783ca11760a672101 02856209e1b0dfd542898c8a8c58da4a91f9f6a82cddb4157117fe18157fc28c94",
            "sequence": 4294967295
        }
    ],
    "out": [
        {
            "value": "0.00010000",
            "scriptPubKey": "OP_DUP OP_HASH160 c74eb0fc16d79cbf4399c80e7ec07162a41f30c6 OP_EQUALVERIFY OP_CHECKSIG"
        }
    ]
}

As you may know, to prove that you are allowed to spend input of tx you need to provide Digital signature - that is the scriptSig element inside in array.

scriptSig are digitally signed following data:

  • ID (hash) of particular input (prev_out)
  • double SHA of new transaction data

Signing transaction data prevents anyone from executing so called Man-in-the-middle attack and intercept and direct out to their wallet, since they cannot provide correct digital signature for the malformed transaction.

Why not try yourself? Here is the hex of above tx:

01000000015e451cf5f8aa9d49ecc299c38b077c75ce29894bef326db8ad3b32f409bbbb5c010000006a47304402203a0a2a31e906997d8beed8ca5a81bd303f9fff2475cb0400983eef0fb718a573022069103db03857fb8c7b204e3ed3706ea6fa729708bc85492a7783ca11760a6721012102856209e1b0dfd542898c8a8c58da4a91f9f6a82cddb4157117fe18157fc28c94ffffffff0110270000000000001976a914c74eb0fc16d79cbf4399c80e7ec07162a41f30c688ac00000000

You can replace output address c74eb0fc16d79cbf4399c80e7ec07162a41f30c6 with double hash (RIPEDM160(SHA256(K)) of your public key.

Then try to broadcast the malformed tx with http://btc.blockr.io/tx/push to see it is impossible. Or if you are skilled you may use sendrawtransaction <tx hex here> command in bitcoind.

  • I see, so using: UTXO + sig[tx data + hash(UTXO) is added for each input output is added for each output Say that I have two UTXO in an address. one has 3btc which we'll call UTXO_a, the other has 1btc (UTXO_b). so the total in the address is 4btc. Now I want to send 4 btc to a friend's address (ignoring fees). Would that come out as: UTXO_a + sig[tx data + hash(UTXO_a)] UTXO_b + sig[tx data + hash(UTXO_b)] + output(4btc to friend's address) Where the tx data would be the same for both UTXO_a and UTXO_b? and only 1 output is required? Thanks for clearing up the previous misconception :) – Luke Jan 29 '15 at 15:30
  • @Luke - Yes, you are correct. Tx data for signing are the same for each scriptSig. Moreover, fee is calculated as a difference between sum(in) and sum(out) thus additional parameters are not required. – Marek Jan 29 '15 at 15:38
  • Do I understand right, each input has a signature of the whole transaction, including outputs? Why not to use single signature as a separate fields for transaction instead of making a signature of whole transaction on each input? – Vedmant Nov 26 '17 at 12:02
4

The sig part signs the entire transaction, not just the input part. So if someone intercepting the transaction replaced the transaction output part, the sig would no longer be valid. In fact, changing other inputs or outputs or amounts would also render the sig and thus the transaction invalid.

When you sign away an input, you are essentially saying "only this very specific transaction may spend this input".

  • 1
    Unless you sign with SIGHASH_NONE, but nobody does that, because of the attack Luke mentions. – Nick ODell Jan 29 '15 at 15:07

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.