Към съдържанието
ДаретеEN

Ключове и адреси

Подпис

Подписът за трансакция биткойн доказва, че държите частния ключ, без да го разкривате. Вижте стъпките, DER кодирането, sighash типовете и low S.

От Dimitar Zurnov · Обновено на 4 ноември 2026
Адаптирано от Learn Me a Bitcoin на Greg Walker.

Подписът е двойка числа, наречени r и s, които частният ключ създава върху хеш на данните от трансакцията. Той доказва, че подписващият контролира публичния ключ, към който е заключен даден изход. Самият частен ключ никога не се появява в трансакцията, така че всеки може да провери подписа, без да научи ключа.

Всеки вход, който харчи изход, заключен с ключ, има нужда от подпис, а при multisig от няколко. Подписът стои в полето за отключване на входа: в ScriptSig при старите изходи или в witness при SegWit и Taproot изходите. За математиката зад подписите прочетете ECDSA и Schnorr.

Къде се появяват подписите в трансакцията?

Мястото зависи от заключващия скрипт на изхода, който харчите.

  • P2PK и P2PKH: един подпис стои в ScriptSig, а при P2PKH до публичния ключ.
  • P2MS: по един подпис за всеки ключ, така че заключване 2 от 3 изисква два подписа в ScriptSig.
  • P2WPKH: подписът и публичният ключ са двата елемента на witness.
  • P2TR: witness съдържа един Schnorr подпис при харчене по ключовия път (key-path).

Подписът на стар вход е част от данните, от които се изчислява идентификаторът на трансакцията (txid). Подписът при SegWit или Taproot стои в witness, който не влиза в txid. Това е една от причините witness да е по-евтин за съхранение.

Как се създава подпис?

Три стъпки създават всеки подпис.

  1. Построете трансакцията с входовете, които харчите, и изходите, които създавате.
  2. Подгответе данните, които всеки вход подписва: копие на трансакцията с малки промени.
  3. Хеширайте тези данни и подпишете хеша с частния ключ и нов случаен nonce.

Подписва се хешът, а не суровите данни. Къс хеш с фиксиран размер се подписва и проверява по-бързо. Старите и SegWit подписите хешират данните си с двойния SHA-256. Taproot използва таговани хешове върху SHA-256.

Стъпката на подписване дава r и s. Числото r е x-координатата на случайна точка от кривата, а s комбинира r, хеша и частния ключ. Останалата част от страницата обяснява подробностите, които превръщат r и s във валиден биткойн подпис.

Как се подписва стар P2PKH вход?

Старият подпис покрива променено копие на трансакцията. Реален пример прави стъпките по-лесни за проследяване. Примерът харчи един P2PKH изход и изпраща 15,000 сатоши към нов P2PKH изход. Подписаната трансакция има идентификатор 1d5308ff12cb6fdb670c3af673a6a1317e21fa14fc863d5827f9d704cd5e14dc, който можете да отворите на /tx/1d5308ff12cb6fdb670c3af673a6a1317e21fa14fc863d5827f9d704cd5e14dc.

Седем стъпки превръщат неподписана P2PKH трансакция в подписана: заместител, sighash, хеш, подпис, low S, DER и ScriptSig. 1. Изчистване на всеки ScriptSig всички данни за отключване се изчистват 2. Заместител: предишният scriptPubKey 76a9144299ff317f…797bfc88ac 3. Добавяне на sighash типа 01000000 (SIGHASH_ALL, 4 байта) 4. Двоен SHA-256 на резултата z = a6b4103f527d…d18ffcb 5. Подписване на z с ключ d и nonce k дава r и s (ECDSA) 6. Low S: ако s > n/2, вземи n - s low s = 1f40afd1…a93a58 7. DER кодиране, 01, ScriptSig 47 3044…5801 21 024aeaf5…
Стъпките за подписване на стар вход по ред. Всяка трябва да е точна, иначе подписът няма да се провери.

Ето стъпките по ред.

  1. Изчистете данните за отключване на всеки вход. Всеки вход се подписва сам, а тук има само един, чийто ScriptSig е празен.
  2. Сложете заключващия скрипт на предишния изход в ScriptSig. За този вход той е 76a9144299ff317fcd12ef19047df66d72454691797bfc88ac. Този заместител казва на хеша кой изход се харчи.
  3. Добавете sighash типа като 4 байта, в little-endian. 01000000 означава SIGHASH_ALL, който покрива цялата трансакция.
  4. Хеширайте резултата с двоен SHA-256. Хешът е z, тук a6b4103f527dfe43dfbadf530c247bac8a98b7463c7c6ad38eed97021d18ffcb.
  5. Подпишете z с частния ключ и nonce k. Резултатът са r и s.
  6. Използвайте low S стойността. Ако s е над половината от реда на кривата, заменете го с n - s.
  7. Кодирайте r и s в DER, после добавете sighash типа като един байт, 01.

Тогава ScriptSig съдържа самия подпис с push на 71 байта (47), следван от push на 33-байтовия компресиран публичен ключ (21). Цялото поле е 106 байта:

473044022008f4f37e2d8f74e18c1b8fde2374d5f28402fb8ab7fd1cc5b786aa40851a70cb02201f40afd1627798ee8529095ca4b205498032315240ac322c9d8ff0f205a93a5801 21024aeaf55040fa16de37303d13ca1dde85f4ca9baa36e2963a27a1c0c1165fe2b1

Поставете този ScriptSig на мястото на заместителя и преизчислете байта за дължина. После трансакцията е готова за изпращане.

Защо nonce-ът трябва да е случаен и никога да не се повтаря?

Nonce-ът k трябва да е уникален за всеки подпис. Примерът по-горе ползва k = 0x75bcd15 умишлено, за да можете да възпроизведете подписа точно. Никога не правете това с истински монети.

Ако два подписа ползват един и същ nonce с един и същ частен ключ, всеки може да изчисли ключа. Двата подписа дават две уравнения, а двете неизвестни, nonce-ът и ключът, могат да се решат. Много портфейли избягват риска, като изведат nonce-а детерминистично от ключа и съобщението, както описва RFC 6979. Тогава едно и също съобщение винаги дава един и същ подпис и няма случайно число, което може да се провали.

Какво е low S?

Всеки подпис има два валидни s. Едното е s, а другото е n - s, и двете се проверяват с един и същ r. Всеки, който види трансакцията, би могъл да размени едното с другото след изпращането, а промяната би сменила txid, без да промени къде отиват парите.

Затова Bitcoin Core отхвърля подпис, чието s е в горната половина на диапазона. Версия 0.11.1 е добавила това през 2015 г. като правило за разпространение и майнинг, което описва BIP 146. Това е политика, а не консенсус, така че блок с подпис от висок S остава валиден. Примерът има висок s, 101656099268479774907861155236876278987061611115278341531512875302287938750185, така че става n - s:

n     = 115792089237316195423570985008687907852837564279074904382605163141518161494337
s     = 101656099268479774907861155236876278987061611115278341531512875302287938750185
n - s = 14135989968836420515709829771811628865775953163796562851092287839230222744152
Подписът има два валидни S, по един във всяка половина на диапазона. Bitcoin пази ниското. n, редът на кривата fffffffffffffffffffffffffffffffe baaedce6af48a03bbfd25e8cd0364141 висок S над n/2: отхвърля се e0bf502e9d8867117ad6f6a35b4dfab5 3a7cab946e9c6e0f22426d9aca8d06e9 n - s дава другата стойност low S, под n/2: стандартен 1f40afd1627798ee8529095ca4b20549 8032315240ac322c9d8ff0f205a93a58 това е стойността в примера
n е редът на кривата. И двете стойности се проверяват, така че правилото пази само една форма на всеки подпис.

Как се кодира подписът в DER?

Bitcoin записва legacy и SegWit ECDSA подписите в DER, стар ASN.1 формат. Той обвива r и s като две цели числа в последователност. Таговете 30 и 02 са фиксирани, така че се променят само дължините и двете числа. BIP 66 позволява до 72 байта DER преди байта за sighash. При low S, изисквано от правилото за разпространение, DER формата е почти винаги 70 или 71 байта, така че целият подпис е 71 или 72 байта.

DER подписът е последователност от две цели числа, r и s, по 32 байта тук, и след тях е добавен sighash типът. 30 таг за последователност 44 останалите 68 байта 02 таг за цяло число, за r 20 r е 32 байта r, 32 байта 08f4f37e2d8f74e18c1b8fde2374d5f2 8402fb8ab7fd1cc5b786aa40851a70cb 02 таг за цяло число, за s 20 s е 32 байта s, 32 байта, low S 1f40afd1627798ee8529095ca4b20549 8032315240ac322c9d8ff0f205a93a58 01 SIGHASH_ALL, добавен след DER
Примерът от раздела за стария вход. Всяко число е 32 байта, защото никое не започва със старши бит.

Ако първият байт на r или s е 80 или повече, DER го чете като отрицателно число, затова отпред се добавя байт 00. При low S това може да се наложи само за r. Старшият бит на s никога не е зададен, защото s е най-много половината от реда на кривата. r се нуждае от допълнителния байт около половината от случаите, затова дължината е 70 или 71 байта. Taproot подписите прескачат DER изцяло и ползват 64-байтовата Schnorr форма, дефинирана в BIP 340.

Какво означават sighash флаговете?

Sighash типът казва кои части от трансакцията покрива подписът. Всеки подпис носи един, а същата стойност влиза в хеша. Подписът с един тип не може да се използва с друг.

Байт Име Какво подписва
01 SIGHASH_ALL Всеки вход и всеки изход. По подразбиране.
02 SIGHASH_NONE Всеки вход и никакъв изход, така че всеки може да избере изходите.
03 SIGHASH_SINGLE Всеки вход и само изходът със същия индекс.
81 ALL с ANYONECANPAY Само този вход и всеки изход.
82 NONE с ANYONECANPAY Само този вход и никакъв изход.
83 SINGLE с ANYONECANPAY Само този вход и изходът със същия индекс.

ANYONECANPAY позволява на други да добавят входове след като подпишете. Така работят схемите coinjoin. Ако не сте сигурни какъв тип да ползвате, ползвайте 01. Той защитава цялата трансакция от промени.

Как се различава SegWit подписът?

SegWit, дефиниран в BIP 143, променя прообраза (preimage), върху който се прави хешът. Вместо да хешира цялата трансакция на едно парче, той хешира частите ѝ поотделно. Тези части могат да се ползват повторно между входовете, така че подписването е по-бързо. Стойността на входа също се добавя към прообраза, така че подписът покрива сумата, която харчите.

Примерът харчи P2WPKH изход от 30,000 сатоши и създава един P2PKH изход от 20,000 сатоши. Ето прообраза на подписа. Хешът на този прообраз е z.

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

Редовете са, отгоре надолу: версията, hashPrevouts, hashSequence, outpoint на този вход (препратката към харчения изход), scriptCode, сумата в 8 байта little-endian, последователността, hashOutputs, locktime и sighash типът. Двойният SHA-256 на тези 182 байта дава z = d7b60220e1b9b2c1ab40845118baf515203f7b6f0ad83cbb68d3c89b5b3098a6. Подписаната трансакция има witness с два елемента: DER подписа с добавен 01 и 33-байтовия публичен ключ. Примерната трансакция е 04f7bc0296fe70799762e628445fa9f0ccc2a2646ee5b369047d86ff964bd74e.

Как се различава Taproot подписът?

Taproot използва Schnorr подписи, дефинирани в BIP 340. Прообразът му следва BIP 341 и е по-голям, защото включва сумата и заключващия скрипт на всеки похарчен изход. Подписът е 64 байта, без DER обвивка. Ако ползвате sighash тип, различен от подразбиращия се, добавяте един байт и подписът е 65 байта.

Подразбиращият се sighash за Taproot е 00, който е същото като ALL. Така Taproot подпис с подразбиращия се тип е 64 байта, а елементът на witness също е 64 байта. Страницата за Taproot обяснява правилата за харчене по key-path и по script-path.

Може ли да изпълните стъпките за стар подпис в код?

Скриптът по-долу повтаря стъпки 2 до 7 за примера със стар вход и ползва само стандартната библиотека на Python. Той възпроизвежда DER подписа, показан по-горе. Стартирайте го само с демо ключ, никога с ключ, който държи монети.

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())

Изходът завършва на 01, sighash типа, и съвпада с DER подписа от стъпките за стария вход. Проверете собствения си код с този пример, преди да му се доверите.

Как да пазите подписите си в безопасност?

  • Подписвайте на компютър, който контролирате, и пазете частния ключ на него или на хардуерно устройство. Никога не въвеждайте ключ или сийд фраза в уебсайт.
  • Никога не ползвайте nonce повторно и предпочитайте портфейл или библиотека, която извежда nonce-а детерминистично.
  • Проверете sighash типа, преди да подпишете. Подпис с 02 позволява на други да сменят изходите, а 81 им позволява да добавят входове.
  • Проверете подписа с публичния ключ, преди да изпратите. Подпис, който не се проверява, е невалиден, и мрежата ще отхвърли трансакцията.

Какво да запомните за подписите?

  • Подписът е двойка числа, r и s, направена от хеш на трансакцията и частен ключ.
  • Всеки вход има собствен подпис, а sighash типът казва какво покрива той.
  • Legacy и SegWit подписите са DER кодирани, а Taproot подписите са 64-байтови Schnorr.
  • Bitcoin Core разпространява по мрежата само low S подписи, така че всеки подпис има една стандартна форма.

Следващо прочетете HD портфейли, за да видите как един сийд може да създаде ключовете зад всеки от тези подписи.

В този раздел: Ключове и адреси

Целият курс „Биткойн от нулата“

Нещо не изглежда наред? Кажете ни