{"record":{"id":"eea640b4469286ef","repo":"caddyserver/caddy","slug":"parsing-public-key-w","errorCode":null,"errorMessage":"parsing public_key: %w","messagePattern":"parsing public_key: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/ech.go","lineNumber":1001,"sourceCode":"\tvar t cryptobyte.String\n\tvar pk []byte\n\n\tif !content.ReadUint8(&echCfg.ConfigID) ||\n\t\t!content.ReadUint16((*uint16)(&echCfg.KEMID)) ||\n\t\t!content.ReadUint16LengthPrefixed(&t) ||\n\t\t!t.ReadBytes(&pk, len(t)) ||\n\t\t!content.ReadUint16LengthPrefixed(&t) ||\n\t\tlen(t)%4 != 0 /* the length of (KDFs and AEADs) must be divisible by 4 */ {\n\t\treturn errInvalidLen\n\t}\n\n\tif !echCfg.KEMID.IsValid() {\n\t\treturn fmt.Errorf(\"invalid KEM ID: %d\", echCfg.KEMID)\n\t}\n\n\tvar err error\n\tif echCfg.PublicKey, err = echCfg.KEMID.Scheme().UnmarshalBinaryPublicKey(pk); err != nil {\n\t\treturn fmt.Errorf(\"parsing public_key: %w\", err)\n\t}\n\n\techCfg.CipherSuites = echCfg.CipherSuites[:0]\n\n\tfor !t.Empty() {\n\t\tvar hpkeKDF, hpkeAEAD uint16\n\t\tif !t.ReadUint16(&hpkeKDF) || !t.ReadUint16(&hpkeAEAD) {\n\t\t\t// we have already checked that the length is divisible by 4\n\t\t\tpanic(\"this must not happen\")\n\t\t}\n\t\tif !hpke.KDF(hpkeKDF).IsValid() {\n\t\t\treturn fmt.Errorf(\"invalid KDF ID: %d\", hpkeKDF)\n\t\t}\n\t\tif !hpke.AEAD(hpkeAEAD).IsValid() {\n\t\t\treturn fmt.Errorf(\"invalid AEAD ID: %d\", hpkeAEAD)\n\t\t}\n\t\techCfg.CipherSuites = append(echCfg.CipherSuites, hpkeSymmetricCipherSuite{\n\t\t\tKDFID:  hpke.KDF(hpkeKDF),","sourceCodeStart":983,"sourceCodeEnd":1019,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/ech.go#L983-L1019","documentation":"After the KEM check, UnmarshalBinary parses the public_key field via the KEM scheme's UnmarshalBinaryPublicKey. Malformed or wrong-length key bytes (not a valid X25519 public key) produce this wrapped error. For X25519 the expected length is exactly 32 bytes, so truncated or expanded blobs fail here.","triggerScenarios":"Stored ECH config where the length-prefixed public key blob is not 32 bytes or not a valid curve point encoding — corruption, wrong-version data, or a config list crafted for another KEM.","commonSituations":"Truncated config.bin from an interrupted storage write; storage backend with byte-mangling bugs; hand-assembled ECH configs for testing.","solutions":["Delete the suspect ech/configs/<id>/config.bin (whole ID directory) so Caddy mints a fresh config.","If importing, ensure the public key is a raw 32-byte X25519 key inside the ECHConfig structure.","Check storage reliability if files keep truncating."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"parsing public_key\") {\n    // corrupt stored config: delete ech/configs/<id> and restart to regenerate\n}","preventionTips":["Use atomic/copy-safe storage migration for the Caddy data dir.","Regenerate rather than repair ECH configs — they are cheap and rotate by design."],"tags":["tls","ech","crypto","hpke","serialization"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}