golang/go · error
invalid public key size
Error message
invalid public key size
What it means
hybridKEM.NewPublicKey deserializes a combined hybrid public key blob (PQ encapsulation key || ECDH point). The total length must equal kem.pqEncapsKeySize + kem.curvePointSize, fixed by the chosen combiner. Any other length is rejected before any parsing.
Source
Thrown at src/crypto/hpke/pq.go:166
return &hybridPublicKey{mlkem768X25519, t, pq}, nil
case ecdh.P256():
if _, ok := pq.(*mlkem.EncapsulationKey768); !ok {
return nil, errors.New("invalid PQ KEM for P-256 hybrid")
}
return &hybridPublicKey{mlkem768P256, t, pq}, nil
case ecdh.P384():
if _, ok := pq.(*mlkem.EncapsulationKey1024); !ok {
return nil, errors.New("invalid PQ KEM for P-384 hybrid")
}
return &hybridPublicKey{mlkem1024P384, t, pq}, nil
default:
return nil, errors.New("unsupported curve")
}
}
func (kem *hybridKEM) NewPublicKey(data []byte) (PublicKey, error) {
if len(data) != kem.pqEncapsKeySize+kem.curvePointSize {
return nil, errors.New("invalid public key size")
}
pq, err := kem.pqNewPublicKey(data[:kem.pqEncapsKeySize])
if err != nil {
return nil, err
}
var k *ecdh.PublicKey
fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved.
k, err = kem.curve.NewPublicKey(data[kem.pqEncapsKeySize:])
})
if err != nil {
return nil, err
}
return NewHybridPublicKey(pq, k)
}
func (pk *hybridPublicKey) KEM() KEM {
return pk.kem
}View on GitHub (pinned to b6b368adc5)
Solutions
- Ensure the blob is exactly pqEncapsKeySize + curvePointSize bytes for the chosen combiner.
- Match sender and recipient KEM (e.g. both MLKEM768X25519).
- Verify length on the wire before invoking NewPublicKey and emit a clearer framing error.
Example fix
// before
// data was truncated in transit
pub, err := hpke.MLKEM768X25519().NewPublicKey(data) // "invalid public key size"
// after
const want = 1184 + 32 // ML-KEM-768 encapsulation key + X25519 point
if len(data) != want {
return fmt.Errorf("hybrid pubkey: got %d want %d", len(data), want)
}
pub, err := hpke.MLKEM768X25519().NewPublicKey(data) Defensive patterns
Strategy: validation
Validate before calling
var hybridKeyLen = map[uint16]int{
0x647A: 1184 + 32, // MLKEM768-X25519
0x0050: 1184 + 65, // MLKEM768-P256
0x0051: 1568 + 97, // MLKEM1024-P384
}
func parseHybridPub(kemID uint16, data []byte) (hpke.PublicKey, error) {
want, ok := hybridKeyLen[kemID]
if !ok {
return nil, fmt.Errorf("unknown hybrid kem 0x%04x", kemID)
}
if len(data) != want {
return nil, fmt.Errorf("hybrid pubkey length: got %d want %d", len(data), want)
}
return hpke.NewKEM(kemID).NewPublicKey(data)
} Try / catch
pub, err := kem.NewPublicKey(data)
if err != nil && err.Error() == "invalid public key size" {
return nil, fmt.Errorf("framing mismatch: blob %d bytes does not match combiner layout", len(data))
} Prevention
- Length-prefix the serialized hybrid key on the wire and verify before parsing.
- Tag blobs with their combiner ID so receiver and sender agree on layout.
- Round-trip test Bytes()/NewPublicKey for every combiner.
When it happens
Trigger: Calling MLKEM768X25519().NewPublicKey(data) (or the P256/P384 equivalents) with data whose length does not match the combiner's fixed sum. Triggered by truncation, trailing bytes, or mixing key formats from a different combiner.
Common situations: Sender used a different hybrid KEM than receiver; raw bytes were padded/stripped in transit; misreading the spec on byte layout.
Related errors
- hpke: invalid hybrid KEM secret length
- ciphertext too short
- invalid PQ KEM for X25519 hybrid
- invalid PQ KEM for P-256 hybrid
- invalid PQ KEM for P-384 hybrid
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/ab6ae34a08dcd7e5.
Report an issue: GitHub.