Pular para o conteúdo
ecdsa.com
golang-jwt/jwt (Go)Go

Mensagem de erro

token signature is invalid: crypto/ecdsa: verification error

Também aparece como

  • token signature is invalid: crypto/rsa: verification error
  • token signature is invalid: signature is invalid
  • token signature is invalid: ed25519: verification error
  • crypto/ecdsa: verification error

O golang-jwt v4 retorna só o texto interno, por exemplo, “crypto/ecdsa: verification error”. Use `errors.Is(err, jwt.ErrTokenSignatureInvalid)` (v5) em vez de comparar strings.

golang-jwt/jwt (Go) — jwt.ErrTokenSignatureInvalid joined with the algorithm's verification error

O que significa

O golang-jwt analisou o token, aceitou o algoritmo dele e obteve uma chave do seu `Keyfunc`, mas a verificação da assinatura com essa chave falhou. Na v5, o erro combina `jwt.ErrTokenSignatureInvalid` (“token signature is invalid”) com o erro do próprio algoritmo: `crypto/ecdsa: verification error` para ES*, `crypto/rsa: verification error` para RS*/PS*, `signature is invalid` para HS*. Os bytes do token e a chave simplesmente não combinam.

Por que acontece

Como corrigir

  1. 1.

    Obter a chave do JWKS pelo kid

    Deixe o Keyfunc escolher, no conjunto de chaves do emissor, a chave indicada no cabeçalho do token e atualizar esse conjunto na rotação (por exemplo, com `github.com/MicahParks/keyfunc`). Sempre fixe `WithValidMethods`.

    go
    import (
    	"context"
    	"github.com/MicahParks/keyfunc/v3"
    	"github.com/golang-jwt/jwt/v5"
    )
    
    // Resolve the verification key from the issuer's JWKS by the token's kid.
    k, err := keyfunc.NewDefaultCtx(ctx, []string{"https://issuer.example.com/.well-known/jwks.json"})
    if err != nil {
    	return err
    }
    token, err := jwt.Parse(raw, k.Keyfunc,
    	jwt.WithValidMethods([]string{"ES256"}),
    	jwt.WithIssuer("https://issuer.example.com/"),
    	jwt.WithAudience("https://api.example.com"))
  2. 2.

    Comprovar que os dois lados usam a mesma chave

    Calcule o hash da chave pública em codificação DER no verificador e o da metade pública da chave privada do emissor. Hashes diferentes encerram a investigação.

    bash
    # Same key on both sides? Compare SPKI fingerprints.
    openssl pkey -pubin -in verifier-public.pem -outform DER | sha256sum
    openssl pkey -in issuer-private.pem -pubout -outform DER | sha256sum
  3. 3.

    Tratar a classe do erro, e não o texto

    O golang-jwt v5 expõe erros sentinela. Mapeie uma falha de assinatura para 401 e não recorra a tentar outras chaves nem a pular a verificação.

    go
    switch {
    case errors.Is(err, jwt.ErrTokenSignatureInvalid):
    	return http.StatusUnauthorized // wrong key or tampered token: never retry with another key blindly
    case errors.Is(err, jwt.ErrTokenExpired):
    	return http.StatusUnauthorized // client should refresh
    case errors.Is(err, jwt.ErrTokenMalformed):
    	return http.StatusBadRequest
    }

Erros relacionados

Ver toda a base de erros de assinatura