{"record":{"id":"ca0797fb69fc0995","repo":"OpenNHP/opennhp","slug":"private-key-too-short-got-d-bytes-need-d","errorCode":null,"errorMessage":"private key too short: got %d bytes, need %d","messagePattern":"private key too short: got (.+?) bytes, need (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nhp/core/scheme/curve/curve.go","lineNumber":26,"sourceCode":"\t\"golang.org/x/crypto/curve25519\"\n)\n\nconst (\n\tPrivateKeySize = 32\n\tPublicKeySize  = 32\n)\n\ntype Curve25519ECDH struct {\n\tPrivKey       [PrivateKeySize]byte\n\tPubKey        [PublicKeySize]byte\n\tPrivKeyBase64 string\n\tPubKeyBase64  string\n\tBriefName     string\n}\n\nfunc (c *Curve25519ECDH) SetPrivateKey(prk []byte) (err error) {\n\tif len(prk) < PrivateKeySize {\n\t\treturn fmt.Errorf(\"private key too short: got %d bytes, need %d\", len(prk), PrivateKeySize)\n\t}\n\tcopy(c.PrivKey[:], prk[:PrivateKeySize])\n\tpbk, err := curve25519.X25519(c.PrivKey[:], curve25519.Basepoint)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcopy(c.PubKey[:], pbk)\n\tc.PrivKeyBase64 = base64.StdEncoding.EncodeToString(c.PrivKey[:])\n\tc.PubKeyBase64 = base64.StdEncoding.EncodeToString(c.PubKey[:])\n\tc.BriefName = fmt.Sprintf(\"%s...%s\", c.PubKeyBase64[0:4], c.PubKeyBase64[39:43])\n\n\treturn nil\n}\n\nfunc (c *Curve25519ECDH) PrivateKey() []byte {\n\treturn c.PrivKey[:]\n}\n","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/nhp/core/scheme/curve/curve.go#L8-L44","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nprk := keyBytes[:16] // accidentally truncated\necdhe := curve.NewECDH()\nerr := ecdhe.SetPrivateKey(prk)\n// after\nif len(keyBytes) < curve.PrivateKeySize {\n\treturn fmt.Errorf(\"key source provided %d bytes\", len(keyBytes))\n}\nerr := ecdhe.SetPrivateKey(keyBytes[:curve.PrivateKeySize])","handlingStrategy":"validation","validationCode":"// Go\nfunc validCurvePrivKey(b []byte) bool { return len(b) >= curve.PrivateKeySize } // PrivateKeySize == 32\nif !validCurvePrivKey(keyBytes) {\n\treturn fmt.Errorf(\"curve private key must be 32 bytes, got %d\", len(keyBytes))\n}","typeGuard":null,"tryCatchPattern":"if err := ecdhe.SetPrivateKey(prk); err != nil {\n\tif strings.Contains(err.Error(), \"private key too short\") {\n\t\t// recover: re-load or regenerate key pair\n\t}\n\treturn err\n}","preventionTips":["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."],"tags":["crypto","ecdh","curve25519","key-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}