Error message
go-jose/go-jose: error in cryptographic primitive
Also printed as
- square/go-jose: error in cryptographic primitive
go-jose v2 (imported as gopkg.in/square/go-jose.v2) used the prefix "square/go-jose:"; v3 and v4 use "go-jose/go-jose:". The same error is returned for JWE decryption failures.
go-jose (Go) — jose.ErrCryptoFailure from JSONWebSignature.Verify / jwt.JSONWebToken.Claims
What it means
go-jose's generic signature (or decryption) failure, `jose.ErrCryptoFailure`. The JWS parsed and the algorithm was allowed, but verifying the signature with the key you passed failed. go-jose deliberately does not say more — wrong key and modified token look the same to a verifier — so the investigation is always: which key did you pass, and was the token changed?
Why it happens
The key does not belong to the signer
commonA key from another environment or tenant, or a public key that was replaced by the issuer during rotation.
The key set was searched without kid
commonCode that takes `keys.Keys[0]` instead of `keys.Key(kid)` verifies with the first key of the set. It works until the issuer publishes a second key.
Header or payload was modified
occasionalThe signature covers the exact base64url bytes. Re-serialising the payload, or combining parts of two tokens, breaks verification.
Decrypting with the wrong private key
occasionalFor JWE tokens the same error means the content-encryption key could not be unwrapped or the authentication tag did not verify — the token was encrypted for a different recipient key.
How to fix it
- 1.
Select the key by kid, then validate claims
Resolve exactly one key by the header's `kid` from the issuer's JWKS, verify, and then validate `iss`, `aud` and `exp` with `Claims.Validate` — go-jose does not check claims on its own.
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()})