golang/go · error
private key seed not available
Error message
private key seed not available
What it means
Raised by hybridPrivateKey.Bytes() when k.seed is nil. The seed is only retained when the key was constructed through the generate/derive path that captures it; a key assembled from externally supplied parts has no storable seed, so returning the raw private bytes is impossible.
Source
Thrown at src/crypto/hpke/pq.go:320
}
}
func (kem *hybridKEM) DeriveKeyPair(ikm []byte) (PrivateKey, error) {
suiteID := byteorder.BEAppendUint16([]byte("KEM"), kem.id)
dk, err := SHAKE256().labeledDerive(suiteID, ikm, "DeriveKeyPair", nil, 32)
if err != nil {
return nil, err
}
return kem.NewPrivateKey(dk)
}
func (k *hybridPrivateKey) KEM() KEM {
return k.kem
}
func (k *hybridPrivateKey) Bytes() ([]byte, error) {
if k.seed == nil {
return nil, errors.New("private key seed not available")
}
return k.seed, nil
}
func (k *hybridPrivateKey) PublicKey() PublicKey {
return &hybridPublicKey{
kem: k.kem,
t: k.t.PublicKey(),
pq: k.pq.Encapsulator(),
}
}
func (k *hybridPrivateKey) decap(enc []byte) ([]byte, error) {
if len(enc) != k.kem.pqCiphertextSize+k.kem.curvePointSize {
return nil, errors.New("invalid encapsulated key size")
}
ctPQ, ctT := enc[:k.kem.pqCiphertextSize], enc[k.kem.pqCiphertextSize:]
ssPQ, err := k.pq.Decapsulate(ctPQ)View on GitHub (pinned to b6b368adc5)
Solutions
- Generate the key via the suite's KEM.GenerateKey() or DeriveKeyPair() so the seed is retained and Bytes() succeeds.
- If you must assemble from parts, store the seed yourself at construction time instead of relying on Bytes().
- Check for the error (or pre-check whether the key came from the generate path) before attempting serialization.
Example fix
// before priv, _ := MLKEM768P256().NewPrivateKey(externalParts) // seed == nil seed, err := priv.Bytes() // errors // after priv, _ := MLKEM768P256().GenerateKey(rand.Reader) // seed retained seed, err := priv.Bytes() // ok
Defensive patterns
Strategy: try-catch
Validate before calling
// Before serializing, confirm the key came from a seed-retaining path.
func canSerialize(p hpke.PrivateKey) bool {
_, err := p.Bytes()
return err == nil
} Try / catch
if b, err := priv.Bytes(); err != nil {
if err.Error() == "private key seed not available" {
// regenerate from seed or refuse to persist
}
return err
} else {
_ = b
} Prevention
- Generate keys via KEM.GenerateKey/DeriveKeyPair when future serialization is needed.
- If you assemble from parts, store the seed yourself.
- Gate persistence on a successful Bytes() call.
When it happens
Trigger: Calling PrivateKey.Bytes() on a hybridPrivateKey whose seed field is nil — typically a key built via NewHybridPrivateKey from pre-existing ML-KEM and ECDH key material rather than generated/derived in-package.
Common situations: Serializing a hybrid private key for storage/transport after constructing it from independently generated parts; calling Bytes() on a key obtained via NewHybridPrivateKey rather than GenerateKey/DeriveKeyPair; persistence code that assumes every private key is serializable.
Related errors
- invalid encapsulated key size
- ecdh: private key does not support Bytes
- 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/6fe7a803c69864e6.
Report an issue: GitHub.