Zum Inhalt springen
ecdsa.com
Go

go-webauthn

go-webauthn, die Relying-Party-Bibliothek für WebAuthn in Go: Assertion-Signaturen nur als DER, Benutzerverifizierung nach den Vorgaben der Sitzung und ein Rückgang des Signaturzählers, der als Klon-Warnung statt als fehlgeschlagene Anmeldung gemeldet wird.
Lizenz
BSD-3-Clause
Geprüfte Version
0.18.2 ·
Quellcode
github.com/go-webauthn/webauthn
Dokumentation
pkg.go.dev/github.com/go-webauthn/webauthn/webauthn

Kompatibilität auf einen Blick

WebAuthn

github.com/go-webauthn/webauthn (der gepflegte Fork von duo-labs/webauthn) führt beide Zeremonien aus – BeginRegistration/FinishRegistration und BeginLogin/FinishLogin oder deren Varianten Validate* für andere Frameworks als net/http – und prüft Attestierungen in jedem Format. Die Prüfung validierte dieselben Antworten eines Software-Authenticators wie bei SimpleWebAuthn, py_webauthn und WebAuthn4J.

Die Richtlinie stammt aus der Konfiguration und wird in SessionData mitgeführt. Bei leerem AuthenticatorSelection sendete BeginRegistration ein leeres Objekt, sodass Browser die Standardwerte anwenden – Benutzerverifizierung preferred, Resident Key discouraged –, und die Validierung akzeptierte Antworten mit nicht gesetztem UV-Flag, weil die Sitzung nur preferred verlangte. Mit UserVerification: required in der Sitzung scheiterte dieselbe Assertion mit User verification required but flag not set by authenticator. Lege die Richtlinie in Config.AuthenticatorSelection fest, wie es das Beispiel tut, und speichere zwischen den beiden Aufrufen das gesamte SessionData.

Der Umgang mit dem Signaturzähler ist der wichtigste Unterschied zu den anderen Bibliotheken. Eine Assertion, deren Zähler (3) unter dem gespeicherten Wert (5) lag, führte zu einer erfolgreichen Anmeldung: Beim zurückgegebenen Credential war Authenticator.CloneWarning gesetzt, und SignCount blieb bei 5. Die Bibliothek meldet nur einen möglichen Klon; ob die Anmeldung abgelehnt wird, entscheidet dein Code, der nach jeder Anmeldung CloneWarning prüfen muss.

Assertion-Signaturen müssen ASN.1-DER sein – eine rohe r‖s-Signatur mit 64 Byte scheiterte mit Error validating the assertion signature: Signature invalid or not provided –, und eine DER-Signatur mit High-S bestand die Prüfung. Die Standardliste pubKeyCredParams ist lang: ES256, ES384 und ES512 (-7, -35, -36), RS256 bis RS512 (-257 bis -259), PS256 bis PS512 (-37 bis -39) und Ed25519 (-8); das Ed25519-Credential funktionierte durchgängig, von der Registrierung bis zur Prüfung. In 0.18.2 gibt es keinen Eintrag für ML-DSA.

Dekodiere mit dem WebAuthn-Inspektor, was ein Browser sendet, schlage Authenticator-Modelle mit dem AAGUID-Lookup nach und probiere Zeremonien in der Passkey-Sandbox aus.

Fakten und die Prüfungen dahinter

Nichts im Folgenden ist aus einer Dokumentation abgeschrieben. Das Prüfskript content/libraries/verify/go-webauthn/run.sh hat go-webauthn 0.18.2 am 20. Oktober 2026 im Container-Image golang:1.27.3-trixie ausgeführt; die Seite muss mit seiner Ausgabe übereinstimmen, und jeder Fakt führt die zugehörigen Zeilen auf.

  • Standard-COSE-Algorithmen

    -7-35-36-257-258-259-37-38-39-8

    BeginRegistration listet die COSE-Algorithmen -7, -35, -36 (ES256/384/512), -257, -258, -259 (RS256/384/512), -37, -38, -39 (PS256/384/512) und -8 (Ed25519) auf.

    Von der Prüfung aufgezeichnet
    fact webauthn-default-algorithms = -7, -35, -36, -257, -258, -259, -37, -38, -39, -8
  • Standard-Attestierung

    none

    Die Übermittlung der Attestierung steht standardmäßig auf none.

    Von der Prüfung aufgezeichnet
    fact webauthn-attestation = none
  • Standard-Benutzerverifizierung

    preferred

    authenticatorSelection wird standardmäßig als leeres Objekt gesendet, sodass der Browser preferred anwendet.

    Von der Prüfung aufgezeichnet
    fact webauthn-user-verification = preferred
    evidence webauthn-user-verification: authenticatorSelection in BeginRegistration output: {}
  • Standardwert für Resident Key

    discouraged

    Ohne residentKey in den Optionen gilt der WebAuthn-Standardwert discouraged.

    Von der Prüfung aufgezeichnet
    fact webauthn-resident-key = discouraged
  • Benutzerverifizierung standardmäßig erzwungen

    no

    Stand die Benutzerverifizierung der Sitzung auf preferred, bestanden eine Registrierung und eine Assertion, bei denen nur UP gesetzt war, die Prüfung; mit required scheiterte die Assertion mit User verification required but flag not set by authenticator.

    Von der Prüfung aufgezeichnet
    fact webauthn-uv-enforced-by-default = no
    evidence webauthn-uv-enforced-by-default: registration with the UV flag clear, session UV preferred: verified
  • Kodierung der Assertion-Signatur

    der

    Eine korrekte ES256-Assertion mit DER-Signatur bestand die Prüfung.

    Von der Prüfung aufgezeichnet
    fact webauthn-assertion-encoding = der
  • Assertion-Signatur als rohes r‖s

    rejected

    Eine rohe r‖s-Signatur mit 64 Byte scheiterte mit Error validating the assertion signature: Signature invalid or not provided.

    Von der Prüfung aufgezeichnet
    fact webauthn-raw-signature = rejected
  • Assertion-Signatur mit High-S

    accepted

    Eine DER-Signatur, in der s durch n − s ersetzt war, bestand die Prüfung.

    Von der Prüfung aufgezeichnet
    fact webauthn-high-s = accepted
  • Rückläufiger Signaturzähler

    flagged

    Ein Zählerstand von 3 nach gespeicherten 5 ließ die Anmeldung nicht scheitern: Das Credential kam mit CloneWarning auf true und SignCount weiterhin bei 5 zurück.

    Von der Prüfung aufgezeichnet
    fact webauthn-counter-regression = flagged
    evidence webauthn-counter-regression: counter 3 after a stored 5: login succeeded, CloneWarning true, SignCount now 5
    evidence webauthn-counter-regression: counter 0 after a stored 0: verified, CloneWarning false
  • Ed25519-Credentials

    supported

    Ein Ed25519-Credential (COSE -8) ließ sich erfolgreich registrieren und zur Authentifizierung verwenden.

    Von der Prüfung aufgezeichnet
    fact webauthn-ed25519 = supported
    evidence webauthn-ed25519: verified

Verwendung

Konfiguriere die Relying Party so, dass sie Benutzerverifizierung und Discoverable Credentials verlangt, und sieh dir die Richtlinie in den Optionen und in der Sitzung an.
package main

import (
	"fmt"

	"github.com/go-webauthn/webauthn/protocol"
	"github.com/go-webauthn/webauthn/webauthn"
)

type user struct{}

func (user) WebAuthnID() []byte                         { return []byte("user-1") }
func (user) WebAuthnName() string                       { return "user@example.com" }
func (user) WebAuthnDisplayName() string                { return "User" }
func (user) WebAuthnCredentials() []webauthn.Credential { return nil }

func main() {
	w, _ := webauthn.New(&webauthn.Config{
		RPID: "example.com", RPDisplayName: "Example", RPOrigins: []string{"https://example.com"},
		// Without this, options say nothing about UV or discoverable credentials.
		AuthenticatorSelection: protocol.AuthenticatorSelection{
			ResidentKey: protocol.ResidentKeyRequirementRequired, UserVerification: protocol.VerificationRequired,
		},
	})
	creation, session, _ := w.BeginRegistration(user{})
	// The session carries the requirement into FinishRegistration/FinishLogin.
	fmt.Println("uv:", creation.Response.AuthenticatorSelection.UserVerification, session.UserVerification)
	fmt.Println("resident key:", creation.Response.AuthenticatorSelection.ResidentKey)
}

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

Befehl
GOFLAGS=-mod=mod go run .
Ausgabe muss passen (regulärer Ausdruck)
uv: required required\nresident key: required

Bibliotheken