micro/go-micro · error

ap2: invalid signature encoding: %w

Error message

ap2: invalid signature encoding: %w

What it means

VerifyAP2Mandate decodes the mandate's Signature field using base64 RawURL encoding before performing an Ed25519 verification. This error is returned when the signature string is not valid base64url (no padding), so the signature can never be verified. It wraps the underlying base64 decode error with %w.

Source

Thrown at gateway/a2a/ap2.go:87

	}
	if m.Kind == "" {
		return AP2SignedMandate{}, errors.New("ap2: mandate kind is required")
	}
	if m.IssuedAt.IsZero() {
		m.IssuedAt = time.Now().UTC()
	}
	payload, err := ap2Payload(m)
	if err != nil {
		return AP2SignedMandate{}, err
	}
	return AP2SignedMandate{Mandate: m, KeyID: keyID, Signature: base64.RawURLEncoding.EncodeToString(ed25519.Sign(private, payload))}, nil
}

// VerifyAP2Mandate verifies a signed mandate credential.
func VerifyAP2Mandate(s AP2SignedMandate, public ed25519.PublicKey) error {
	sig, err := base64.RawURLEncoding.DecodeString(s.Signature)
	if err != nil {
		return fmt.Errorf("ap2: invalid signature encoding: %w", err)
	}
	payload, err := ap2Payload(s.Mandate)
	if err != nil {
		return err
	}
	if !ed25519.Verify(public, payload, sig) {
		return errors.New("ap2: mandate signature verification failed")
	}
	return nil
}

// AP2BindMandateToMessage returns a copy of m bound to the A2A message's task/context.
func AP2BindMandateToMessage(m AP2Mandate, msg Message) AP2Mandate {
	m.TaskID = msg.TaskID
	m.ContextID = msg.ContextID
	return m
}

View on GitHub (pinned to 24529f1404)

Solutions

  1. Re-encode the signature with base64.RawURLEncoding on the signing side: base64.RawURLEncoding.EncodeToString(sig).
  2. If the incoming value uses padded standard base64, strip '=' and translate +/ to -_ before verification (or fix the producer).
  3. Log the received Signature value and confirm it is a 64-byte Ed25519 signature (86 base64url chars) and not a key or hash.

Example fix

// before (producer)
sig := base64.StdEncoding.EncodeToString(signature)
// after
sig := base64.RawURLEncoding.EncodeToString(signature)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := base64.RawURLEncoding.DecodeString(signed.Signature); err != nil {
    return fmt.Errorf("signature must be base64url without padding: %w", err)
}

Type guard

func validSignatureEncoding(sig string) bool {
    _, err := base64.RawURLEncoding.DecodeString(sig)
    return err == nil && len(sig) == 86
}

Try / catch

err := a2a.VerifyAP2Mandate(signed, pub)
if err != nil && strings.Contains(err.Error(), "invalid signature encoding") {
    // re-encode producer signature with base64.RawURLEncoding
}

Prevention

When it happens

Trigger: Calling gateway/a2a.VerifyAP2Mandate(s, publicKey) where s.Signature contains standard base64 with padding, hex, whitespace, or any characters outside the base64url alphabet — producing 'ap2: invalid signature encoding: <decode error>'.

Common situations: A client signing with base64.StdEncoding (with '=' padding) while the gateway expects RawURLEncoding; the signature being URL-query-decoded and corrupted; a field mix-up sending a key or payload hash in the Signature field.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/21feabffe1d74bf1. Report an issue: GitHub.