OpenNHP/opennhp · error
private key too short: got
Error message
private key too short: got %d bytes, need %d
What it means
Curve25519ECDH.SetPrivateKey validates that the supplied private key material is at least PrivateKeySize (32) bytes before copying it into the fixed 32-byte PrivKey array. If the input is shorter, the X25519 scalar would be silently under-sized, so the library rejects it with this error instead of producing a wrong/weak key pair. It is a defensive length check on ECDH key initialization.
Solutions
- Check len(prk) >= 32 at the call site and fix the key source (re-decode base64, use the full key string).
- Regenerate the key pair with the daemon's `keygen --curve` command and paste the complete 32-byte (44-char base64) private key.
- If the key is stored as hex/base64, verify the decoding method matches the storage encoding before calling SetPrivateKey.
- If the key comes from a KDF, ensure the output length is exactly 32 bytes (e.g. XOF/sha256 with size 32).
Example fix
// before
prk := keyBytes[:16] // accidentally truncated
ecdhe := curve.NewECDH()
err := ecdhe.SetPrivateKey(prk)
// after
if len(keyBytes) < curve.PrivateKeySize {
return fmt.Errorf("key source provided %d bytes", len(keyBytes))
}
err := ecdhe.SetPrivateKey(keyBytes[:curve.PrivateKeySize]) Defensive patterns
Strategy: validation
Validate before calling
// Go
func validCurvePrivKey(b []byte) bool { return len(b) >= curve.PrivateKeySize } // PrivateKeySize == 32
if !validCurvePrivKey(keyBytes) {
return fmt.Errorf("curve private key must be 32 bytes, got %d", len(keyBytes))
} Try / catch
if err := ecdhe.SetPrivateKey(prk); err != nil {
if strings.Contains(err.Error(), "private key too short") {
// recover: re-load or regenerate key pair
}
return err
} Prevention
- Always decode keys with base64.StdEncoding and assert decoded length equals 32 before use.
- Never slice key material by guesswork; use the package's PrivateKeySize constant.
- Store keys generated by `keygen --curve` verbatim, without trimming or reformatting.
- Add a startup sanity check that all configured keys decode to the expected length.
When it happens
Trigger: Calling (*Curve25519ECDH).SetPrivateKey with a byte slice shorter than 32 bytes, directly or indirectly via NewECDH's key-setting path or ECDHFromKey, e.g. passing a truncated base64-decoded key, a hex string decoded to 16 bytes, or a seed/derivation output that returned fewer bytes than expected.
Common situations: Loading a private key from config.toml where the value was truncated or mis-pasted; decoding a key with the wrong base64/hex assumption; generating keys with a different tool that outputs 16- or 24-byte keys; a key-derivation function returning a shortened seed.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- private key too short: got
- private key parse error
- failed to create device
- failed to create device
- failed to create device from new key
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/ca0797fb69fc0995.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/scheme/curve/curve.go:26
"golang.org/x/crypto/curve25519"
)
const (
PrivateKeySize = 32
PublicKeySize = 32
)
type Curve25519ECDH struct {
PrivKey [PrivateKeySize]byte
PubKey [PublicKeySize]byte
PrivKeyBase64 string
PubKeyBase64 string
BriefName string
}
func (c *Curve25519ECDH) SetPrivateKey(prk []byte) (err error) {
if len(prk) < PrivateKeySize {
return fmt.Errorf("private key too short: got %d bytes, need %d", len(prk), PrivateKeySize)
}
copy(c.PrivKey[:], prk[:PrivateKeySize])
pbk, err := curve25519.X25519(c.PrivKey[:], curve25519.Basepoint)
if err != nil {
return err
}
copy(c.PubKey[:], pbk)
c.PrivKeyBase64 = base64.StdEncoding.EncodeToString(c.PrivKey[:])
c.PubKeyBase64 = base64.StdEncoding.EncodeToString(c.PubKey[:])
c.BriefName = fmt.Sprintf("%s...%s", c.PubKeyBase64[0:4], c.PubKeyBase64[39:43])
return nil
}
func (c *Curve25519ECDH) PrivateKey() []byte {
return c.PrivKey[:]
}
View on GitHub (pinned to 6e04ca5ff0)