golang/go · error

tls: invalid or missing PSK binders

Error message

tls: invalid or missing PSK binders

What it means

RFC 8446 §4.2.11 requires the number of PSK identities to equal the number of binders, in order. If len(pskIdentities) != len(pskBinders), the ClientHello is malformed; the server sends illegal_parameter.

Source

Thrown at src/crypto/tls/handshake_server_tls13.go:312

	if c.config.SessionTicketsDisabled {
		return nil
	}

	modeOK := false
	for _, mode := range hs.clientHello.pskModes {
		if mode == pskModeDHE {
			modeOK = true
			break
		}
	}
	if !modeOK {
		return nil
	}

	if len(hs.clientHello.pskIdentities) != len(hs.clientHello.pskBinders) {
		c.sendAlert(alertIllegalParameter)
		return errors.New("tls: invalid or missing PSK binders")
	}
	if len(hs.clientHello.pskIdentities) == 0 {
		return nil
	}

	for i, identity := range hs.clientHello.pskIdentities {
		if i >= maxClientPSKIdentities {
			break
		}

		var sessionState *SessionState
		if c.config.UnwrapSession != nil {
			var err error
			sessionState, err = c.config.UnwrapSession(identity.label, c.connectionStateLocked())
			if err != nil {
				return err
			}
			if sessionState == nil {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Ensure each PSK identity has exactly one corresponding binder, in the same order
  2. Use a compliant TLS library to construct the pre_shared_key extension rather than building it by hand

Example fix

// before
identities = []pskIdentity{a, b, c}
binders = [][]byte{ba, bb} // missing c

// after
identities = []pskIdentity{a, b, c}
binders = [][]byte{ba, bb, bc}
Defensive patterns

Strategy: validation

Validate before calling

// Client-side: before sending, assert identity/binder counts match.
if len(pskIdentities) != len(pskBinders) {
    return fmt.Errorf("psk mismatch: %d identities vs %d binders", len(pskIdentities), len(pskBinders))
}

Try / catch

if err := tlsConn.Handshake(); err != nil {
    if strings.Contains(err.Error(), "invalid or missing PSK binders") {
        log.Printf("malformed pre_shared_key from %v", remote)
    }
    c.Close()
    return
}

Prevention

When it happens

Trigger: Client sends 3 identities but 2 binders, or any count mismatch. Occurs when a ClientHello is constructed with mismatched identity/binder lists.

Common situations: Buggy session-resumption code that appends an identity without its binder; fuzzers; attackers hand-crafting ClientHellos.

Understand the failure class

Related errors


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