Saltar al contenido
ecdsa.com
Go

go-webauthn

go-webauthn, la biblioteca de relying party WebAuthn para Go: firmas de aserción solo en DER, verificación del usuario determinada por la sesión y retrocesos del contador notificados como advertencia de clonación en lugar de como inicio de sesión fallido.
Licencia
BSD-3-Clause
Versión comprobada
0.18.2 ·
Código fuente
github.com/go-webauthn/webauthn
Documentación
pkg.go.dev/github.com/go-webauthn/webauthn/webauthn

Compatibilidad de un vistazo

WebAuthn

github.com/go-webauthn/webauthn (el fork mantenido de duo-labs/webauthn) ejecuta las dos ceremonias —BeginRegistration/FinishRegistration y BeginLogin/FinishLogin, o sus variantes Validate* para frameworks distintos de net/http— y verifica todos los formatos de atestación. La comprobación validó las mismas respuestas de un autenticador por software que se usaron con SimpleWebAuthn, py_webauthn y WebAuthn4J.

La política sale de la configuración y viaja en SessionData. Con un AuthenticatorSelection vacío, BeginRegistration envió un objeto vacío, así que los navegadores aplican los valores predeterminados —verificación del usuario preferred, clave residente discouraged— y la validación aceptó respuestas con el indicador UV desactivado porque la sesión solo pedía preferred. Con UserVerification: required en la sesión, la misma aserción falló con User verification required but flag not set by authenticator. Establece la política en Config.AuthenticatorSelection, como hace el ejemplo, y guarda el SessionData completo entre las dos llamadas.

El tratamiento del contador es la diferencia más importante respecto de las demás bibliotecas. Con una aserción cuyo contador (3) era menor que el almacenado (5), el inicio de sesión se completó correctamente: la credencial devuelta tenía Authenticator.CloneWarning activado y su SignCount seguía en 5. La biblioteca solo informa de un posible clon; rechazar o no el inicio de sesión le corresponde a tu código, que debe comprobar CloneWarning después de cada inicio de sesión.

Las firmas de aserción deben ser DER ASN.1 —una firma r‖s en bruto de 64 bytes falló con Error validating the assertion signature: Signature invalid or not provided— y una firma DER high-S se verificó. La lista predeterminada de pubKeyCredParams es larga: ES256, ES384 y ES512 (-7, -35, -36), de RS256 a RS512 (de -257 a -259), de PS256 a PS512 (de -37 a -39) y Ed25519 (-8); la credencial Ed25519 se verificó de principio a fin. La 0.18.2 no tiene ninguna entrada ML-DSA.

Decodifica lo que envía un navegador con el inspector de WebAuthn, busca modelos de autenticador con la búsqueda de AAGUID y prueba ceremonias en el entorno de pruebas de llaves de acceso.

Datos y las comprobaciones que los respaldan

Nada de lo que sigue está copiado de la documentación. La comprobación content/libraries/verify/go-webauthn/run.sh ejecutó go-webauthn 0.18.2 en la imagen de contenedor golang:1.27.3-trixie el 20 de octubre de 2026; la página debe coincidir con lo que imprimió, y cada dato cita esas líneas.

  • Algoritmos COSE predeterminados

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

    BeginRegistration enumera los algoritmos COSE -7, -35, -36 (ES256/384/512), -257, -258, -259 (RS256/384/512), -37, -38, -39 (PS256/384/512) y -8 (Ed25519).

    Registrado por la comprobación
    fact webauthn-default-algorithms = -7, -35, -36, -257, -258, -259, -37, -38, -39, -8
  • Atestación predeterminada

    none

    La preferencia de transmisión de la atestación es none por defecto.

    Registrado por la comprobación
    fact webauthn-attestation = none
  • Verificación del usuario predeterminada

    preferred

    authenticatorSelection se envía por defecto como un objeto vacío, así que el navegador aplica preferred.

    Registrado por la comprobación
    fact webauthn-user-verification = preferred
    evidence webauthn-user-verification: authenticatorSelection in BeginRegistration output: {}
  • Clave residente predeterminada

    discouraged

    Sin residentKey en las opciones, se aplica el valor predeterminado de WebAuthn, discouraged.

    Registrado por la comprobación
    fact webauthn-resident-key = discouraged
  • Verificación del usuario exigida por defecto

    no

    Con la verificación del usuario de la sesión en preferred, un registro y una aserción con solo UP activado se verificaron; con required, la aserción falló con User verification required but flag not set by authenticator.

    Registrado por la comprobación
    fact webauthn-uv-enforced-by-default = no
    evidence webauthn-uv-enforced-by-default: registration with the UV flag clear, session UV preferred: verified
  • Codificación de la firma de la aserción

    der

    Una aserción ES256 correcta con firma DER se verificó.

    Registrado por la comprobación
    fact webauthn-assertion-encoding = der
  • Firma de aserción r‖s en bruto

    rejected

    Una firma r‖s en bruto de 64 bytes falló con Error validating the assertion signature: Signature invalid or not provided.

    Registrado por la comprobación
    fact webauthn-raw-signature = rejected
  • Firma de aserción high-S

    accepted

    Una firma DER con s sustituido por n − s se verificó.

    Registrado por la comprobación
    fact webauthn-high-s = accepted
  • Contador de firmas que retrocede

    flagged

    Un contador de 3 tras un 5 almacenado no hizo fallar el inicio de sesión: la credencial volvió con CloneWarning en true y SignCount todavía en 5.

    Registrado por la comprobación
    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
  • Credenciales Ed25519

    supported

    Una credencial Ed25519 (COSE -8) se registró y se autenticó correctamente.

    Registrado por la comprobación
    fact webauthn-ed25519 = supported
    evidence webauthn-ed25519: verified

Uso

Configura la relying party para que exija la verificación del usuario y credenciales detectables, y observa la política en las opciones y en la sesión.
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)
}

El arnés de pruebas de fragmentos de código ejecuta cada ejemplo tal cual en la imagen de contenedor golang:1.27.3-trixie, y la ejecución falla si la salida no coincide.

Comando
GOFLAGS=-mod=mod go run .
La salida debe coincidir (expresión regular)
uv: required required\nresident key: required

Bibliotecas