Go liefert seine Kryptografie in der Standardbibliothek mit, und seit Go 1.24 stecken die zentralen Primitive im Go Cryptographic Module, das für FIPS 140-3 gebaut ist. crypto/ecdsa signiert und prüft, crypto/x509 liest Schlüssel und Zertifikate, und Go 1.27.3 bietet neben crypto/ed25519 auch crypto/mlkem (ML-KEM-768/1024) und crypto/mldsa (ML-DSA-44/65/87). Es gibt kein secp256k1: Code für Ethereum und Bitcoin nutzt die Pakete von go-ethereum oder decred.
Alles in crypto/ecdsa arbeitet mit einem Digest, den du selbst berechnet hast – das Paket hasht nie. Schlimmer als eine falsche Signatur: Eine lange Eingabe wird stillschweigend auf die Kurvengröße gekürzt, und eine Signatur über eine 46-Byte-Eingabe bestand die Prüfung für eine andere Eingabe mit denselben ersten 32 Byte. Hashe also immer zuerst, wie es das Beispiel tut. SignASN1, VerifyASN1 und die Schnittstelle crypto.Signer sprechen ASN.1-DER; WebCrypto, JWS und andere Gegenstellen mit rohem r‖s brauchen Sign/Verify mit Ganzzahlen, die per FillBytes aufgefüllt sind – Bytes() lässt führende Nullbytes weg, sodass jedes r oder s, das zufällig mit einem Nullbyte beginnt, ein Byte zu kurz herauskommt.
Signaturen sind randomisiert, und seit Go 1.26 wird der übergebene io.Reader ignoriert, sofern nicht GODEBUG=cryptocustomrand=1 gesetzt ist: Zwei Signaturen mit einem Reader, der nur Nullen liefert, unterschieden sich. Tests, die sich auf einen festen Reader verließen, um reproduzierbare Signaturen zu erhalten, funktionieren nicht mehr; der dokumentierte Ersatz ist testing/cryptotest.SetGlobalRandom. s wird nicht normalisiert, und VerifyASN1 akzeptiert beide Hälften; für Verifizierer, die strikt Low-S verlangen, muss s in den Signaturen daher durch n − s ersetzt werden.
Beim Parsen von Schlüsseln steht DER an erster Stelle. x509.ParsePKIXPublicKey scheitert bei PEM-Text mit asn1: structure error: tags don't match – rufe zuerst pem.Decode auf. ecdsa.ParseUncompressedPublicKey und ecdsa.ParseRawPrivateKey lesen den bloßen SEC1-Punkt und den bloßen Skalar; komprimierte Punkte werden abgelehnt, und für mit Passphrase verschlüsseltes PKCS#8 gibt es keinen Parser. Bei einer fehlerhaften Signatur gibt VerifyASN1 false zurück, nie einen Fehler.
Um eine Go-Signatur mit einem anderen Stack zu vergleichen, wandle sie im Konverter DER ⇄ Raw um und prüfe sie im Signatur-Verifizierer; Probleme beim Parsen von Zertifikaten erkennst du am leichtesten im Zertifikats-Decoder.