OpenNHP/opennhp · error
size incorrect
Error message
size incorrect
What it means
Base64DecodeSM2ECDHPrivateKey decodes a base64 string and requires the result to be exactly 32 bytes — the size of a raw P-256/SM2 private scalar for ecdh.P256().NewPrivateKey. Any other length is rejected with the terse 'size incorrect' error, preventing invalid scalars from reaching the crypto library.
Solutions
- Re-encode the 32-byte private scalar with base64.StdEncoding.EncodeToString and store that exact string.
- Strip PEM headers/whitespace and ensure the payload is pure standard base64 (not URL-safe, no hex).
- Check the decoded length at the call site: len(base64.StdEncoding.DecodeString(s)) == 32.
- Regenerate the key pair with `keygen --sm2 --json` and use the emitted private key field directly.
Example fix
// before
priv, err := gmsm.Base64DecodeSM2ECDHPrivateKey(hexKey) // hex string, wrong format
// after
b, err := hex.DecodeString(hexKey)
if err != nil {
return err
}
priv, err := gmsm.Base64DecodeSM2ECDHPrivateKey(base64.StdEncoding.EncodeToString(b)) Defensive patterns
Strategy: validation
Validate before calling
// Go
func isSM2ECDHPrivKeyStr(s string) bool {
b, err := base64.StdEncoding.DecodeString(s)
return err == nil && len(b) == 32
}
if !isSM2ECDHPrivKeyStr(privStr) {
return errors.New("private key must be base64 of 32 raw bytes")
} Try / catch
priv, err := gmsm.Base64DecodeSM2ECDHPrivateKey(privStr)
if err != nil {
if err.Error() == "size incorrect" {
return fmt.Errorf("SM2 private key has wrong encoding (expected base64 of 32 bytes): %w", err)
}
return err
} Prevention
- Store keys as standard (not URL-safe) base64 with no PEM armor or whitespace.
- Reject hex-encoded or DER-encoded key strings at config load time.
- Round-trip check: encode-then-decode a stored key in tests to catch format drift.
- Regenerate keys with the daemon's keygen so the emitted format always matches the parser.
When it happens
Trigger: Calling Base64DecodeSM2ECDSAPrivateKey/... specifically Base64DecodeSM2ECDHPrivateKey with a string whose base64 decoding is not exactly 32 bytes: an empty string, a DER/PEM-encoded key, a base64 string with padding mistakes, or a hex-encoded key pasted where base64 is expected.
Common situations: Storing a key as hex ('a3f0...') instead of base64; including a '-----BEGIN...' header; trimming characters when copying the key from a terminal; an older serialized key format from a previous NHP version.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- size incorrect
- private key parse error
- invalid CookieSigningKeyBase64
- private key too short: got
- invalid public key length: got
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/14b891e6844a0334.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/scheme/gmsm/gmsm.go:134
pKey, err := ecdh.P256().GenerateKey(rand.Reader)
if err != nil {
return "", ""
}
copy(privKey[:32], pKey.Bytes()[:32]) // Private Key 32 bytes
copy(pubKey[:64], pKey.PublicKey().Bytes()[1:65]) // Public Key 64 bytes
return base64.StdEncoding.EncodeToString(pubKey[:]),
base64.StdEncoding.EncodeToString(privKey[:])
}
func Base64DecodeSM2ECDHPrivateKey(privStr string) (*ecdh.PrivateKey, error) {
privKeyBytes, err := base64.StdEncoding.DecodeString(privStr)
if err != nil {
return nil, err
}
if len(privKeyBytes) != 32 {
return nil, fmt.Errorf("size incorrect")
}
privKey, err := ecdh.P256().NewPrivateKey(privKeyBytes)
if err != nil {
return nil, err
}
return privKey, nil
}
func Base64DecodeSM2ECDHPublicKey(pubStr string) (*ecdh.PublicKey, error) {
pubKeyBytes, err := base64.StdEncoding.DecodeString(pubStr)
if err != nil {
return nil, err
}
if len(pubKeyBytes) != 64 {
return nil, fmt.Errorf("size incorrect")
}
buf := make([]byte, 65)
buf[0] = 4 // public key first byte means uncompressedView on GitHub (pinned to 6e04ca5ff0)