Zum Inhalt springen
ecdsa.com
C

libsecp256k1 (Bitcoin Core)

libsecp256k1 aus Bitcoin Core, die Referenzimplementierung von secp256k1: opake Signaturen, kompakt oder als striktes DER serialisiert, Nonces nach RFC 6979, Low-S beim Signieren und Prüfen, Wiederherstellung des öffentlichen Schlüssels und Schnorr nach BIP-340.
Lizenz
MIT
Geprüfte Version
0.5.0 ·
Quellcode
github.com/bitcoin-core/secp256k1
Dokumentation
github.com/bitcoin-core/secp256k1/tree/master/include

Kompatibilität auf einen Blick

ECDSA

ECDSA-Kurven
secp256k1
EdDSA
none
Formate öffentlicher Schlüssel
sec1-uncompressedsec1-compressed

libsecp256k1 unterstützt eine einzige Kurve und tut das sorgfältig: zeitkonstantes Signieren, erschöpfende Tests und formale Verifikation von Teilen der Körperarithmetik. Bitcoin Core, viele Wallets und Bindings wie coincurve und das cgo-Backend von go-ethereum setzen die Bibliothek ein. Die Fakten auf dieser Seite wurden mit dem Paket aus Alpine 3.24.2 geprüft, Version 0.5.0 mit den Modulen recovery, extrakeys und schnorrsig; upstream war zu diesem Zeitpunkt bereits 0.8.0 erschienen.

Signaturen liegen in einer opaken Struktur; die Kodierung wird erst beim Serialisieren gewählt – serialize_compact liefert 64 Byte r‖s, serialize_der liefert DER –, und das Parsen ist ebenso explizit. parse_der ist strikt: Die Funktion akzeptierte minimales DER und lehnte dieselbe Signatur mit einer überflüssigen führenden Null in r ab, gemäß den BIP-66-Regeln von Bitcoin. Für laxe historische Signaturen braucht es den laxen Parser, der im Verzeichnis contrib des Repositorys liegt.

Das Signieren erwartet einen 32-Byte-Hash – die Bibliothek hasht deine Nachricht nie selbst –, verwendet RFC 6979 (der Abgleich ergab Übereinstimmung mit einer unabhängigen Implementierung) und erzeugt immer Low-S. Streng ist die Prüfung: Die gespiegelte High-S-Form einer gültigen Signatur scheiterte, und secp256k1_ecdsa_signature_normalize gibt es genau dafür, Signaturen von Allzweck-Signierern zu korrigieren. Besteht eine Signatur aus OpenSSL, Java oder einem Cloud-KMS die Prüfung nur in etwa der Hälfte der Fälle, liegt das an High-S; das Beispiel normalisiert vor der Prüfung.

Öffentliche Schlüssel sind SEC1-Punkte, unkomprimiert 65 Byte oder komprimiert 33 Byte lang; ein 64 Byte langes x‖y wird abgelehnt, und SPKI, PEM oder JWK werden nicht unterstützt. Das Modul recovery stellt den öffentlichen Schlüssel aus einer Signatur wieder her – die Grundlage von Ethereum-Adressen –, und das Modul schnorrsig implementiert BIP-340. Prüfe Signaturen von Bitcoin-Nachrichten mit dem Bitcoin-Nachrichten-Verifizierer und Nostr-Events mit dem Nostr-Event-Verifizierer.

Fakten und die Prüfungen dahinter

Nichts im Folgenden ist aus einer Dokumentation abgeschrieben. Das Prüfskript content/libraries/verify/libsecp256k1/run.sh hat libsecp256k1 (Bitcoin Core) 0.5.0 am 20. Oktober 2026 im Container-Image alpine:3.24.2 ausgeführt; die Seite muss mit seiner Ausgabe übereinstimmen, und jeder Fakt führt die zugehörigen Zeilen auf.

  • Kodierung von ECDSA-Signaturen

    structured

    Signaturen sind eine opake Struktur; serialize_compact schreibt 64 Byte r‖s und serialize_der schreibt DER.

    Von der Prüfung aufgezeichnet
    fact ecdsa-signature-encoding = structured
    evidence ecdsa-signature-encoding: secp256k1_ecdsa_signature is opaque: serialize_compact gives 64 bytes, serialize_der 70 bytes
  • ECDSA-Nonce

    rfc6979

    RFC 6979: Die Signatur war identisch mit der einer unabhängigen Implementierung von RFC 6979, bei normalisiertem s.

    Von der Prüfung aufgezeichnet
    fact ecdsa-nonce = rfc6979
    evidence ecdsa-nonce: two signatures identical: yes; equal to the reference RFC 6979 signature with s normalized: yes
  • Low-S beim Signieren

    low-s

    Kein High-S-Wert unter 64 Signaturen.

    Von der Prüfung aufgezeichnet
    fact ecdsa-low-s-sign = low-s
  • High-S bei der Prüfung

    rejects-high-s

    secp256k1_ecdsa_verify lehnte (r, n − s) ab; nach secp256k1_ecdsa_signature_normalize bestand die Signatur die Prüfung.

    Von der Prüfung aufgezeichnet
    fact ecdsa-low-s-verify = rejects-high-s
    evidence ecdsa-low-s-verify: verify on (r, n - s): 0; signature_normalize reports it was high: 1; normalized verifies: 1
  • Was der Signaturaufruf hasht

    takes-digest

    secp256k1_ecdsa_sign erwartet einen 32-Byte-Hash der Nachricht.

    Von der Prüfung aufgezeichnet
    fact ecdsa-prehash = takes-digest
    evidence ecdsa-prehash: secp256k1_ecdsa_sign takes a 32-byte message hash (msghash32)
  • Standard-Hash

    none

    Beim Signieren und Prüfen wird nichts gehasht.

    Von der Prüfung aufgezeichnet
    fact ecdsa-default-hash = none
  • Strenge beim Parsen von DER

    rejects-non-minimal

    parse_der akzeptierte minimales DER und lehnte eine Kodierung mit einem überflüssigen führenden Nullbyte in r ab.

    Von der Prüfung aufgezeichnet
    fact der-strictness = rejects-non-minimal
    evidence der-strictness: parse_der on minimal DER: 1; with a redundant leading zero in r: 0
  • Fehlerhafte ECDSA-Signatur

    returns-error

    Fehlerhafte Eingaben scheitern schon beim Parsen (parse_der gibt 0 zurück); verify erhält nur geparste Signaturen.

    Von der Prüfung aufgezeichnet
    fact ecdsa-malformed-signature = returns-error
    evidence ecdsa-malformed-signature: parsing is a separate call: parse_der on 3 bytes returned 0; verify only ever sees parsed signatures
  • ECDSA-Kurven

    secp256k1

    Nur secp256k1.

    Von der Prüfung aufgezeichnet
    fact ecdsa-curves = secp256k1
  • Wiederherstellung des öffentlichen Schlüssels

    supported

    Das Modul recovery stellte den öffentlichen Schlüssel des Signierers aus einer wiederherstellbaren Signatur wieder her.

    Von der Prüfung aufgezeichnet
    fact public-key-recovery = supported
  • Schnorr-Signaturen

    BIP-340

    Das Modul schnorrsig erzeugte eine BIP-340-Signatur und prüfte sie gegen den öffentlichen Schlüssel in x-only-Form.

    Von der Prüfung aufgezeichnet
    fact schnorr = BIP-340
  • EdDSA

    none

    Kein EdDSA.

    Von der Prüfung aufgezeichnet
    fact eddsa = none
  • Post-Quanten-Algorithmen

    none

    Keine Post-Quanten-Algorithmen.

    Von der Prüfung aufgezeichnet
    fact pqc = none
  • Formate öffentlicher Schlüssel

    sec1-uncompressedsec1-compressed

    ec_pubkey_parse akzeptiert SEC1-Punkte in unkomprimierter Form mit 65 Byte und in komprimierter Form mit 33 Byte; ein 64 Byte langes x‖y wurde abgelehnt.

    Von der Prüfung aufgezeichnet
    fact public-key-formats = sec1-uncompressed, sec1-compressed
    evidence public-key-formats: ec_pubkey_parse: 65-byte uncompressed 1, 33-byte compressed 1, 64-byte x||y 0
  • Formate privater Schlüssel

    raw-scalar

    Geheime Schlüssel sind rohe 32-Byte-Skalare.

    Von der Prüfung aufgezeichnet
    fact private-key-formats = raw-scalar

Verwendung

Signiere einen 32-Byte-Hash, parse eine Signatur so, wie sie von anderswo ankäme, normalisiere s und prüfe.
#include <secp256k1.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
    unsigned char seckey[32], msghash[32];
    memset(seckey, 0x11, 32);   /* use a random 32-byte key in real code */
    memset(msghash, 0x22, 32);  /* the caller hashes: libsecp256k1 signs a 32-byte digest */

    secp256k1_pubkey pub;
    secp256k1_ecdsa_signature sig;
    if (!secp256k1_ec_pubkey_create(ctx, &pub, seckey) || !secp256k1_ecdsa_sign(ctx, &sig, msghash, seckey, NULL, NULL)) return 1;

    /* A signature from elsewhere: parse (strict DER or 64-byte compact), then normalize s,
       because verify rejects high-S signatures that OpenSSL or Java produce half the time. */
    unsigned char compact[64];
    secp256k1_ecdsa_signature_serialize_compact(ctx, compact, &sig);
    secp256k1_ecdsa_signature parsed;
    if (!secp256k1_ecdsa_signature_parse_compact(ctx, &parsed, compact)) return 1;
    secp256k1_ecdsa_signature_normalize(ctx, &parsed, &parsed);

    printf("verified: %d\n", secp256k1_ecdsa_verify(ctx, &parsed, msghash, &pub));
    secp256k1_context_destroy(ctx);
    return 0;
}

Die Snippet-Testumgebung führt jedes Beispiel unverändert im Container-Image alpine:3.24.2 aus, und der Lauf schlägt fehl, wenn die Ausgabe nicht übereinstimmt.

Einrichtung
apk add --no-cache -q build-base libsecp256k1-dev=0.5.0-r1 >/dev/null
Befehl
cc -o usage usage.c -lsecp256k1 && ./usage
Ausgabe muss passen (regulärer Ausdruck)
verified: 1

Bibliotheken