golang/go · error · ErrVerification

crypto/rsa: verification error

Error message

crypto/rsa: verification error

What it means

ErrVerification is a sentinel error (var) returned by VerifyPKCS1v15 and VerifyPSS when the signature does not validate — wrong public key, wrong hash algorithm, tampered message, or malformed signature encoding. Like ErrDecryption, it is deliberately vague to avoid adaptive signature attacks; callers must not branch on the underlying cause.

Source

Thrown at src/crypto/rsa/rsa.go:549

	if err := priv.Validate(); err != nil {
		return nil, err
	}

	return priv, nil
}

// ErrMessageTooLong is returned when attempting to encrypt or sign a message
// which is too large for the size of the key. When using [SignPSS], this can also
// be returned if the size of the salt is too large.
var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA key size")

// ErrDecryption represents a failure to decrypt a message.
// It is deliberately vague to avoid adaptive attacks.
var ErrDecryption = errors.New("crypto/rsa: decryption error")

// ErrVerification represents a failure to verify a signature.
// It is deliberately vague to avoid adaptive attacks.
var ErrVerification = errors.New("crypto/rsa: verification error")

// Precompute performs some calculations that speed up private key operations in
// the future. It is safe to run on non-validated private keys, and it can speed
// up future calls to [PrivateKey.Validate] for valid keys.
//
// Precompute writes to the Precomputed field, so it must not be called
// concurrently with any other method.
//
// Precompute does not return an error. Applications should call
// [PrivateKey.Validate] after Precompute to check for any problems with the
// key, including any that would cause Precompute to fail.
//
// Calling Precompute on a key that has already been precomputed is a no-op.
func (priv *PrivateKey) Precompute() {
	if priv.precomputedIsConsistent() {
		return
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Confirm the public key (kid) matches the signing key before calling Verify*.
  2. Confirm the hash identifier and digest computation match what the signer used (including any canonicalization).
  3. For PSS, ensure opts.SaltLength on the verifier matches the signer's choice (or use rsa.PSSSaltLengthEqualsHash / auto on both sides).
  4. Compare with errors.Is(err, rsa.ErrVerification) and treat all verification failures uniformly.

Example fix

// before
err := rsa.VerifyPSS(pub, crypto.SHA256, digest, sig, &rsa.PSSOptions{SaltLength: 64})
if err != nil {
    log.Printf("sig invalid because: %v", err) // leaks and is meaningless
}

// after
err := rsa.VerifyPSS(pub, crypto.SHA256, digest, sig, &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash})
if errors.Is(err, rsa.ErrVerification) {
    return errors.New("signature rejected")
}
Defensive patterns

Strategy: try-catch

Try / catch

err := rsa.VerifyPSS(pub, crypto.SHA256, digest, sig, opts)
if errors.Is(err, rsa.ErrVerification) {
    return errors.New("signature rejected")
}

Prevention

When it happens

Trigger: rsa.VerifyPKCS1v15(pub, crypto.SHA256, digest, sig) where sig was produced under a different key or with a different hash; rsa.VerifyPSS with mismatched SaltLength between signer and verifier; truncated signature bytes; signature computed over a different digest than the one passed in.

Common situations: JWT/RS256 verification with the wrong JWKS key; clock/key-rotation mismatch where the verifier holds a newer pub key than the signer used; wrong hash identifier in a header (SHA-1 vs SHA-256); signature transferred as base64url while decoded as base64.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/c0f6e79624d2e4af. Report an issue: GitHub.