Mensagem de erro
go-jose/go-jose: error in cryptographic primitive
Também aparece como
- square/go-jose: error in cryptographic primitive
O go-jose v2 (importado como gopkg.in/square/go-jose.v2) usava o prefixo “square/go-jose:”; a v3 e a v4 usam “go-jose/go-jose:”. O mesmo erro é retornado em falhas de descriptografia de JWE.
go-jose (Go) — jose.ErrCryptoFailure from JSONWebSignature.Verify / jwt.JSONWebToken.Claims
O que significa
É a falha genérica de assinatura (ou de descriptografia) do go-jose, `jose.ErrCryptoFailure`. O JWS foi interpretado sem erros e o algoritmo era permitido, mas a verificação da assinatura com a chave que você passou falhou. O go-jose não diz mais nada de propósito — para um verificador, chave errada e token modificado parecem iguais — e, por isso, a investigação é sempre esta: qual chave você passou? O token foi alterado?
Por que acontece
A chave não pertence ao signatário
comumUma chave de outro ambiente ou locatário, ou uma chave pública que o emissor substituiu durante uma rotação.
O conjunto de chaves foi consultado sem o kid
comumUm código que pega `keys.Keys[0]` em vez de `keys.Key(kid)` verifica com a primeira chave do conjunto. Funciona até o emissor publicar uma segunda chave.
O cabeçalho ou o payload foi modificado
ocasionalA assinatura cobre exatamente os bytes em base64url. Serializar o payload de novo, ou combinar partes de dois tokens, quebra a verificação.
Descriptografia com a chave privada errada
ocasionalEm tokens JWE, o mesmo erro significa que não foi possível desencapsular a chave de criptografia de conteúdo ou que a verificação da tag de autenticação falhou — o token foi criptografado para a chave de outro destinatário.
Como corrigir
- 1.
Selecionar a chave pelo kid e depois validar as claims
Obtenha exatamente uma chave do JWKS do emissor pelo `kid` do cabeçalho, verifique o token e depois valide `iss`, `aud` e `exp` com `Claims.Validate` — o go-jose não verifica as claims por conta própria.
go // keys: *jose.JSONWebKeySet fetched from the issuer's jwks_uri parsed, err := jwt.ParseSigned(raw, []jose.SignatureAlgorithm{jose.ES256}) if err != nil { return err } kid := parsed.Headers[0].KeyID matches := keys.Key(kid) // all keys with this kid if len(matches) != 1 { return fmt.Errorf("no unique key for kid %q", kid) } var claims jwt.Claims if err := parsed.Claims(matches[0].Key, &claims); err != nil { return err } return claims.Validate(jwt.Expected{Issuer: "https://issuer.example.com/", AnyAudience: jwt.Audience{"api"}, Time: time.Now()})