TeachMeBitcoin

Raw DER signature with SIGHASH_ALL appended

From TeachMeBitcoin, the free encyclopedia Reading time: 2 min

11. SIGHASH_ALL — Signing All Inputs and Outputs

Overview

SIGHASH_ALL (value 0x01) is the default and most common sighash type. A signature using SIGHASH_ALL commits to every input and every output in the transaction, ensuring nothing can be changed without invalidating the signature.

What SIGHASH_ALL Commits To

Commits to:
✓ All inputs (their outpoints/txid:vout references)
✓ All input sequences
✓ All outputs (values and scripts)
✓ Transaction version
✓ Transaction locktime

Does NOT commit to:
✗ Input amounts (in legacy; SegWit/Taproot DO commit to amounts)
✗ Input scriptPubKeys (in legacy; Taproot DOES commit to scriptPubKeys)

Transaction Structure Under SIGHASH_ALL

Transaction:
├── Version (4 bytes)
├── Inputs [committed]
│   ├── Input 0: txid + vout + scriptSig + sequence
│   ├── Input 1: txid + vout + scriptSig + sequence
│   └── ...
├── Outputs [committed]
│   ├── Output 0: value + scriptPubKey
│   ├── Output 1: value + scriptPubKey
│   └── ...
└── Locktime (4 bytes)

All of this is captured in the sighash preimage and signed.

Signature Appearance in a Transaction

# Raw DER signature with SIGHASH_ALL appended
# Format: <DER prefix> <r> <s> <sighash_type>
30 44
  02 20 <r: 32 bytes>
  02 20 <s: 32 bytes>
01  ← SIGHASH_ALL type byte

# Full scriptSig in P2PKH transaction
<sig_with_sighash_all> <pubkey>

# Hex example (71-byte SIGHASH_ALL signature):
3044022045... (69 bytes DER) + 01 (sighash type) = 70 bytes total

Why SIGHASH_ALL is the Safe Default

Using SIGHASH_ALL ensures:

  1. No output substitution: An attacker can't redirect payments by changing output addresses.

  2. No input addition: New inputs can't be quietly added to redirect change.

  3. No fee manipulation: Outputs can't be shrunk to increase miner fees.

  4. Complete transaction integrity: The signed transaction is exactly what gets broadcast.

# Creating a SIGHASH_ALL signature
def sign_input_sighash_all(private_key, tx, input_index, script_code):
    # Compute the sighash
    z = get_signature_hash(tx, input_index, script_code, SIGHASH_ALL)

    # Sign with ECDSA
    r, s = ecdsa_sign(private_key, z)

    # Encode as DER
    der_sig = encode_der(r, s)

    # Append sighash type byte
    return der_sig + bytes([SIGHASH_ALL])

Limitations of SIGHASH_ALL

The main limitation is inflexibility: once signed, nothing about the transaction can change. This prevents useful patterns like:

For these cases, other sighash types are used.

☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!