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

  1. Verify the key input is exactly 32 bytes (44-char standard base64) before calling SetPrivateKey.
  2. Regenerate SM2 keys with `keygen --sm2` and use the full private key string from the output.
  3. Confirm the key loaded from config is non-empty and not truncated (log its decoded length).
  4. 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

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


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)