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

  1. Re-encode the 32-byte private scalar with base64.StdEncoding.EncodeToString and store that exact string.
  2. Strip PEM headers/whitespace and ensure the payload is pure standard base64 (not URL-safe, no hex).
  3. Check the decoded length at the call site: len(base64.StdEncoding.DecodeString(s)) == 32.
  4. 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

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


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 uncompressed

View on GitHub (pinned to 6e04ca5ff0)