golang/go · error

unsupported AEAD %04x

Error message

unsupported AEAD %04x

What it means

`hpke.NewAEAD(id uint16)` resolves an AEAD algorithm identifier from the HPKE IANA registry. Only four IDs are recognized: 0x0001 (AES-128-GCM), 0x0002 (AES-256-GCM), 0x0003 (ChaCha20Poly1305), and 0xFFFF (Export-only). Any other ID returns this error. Callers normally receive the ID from a KEM/key-package header parsed off the wire.

Source

Thrown at src/crypto/hpke/aead.go:39

	aead(key []byte) (cipher.AEAD, error)
}

// NewAEAD returns the AEAD implementation for the given AEAD ID.
//
// Applications are encouraged to use specific implementations like [AES128GCM]
// or [ChaCha20Poly1305] instead, unless runtime agility is required.
func NewAEAD(id uint16) (AEAD, error) {
	switch id {
	case 0x0001: // AES-128-GCM
		return AES128GCM(), nil
	case 0x0002: // AES-256-GCM
		return AES256GCM(), nil
	case 0x0003: // ChaCha20Poly1305
		return ChaCha20Poly1305(), nil
	case 0xFFFF: // Export-only
		return ExportOnly(), nil
	default:
		return nil, fmt.Errorf("unsupported AEAD %04x", id)
	}
}

// AES128GCM returns an AES-128-GCM AEAD implementation.
func AES128GCM() AEAD { return aes128GCM }

// AES256GCM returns an AES-256-GCM AEAD implementation.
func AES256GCM() AEAD { return aes256GCM }

// ChaCha20Poly1305 returns a ChaCha20Poly1305 AEAD implementation.
func ChaCha20Poly1305() AEAD { return chacha20poly1305AEAD }

// ExportOnly returns a placeholder AEAD implementation that cannot encrypt or
// decrypt, but only export secrets with [Sender.Export] or [Recipient.Export].
//
// When this is used, [Sender.Seal] and [Recipient.Open] return errors.
func ExportOnly() AEAD { return exportOnlyAEAD{} }

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Inspect the suite ID bytes being parsed and compare against the four supported constants; log the value for diagnosis.
  2. Update the Go toolchain / x/crypto to a version that supports the AEAD you need.
  3. If you control both peers, restrict configuration to one of {0x0001, 0x0002, 0x0003}.
  4. Treat the error as a hard protocol failure — do not fall back to a weaker AEAD silently.

Example fix

// before
a, err := hpke.NewAEAD(suite.AEADID) // suite from peer, may be 0x000D
// after
switch suite.AEADID {
case 0x0001, 0x0002, 0x0003:
    a, err = hpke.NewAEAD(suite.AEADID)
default:
    return fmt.Errorf("peer offered unsupported AEAD %04x", suite.AEADID)
}
Defensive patterns

Strategy: type-guard

Validate before calling

supportedAEAD := map[uint16]bool{0x0001:true, 0x0002:true, 0x0003:true, 0xFFFF:true}
if !supportedAEAD[id] {
    return fmt.Errorf("AEAD %04x not supported", id)
}

Type guard

func isSupportedAEAD(id uint16) bool {
    switch id {
    case 0x0001, 0x0002, 0x0003, 0xFFFF:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: A peer proposes an AEAD the local registry does not support (e.g. AES-128-CCM, 0x000D); a malformed/test vector with a typo'd ID; an implementation that only knows a subset (e.g. excludes Export-only); version skew between two HPKE stacks.

Common situations: Interop with a newer draft/RFC that added an AEAD not in this Go version; cipher-suite negotiation bug where the receiver honors an ID it never registered; fuzz/corruption of the HPKE mode byte.

Related errors


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