OpenNHP/opennhp · error
private key too short: got
Error message
private key too short: got %d bytes, need %d
What it means
SM2ECDH.SetPrivateKey requires at least 32 bytes of private key material before copying it into the fixed 32-byte PrivKey array and constructing an ecdh.P256 private key. Shorter input cannot be a valid 32-byte P-256/SM2 scalar, so the library fails fast with this error. It mirrors the curve25519 scheme's length guard for the SM cipher suite.
Solutions
- Verify the key input is exactly 32 bytes (44-char standard base64) before calling SetPrivateKey.
- Regenerate SM2 keys with `keygen --sm2` and use the full private key string from the output.
- Confirm the key loaded from config is non-empty and not truncated (log its decoded length).
- Use the scheme's Base64DecodeSM2ECDHPrivateKey helper, which enforces the same 32-byte check with a clearer boundary.
Example fix
// before
err := ecdh.SetPrivateKey([]byte(cfg.PrivateKey)) // raw config text, wrong length
// after
raw, err := base64.StdEncoding.DecodeString(cfg.PrivateKey)
if err != nil || len(raw) != gmsm.PrivateKeySize {
return fmt.Errorf("invalid SM2 private key: decoded %d bytes", len(raw))
}
err = ecdh.SetPrivateKey(raw) Defensive patterns
Strategy: validation
Validate before calling
// Go
raw, err := base64.StdEncoding.DecodeString(keyStr)
if err != nil || len(raw) != gmsm.PrivateKeySize { // 32
return fmt.Errorf("SM2 private key must decode to 32 bytes")
}
err = ecdhe.SetPrivateKey(raw) Try / catch
if err := ecdhe.SetPrivateKey(prk); err != nil {
if strings.Contains(err.Error(), "private key too short") {
// fall back to regenerating keys or abort startup with a clear config message
}
return err
} Prevention
- Keep curve and sm2 keys in separate config fields and never cross-assign them.
- Assert the config key decodes to exactly 32 bytes at load time, before any SetPrivateKey call.
- Use `keygen --sm2` (not --curve) when configuring the GMSM cipher scheme.
- Log decoded key lengths (not contents) when initializing ECDH to catch truncation early.
When it happens
Trigger: Calling (*SM2ECDH).SetPrivateKey (directly or via ECDHFromKey) with a byte slice shorter than 32 bytes — e.g. a truncated base64-decoded key, a 31-byte raw scalar, or an empty slice when the key failed to load from config.
Common situations: Configuring the GMSM cipher scheme with a key generated by `keygen --curve` (wrong key type) whose stored text is shorter; missing or truncated value in config.toml's privateKey field; base64 decoding errors handled by ignoring partial output.
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
- size incorrect
- size incorrect
- invalid public key length: got
- invalid signature length: got
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/c566bcb233d55507.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/scheme/gmsm/gmsm.go:30
)
const (
PrivateKeySize = 32
PublicKeySize = 64
)
type SM2ECDH struct {
PrivKey [PrivateKeySize]byte
PubKey [PublicKeySize]byte
prvK *ecdh.PrivateKey
PrivKeyBase64 string
PubKeyBase64 string
BriefName string
}
func (s *SM2ECDH) 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(s.PrivKey[:], prk[:PrivateKeySize])
s.prvK, err = ecdh.P256().NewPrivateKey(prk)
if err != nil {
return err
}
copy(s.PubKey[:], s.prvK.PublicKey().Bytes()[1:1+PublicKeySize])
s.PrivKeyBase64 = base64.StdEncoding.EncodeToString(s.PrivKey[:])
s.PubKeyBase64 = base64.StdEncoding.EncodeToString(s.PubKey[:])
s.BriefName = fmt.Sprintf("%s...%s", s.PubKeyBase64[0:4], s.PubKeyBase64[39:43])
return nil
}
func (s *SM2ECDH) PrivateKey() []byte {
return s.PrivKey[:]
}
View on GitHub (pinned to 6e04ca5ff0)