Skip to content
DonateБГ

Keys and addresses

Signature

A Bitcoin signature proves you hold a private key without revealing it. Learn how a transaction is signed, DER encoding, sighash flags and low S.

By Dimitar Zurnov · Updated 4 Nov 2026
Adapted from Learn Me a Bitcoin by Greg Walker.

A signature is a pair of numbers, called r and s, that a private key makes over a hash of transaction data. It proves that the signer controls the public key an output is locked to. The private key itself never appears in the transaction, so anyone can check the signature without learning the key.

Every input that spends a key-locked output needs a signature, or a set of them for multisig. The signature sits in the unlocking field of the input: the ScriptSig for old outputs, or the witness for SegWit and Taproot outputs. For the key math behind it, read ECDSA and Schnorr.

Where do signatures appear in a transaction?

The location depends on the locking script of the output being spent.

  • P2PK and P2PKH: one signature sits in the ScriptSig, and for P2PKH it sits next to the public key.
  • P2MS: one signature per key, so a 2-of-3 lock needs two signatures in the ScriptSig.
  • P2WPKH: the signature and the public key are the two items of the witness.
  • P2TR: the witness holds one Schnorr signature for a key-path spend.

The signature for a legacy input is part of the raw transaction that the transaction ID covers. A SegWit or Taproot signature sits in the witness, which is outside the txid. That is one reason the witness is cheaper to store.

How is a signature created?

Three steps make every signature.

  1. Build the transaction, with the inputs you spend and the outputs you create.
  2. Prepare the data that each input signs, which is a copy of the transaction with small changes.
  3. Hash that data, and sign the hash with the private key and a fresh random nonce.

The hash is what gets signed, not the raw data. A short fixed-size hash is faster to sign and check. Legacy and SegWit signatures hash their data with double SHA-256. Taproot uses a tagged SHA-256 instead.

The sign step produces r and s. The number r is the x coordinate of a random point on the curve, and s combines r, the hash and the private key. The rest of this page covers the details that turn r and s into a valid Bitcoin signature.

How do you sign a legacy P2PKH input?

A legacy signature covers a modified copy of the transaction, so the steps are easier to follow with a real case. The example spends one P2PKH output and sends 15,000 satoshis to a new P2PKH output. Its signed form has the transaction ID 1d5308ff12cb6fdb670c3af673a6a1317e21fa14fc863d5827f9d704cd5e14dc, which you can open at /tx/1d5308ff12cb6fdb670c3af673a6a1317e21fa14fc863d5827f9d704cd5e14dc.

Seven steps turn an unsigned P2PKH transaction into a signed one: placeholder, sighash, hash, sign, low S, DER and the ScriptSig. 1. Clear every ScriptSig all unlocking data is cleared 2. Placeholder: previous scriptPubKey 76a9144299ff317f…797bfc88ac 3. Append the sighash type 01000000 (SIGHASH_ALL, 4 bytes) 4. Double SHA-256 the result z = a6b4103f527d…d18ffcb 5. Sign z with key d and nonce k gives r and s (ECDSA) 6. Low S: if s > n/2, use n - s low s = 1f40afd1…a93a58 7. DER encode, add 01, build ScriptSig 47 3044…5801 21 024aeaf5…
The legacy signing steps in order. Each step must be exact, or the signature will not verify.

Here are the steps in order.

  1. Clear the unlocking data of every input. Each input is signed on its own, and here there is only one input, whose ScriptSig is empty.
  2. Put the previous output's locking script in the ScriptSig. For this input it is 76a9144299ff317fcd12ef19047df66d72454691797bfc88ac. This placeholder tells the hash which output is being spent.
  3. Append the sighash type as 4 bytes, little-endian. 01000000 means SIGHASH_ALL, which commits to the whole transaction.
  4. Hash the result with double SHA-256. The hash is z, here a6b4103f527dfe43dfbadf530c247bac8a98b7463c7c6ad38eed97021d18ffcb.
  5. Sign z with the private key and a nonce k. The output is r and s.
  6. Use the low S value. If s is above half the curve order, replace it with n - s.
  7. DER encode r and s, then append the sighash type as one byte, 01.

The ScriptSig is then the signature, a push of 71 bytes (47), followed by the 33-byte compressed public key (21). The whole field is 106 bytes:

473044022008f4f37e2d8f74e18c1b8fde2374d5f28402fb8ab7fd1cc5b786aa40851a70cb02201f40afd1627798ee8529095ca4b205498032315240ac322c9d8ff0f205a93a5801 21024aeaf55040fa16de37303d13ca1dde85f4ca9baa36e2963a27a1c0c1165fe2b1

You put this ScriptSig in place of the placeholder and recalculate the length byte. Then the transaction is ready to send.

Why must the nonce be random and never reused?

The nonce k must be unique for every signature. The example above uses k = 0x75bcd15 on purpose, so you can reproduce the signature exactly. Never do this with real coins.

If two signatures use the same nonce with the same private key, anyone can solve for the key. The two signatures give two equations, and their two unknowns, the nonce and the key, can be solved. Many wallets avoid the risk by deriving the nonce deterministically from the key and the message, as RFC 6979 describes. Then the same message always gives the same signature, and there is no random number that can fail.

What is the low S value?

Each signature has two valid s values. One is s, and the other is n - s, and both verify against the same r. Anyone could swap one for the other after you broadcast, and the change would alter the txid without changing where the money goes.

Bitcoin Core therefore rejects a signature whose s is in the upper half of the range. Release 0.11.1 added this in 2015 as a relay and mining rule, which BIP 146 describes. It is policy, not consensus, so a block that holds a high-S signature is still valid. The example has a high s of 101656099268479774907861155236876278987061611115278341531512875302287938750185, so it becomes n - s:

n     = 115792089237316195423570985008687907852837564279074904382605163141518161494337
s     = 101656099268479774907861155236876278987061611115278341531512875302287938750185
n - s = 14135989968836420515709829771811628865775953163796562851092287839230222744152
A signature has two valid S values, one in each half of the range. Bitcoin keeps the low one. n, the order of the curve fffffffffffffffffffffffffffffffe baaedce6af48a03bbfd25e8cd0364141 high s, above n/2: not relayed e0bf502e9d8867117ad6f6a35b4dfab5 3a7cab946e9c6e0f22426d9aca8d06e9 n - s gives the other value low s, below n/2: standard 1f40afd1627798ee8529095ca4b20549 8032315240ac322c9d8ff0f205a93a58 this is the value in the example
n is the order of the curve. Both values verify, so the rule keeps only one form of each signature.

How is a signature DER encoded?

Bitcoin writes legacy and SegWit ECDSA signatures in DER, an old ASN.1 format. It wraps r and s as two integers inside a sequence. The 30 and 02 tags are fixed, so only the lengths and the two numbers change. BIP 66 allows up to 72 bytes of DER before the sighash byte. Under low S, which relay policy requires, the DER form is 70 or 71 bytes in almost every case, so the full signature is 71 or 72 bytes.

A DER signature is a sequence of two integers, r and s, each 32 bytes here, with the sighash type added after. 30 sequence tag 44 the rest is 68 bytes long 02 integer tag, for r 20 r is 32 bytes long r, 32 bytes 08f4f37e2d8f74e18c1b8fde2374d5f2 8402fb8ab7fd1cc5b786aa40851a70cb 02 integer tag, for s 20 s is 32 bytes long s, 32 bytes, low 1f40afd1627798ee8529095ca4b20549 8032315240ac322c9d8ff0f205a93a58 01 SIGHASH_ALL, added after the DER
The example from the legacy section. Each integer is 32 bytes because neither starts with a high bit.

If the first byte of r or s is 80 or higher, DER reads the number as negative, so you add a 00 byte in front. Under low S, only r can need this. The top bit of s is never set, because s is at most half the curve order. r needs the byte about half the time, which is why the length is 70 or 71 bytes. Taproot signatures skip DER entirely and use a 64-byte Schnorr form, which BIP 340 defines.

What do the sighash flags mean?

A sighash type says which parts of the transaction the signature commits to. Each signature carries one, and the same value goes into the hash. A signature with one flag cannot be reused with another.

Byte Name What it signs
01 SIGHASH_ALL Every input and every output. The default.
02 SIGHASH_NONE Every input and no outputs, so anyone can choose the outputs.
03 SIGHASH_SINGLE Every input, and only the output with the same index.
81 ALL with ANYONECANPAY Only this input, and every output.
82 NONE with ANYONECANPAY Only this input, and no outputs.
83 SINGLE with ANYONECANPAY Only this input, and the output with the same index.

ANYONECANPAY lets others add inputs after you sign, which is how coinjoin designs work. If you are not sure which one to use, use 01. It protects the whole transaction from changes.

How does a SegWit signature differ?

SegWit, defined in BIP 143, changes the preimage. Instead of hashing the whole transaction in one piece, it hashes the parts separately. Those parts can be reused across inputs, so signing gets faster. The input's amount is also added to the preimage, so the signature commits to the value you are spending.

The example spends a P2WPKH output of 30,000 satoshis and creates one P2PKH output of 20,000 satoshis. Here is the preimage for the signature. The hash of this preimage is z.

02000000
cbfaca386d65ea7043aaac40302325d0dc7391a73b585571e28d3287d6b16203
3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044
ac4994014aa36b7f53375658ef595b3cb2891e1735fe5b441686f5e53338e76a01000000
1976a914aa966f56de599b4094b61aa68a2b3df9e97e9c4888ac
3075000000000000
ffffffff
900a6c6ff6cd938bf863e50613a4ed5fb1661b78649fe354116edaf5d4abb952
00000000
01000000

The lines are, in order: the version, hashPrevouts, hashSequence, this input's outpoint, the scriptCode, the amount in 8-byte little-endian, the sequence, hashOutputs, the locktime and the sighash type. Hashing these 182 bytes with double SHA-256 gives z = d7b60220e1b9b2c1ab40845118baf515203f7b6f0ad83cbb68d3c89b5b3098a6. The signed result has a witness with two items: the DER signature with 01 appended, and the 33-byte public key. The example transaction is 04f7bc0296fe70799762e628445fa9f0ccc2a2646ee5b369047d86ff964bd74e.

How does a Taproot signature differ?

Taproot uses Schnorr signatures, defined in BIP 340. Its preimage follows BIP 341 and is larger, because it includes every spent output's amount and locking script. The signature is 64 bytes, with no DER wrapper. If you use a sighash type other than the default, you add one byte, so the signature is 65 bytes.

The default sighash for Taproot is 00, which means the same as ALL. So a Taproot signature with the default type is 64 bytes, and the witness item is 64 bytes too. The Taproot page explains the full key-path and script-path rules.

Can you run the legacy signing steps in code?

The script below repeats steps 2 to 7 for the legacy example, using only the Python standard library. It reproduces the DER signature shown above. Run it only with a demo key, and never with a key that holds coins.

import hashlib

# secp256k1 parameters
P = 2**256 - 2**32 - 977
N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
     0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)

def add(p, q):                      # point addition (None is the point at infinity)
    if p is None: return q
    if q is None: return p
    if p[0] == q[0] and (p[1] + q[1]) % P == 0: return None
    if p == q: s = 3 * p[0] * p[0] * pow(2 * p[1], -1, P) % P
    else: s = (q[1] - p[1]) * pow(q[0] - p[0], -1, P) % P
    x = (s * s - p[0] - q[0]) % P
    return x, (s * (p[0] - x) - p[1]) % P

def mul(k, pt=G):                   # double-and-add
    r = None
    while k:
        if k & 1: r = add(r, pt)
        pt = add(pt, pt)
        k >>= 1
    return r

def hash256(b): return hashlib.sha256(hashlib.sha256(b).digest()).digest()

def sign(d, z, k):                  # ECDSA with a fixed nonce k (demo only)
    r = mul(k)[0] % N
    s = pow(k, -1, N) * (z + r * d) % N
    if s > N // 2: s = N - s        # low-S rule
    return r, s

def der(r, s):                      # DER encoding of (r, s)
    def enc(x):
        b = x.to_bytes(32, "big").lstrip(b"\x00")
        if b[0] & 0x80: b = b"\x00" + b
        return b"\x02" + bytes([len(b)]) + b
    body = enc(r) + enc(s)
    return b"\x30" + bytes([len(body)]) + body

d = int.from_bytes(hashlib.sha256(b"learnmeabitcoin1").digest(), "big")  # demo key
tx = bytes.fromhex("0100000001b7994a0db2f373a29227e1d90da883c6ce1cb0dd2d6812e4558041ebbbcfa54b000000001976a9144299ff317fcd12ef19047df66d72454691797bfc88acffffffff01983a0000000000001976a914b3e2819b6262e0b1f19fc7229d75677f347c91ac88ac00000000")
z = int.from_bytes(hash256(tx + bytes.fromhex("01000000")), "big")  # the sighash
r, s = sign(d, z, 0x75BCD15)        # never reuse k in real life
print((der(r, s) + b"\x01").hex())

The output ends in 01, the sighash type, and matches the DER signature in the legacy steps. Check your own code against this example before you trust it.

How do you keep signing safe?

  • Sign on a computer you control, and keep the private key on it or on a hardware device. Never enter a key or a seed phrase into a website.
  • Never reuse a nonce, and prefer a wallet or library that derives it deterministically.
  • Check the sighash type before you sign. A 02 signature lets others change the outputs, and an 81 lets them add inputs.
  • Verify the signature with the public key before you broadcast. A signature that fails is invalid, and the network will reject the transaction.

What should you remember about signatures?

  • A signature is a pair of numbers, r and s, made from a hash of the transaction and a private key.
  • Each input has its own signature, and the sighash type says what the signature covers.
  • Legacy and SegWit signatures are DER encoded, and Taproot signatures are 64-byte Schnorr.
  • Bitcoin Core relays only low-S signatures, so each signature has one standard form.

Next, read HD wallets to see how one seed can make the keys behind every one of these signatures.

In this section: Keys and addresses

All of Bitcoin from zero

Something look wrong? Tell us