Публичен ключ
Публичен ключ биткойн: как се получава от частния ключ върху кривата secp256k1, както и компресираната, некомпресираната и x-only формата.
От Dimitar Zurnov · Обновено на 4 ноември 2026
Адаптирано от Learn Me a Bitcoin на Greg Walker.
Публичният ключ в биткойн (bitcoin) се получава, като умножите фиксирана точка от кривата secp256k1 по частния ключ. Резултатът е точка от същата крива. Тя е публичната половина на двойката, затова може безопасно да се споделя. Монетите могат да се заключат към публичен ключ, а само съответният частен ключ ги отключва. Биткойн записва публичния ключ като шестнадесетичен низ в една от трите форми: компресирана, некомпресирана или x-only.
Как се получава публичен ключ?
Публичният ключ се получава чрез умножение върху елиптичната крива. Кривата има фиксирана начална точка, наречена генераторна точка, G. Умножавате G по частния ключ, число от 1 до n-1, и резултатът е нова точка от кривата. Тази точка е публичният ключ. Умножението е бързо. Обратното, от точката към частния ключ, няма известен практичен метод. Страницата за елиптичната крива разглежда математиката.
Параметрите на secp256k1 са публикувани в SEC 2. Този кратък скрипт умножава G по частен ключ, без да ползва библиотека. Той е бавен, затова е само за учене. Истинският код трябва да ползва тествана библиотека.
# простото число на полето secp256k1 и генераторната точка
P = 2**256 - 2**32 - 977
G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
def add(a, b):
if a is None: return b
if b is None: return a
if a[0] == b[0] and (a[1] + b[1]) % P == 0: return None
if a == b: s = 3 * a[0] * a[0] * pow(2 * a[1], -1, P) % P
else: s = (b[1] - a[1]) * pow(b[0] - a[0], -1, P) % P
x = (s * s - a[0] - b[0]) % P
return (x, (s * (a[0] - x) - a[1]) % P)
def public_key(k):
"""Умножава генераторната точка G по частния ключ k."""
point, result = G, None
while k:
if k & 1: result = add(result, point)
point = add(point, point)
k >>= 1
return result
k = int("dbf34ebb797c7b62960c0c7d1784c3209d5de7abf307df4a07dac9c76f22ee72", 16)
x, y = public_key(k)
prefix = "02" if y % 2 == 0 else "03"
print(prefix + f"{x:064x}") # 02cd33111c7fc75b33bc30ad959dd27433d631dee5bf072733334163dedc403070
Примерният ключ е този от страницата за частния ключ. Компресираният му публичен ключ е 02cd33111c7fc75b33bc30ad959dd27433d631dee5bf072733334163dedc403070. Не ползвайте този ключ с истински монети, защото всеки може да го види.
Какви са трите форми на публичен ключ?
Всяка форма започва със същата координата x, 32-байтово число. Формите се различават по това, което добавят към нея. Компресираният ключ добавя байт с префикс, който записва четността на y. Некомпресираният ключ добавя цялата координата y. Ключът x-only не добавя нищо.
Какво е компресиран публичен ключ?
Компресираният публичен ключ е 33 байта. Той съдържа цялата координата x и префикс, който показва дали y е четно или нечетно. Префиксът е 02, когато y е четно, и 03, когато y е нечетно.
Кривата е симетрична, затова за всяко x, което лежи на кривата, има само две възможни стойности на y. Те са с различна четност: едното е четно, а другото нечетно. Префиксът е достатъчен, за да се избере правилното, затова ключът пази префикса, а не цялото y. Примерният ключ има четно y, значи префиксът му е 02.
Използвайте компресирани ключове по подразбиране. Те са по-къси, а политиката по подразбиране на Bitcoin Core отхвърля некомпресираните ключове в SegWit v0 скриптове, като P2WPKH и P2WSH. По подразбиране такива трансакции не се препращат между нодовете и не се включват в блок. Проверката е флагът SCRIPT_VERIFY_WITNESS_PUBKEYTYPE в интерпретатора на скриптове на Bitcoin Core. BIP 143 задава същото правило.
Какво е некомпресиран публичен ключ?
Некомпресираният публичен ключ е 65 байта. Започва с 04, следвано от цялата 32-байтова координата x и цялата 32-байтова координата y. Ранният софтуер е използвал тази форма, преди компресираните ключове да се наложат. Примерният ключ в некомпресирана форма е:
04cd33111c7fc75b33bc30ad959dd27433d631dee5bf072733334163dedc403070002efe73430d2af79531c7d8f64500b5c392db9af29ccfd60e2ca7ea9c198538
Некомпресираните ключове все още работят в стари (legacy) заключващи скриптове, като P2PK, P2PKH, P2SH и голи мултиподписи (bare multisig). Политиката по подразбиране ги отхвърля в P2WPKH и P2WSH изходи. Затова днес няма голяма причина да ги избирате.
Какво е x-only публичен ключ?
x-only публичният ключ е 32-байтовата координата x без префикс. Taproot ползва тази форма, описана в BIP 340. Тъй като няма префикс, ключът се приема за четно y. Всяка точка с нечетно y може да се замени с партньора ѝ с четно y, затова трябва да се пази само x.
Примерният ключ има четно y, така че неговата x-only форма е компресираният ключ без префикса 02: cd33111c7fc75b33bc30ad959dd27433d631dee5bf072733334163dedc403070. Изход в Taproot се заключва към преработена (tweaked) версия на този ключ. Страницата за Taproot обяснява ъпгрейда, който е в сила от блок 709,632.
Как се декомпресира публичен ключ?
Можете да възстановите пълния некомпресиран ключ от компресирания. Кривата secp256k1 следва уравнението y² = x³ + 7, по модул p, простото число, спрямо което работят изчисленията. Знаете x, затова търсите y. Отговорът е квадратен корен с две стойности, едната четна и другата нечетна. Префиксът показва коя да запазите.
Тъй като p е 3 по модул 4, квадратният корен се смята с едно степенуване. Кратката програма по-долу възстановява некомпресирания ключ от компресирания.
P = 2**256 - 2**32 - 977
compressed = "02cd33111c7fc75b33bc30ad959dd27433d631dee5bf072733334163dedc403070"
x = int(compressed[2:], 16)
# y^2 = x^3 + 7 (mod P); P е 3 по модул 4, така че квадратният корен е едно степенуване
y = pow((x**3 + 7) % P, (P + 1) // 4, P)
# префиксът показва дали y трябва да е четно (02) или нечетно (03)
if (y % 2 == 0) != (compressed[:2] == "02"):
y = P - y
print("04" + f"{x:064x}" + f"{y:064x}")
Къде се появяват публичните ключове в блокчейна?
Публичният ключ обикновено се появява в блокчейна едва когато монетите се похарчат. Изключение е заключване, което съдържа целия ключ, като P2PK или голи мултиподписи. Таблицата показва къде стои той при три често срещани вида изходи.
| Заключващ скрипт | Къде стои публичният ключ | Реален пример |
|---|---|---|
| P2PK | Записан цял в scriptPubKey, затова е публичен още щом монетите пристигнат | 18a16d32…ee444, coinbase изход в блок 150,007 |
| P2PKH | В заключването стои само хешът. Целият ключ се показва в scriptSig, когато похарчите | faf2987f…0808c, която харчи P2PKH изход в блок 770,002 |
| P2WPKH | В заключването стои само хешът. Ключът е в witness, когато похарчите | 1674761a…4a6, която харчи P2WPKH изход в блок 682,085 |
P2PK е най-простото заключване, но показва ключа от самото начало. P2PKH и P2WPKH скриват ключа зад хеш, докато не похарчите. Taproot изходът е различен: той показва от самото начало преработена версия на ключа, а не ключа, който държите.
Как публичният ключ получава монети?
Когато някой ви плати, изходът се заключва към вашия публичен ключ или към неговия хеш. Само подпис, направен със съответния частен ключ, може да го отключи. Мрежата проверява подписа спрямо ключа в заключването и никога не се нуждае от вашия частен ключ.
Повечето портфейли ви показват адрес, а не суровия ключ, защото адресът е по-къс и по-лесен за копиране. Адресът се строи от хеша на публичния ключ, а за него е следващата страница в раздела.
Кой ключ да ползвате?
Частният ключ пазете в тайна. Публичният ключ е частта, която можете да публикувате. За старите изходи и за SegWit v0 ползвайте компресирани ключове, които са по 33 байта. Taproot ползва x-only формата на същата точка, тоест компресирания ключ без префикса.
Следващата страница, хеш на публичния ключ, показва как този ключ се хешира в стойността, която носят повечето адреси.
В този раздел: Ключове и адреси
Целият курс „Биткойн от нулата“
Нещо не изглежда наред? Кажете ни