{"record":{"id":"29b9b71c78da0611","repo":"slackhq/nebula","slug":"key-was-not-d-bytes-is-invalid-s-private-key","errorCode":null,"errorMessage":"key was not %d bytes, is invalid %s private key","messagePattern":"key was not (.+?) bytes, is invalid (.+?) private key","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/pem.go","lineNumber":247,"sourceCode":"func UnmarshalPrivateKeyFromPEM(b []byte) ([]byte, []byte, Curve, error) {\n\tk, r := pem.Decode(b)\n\tif k == nil {\n\t\treturn nil, r, 0, fmt.Errorf(\"input did not contain a valid PEM encoded block\")\n\t}\n\tvar expectedLen int\n\tvar curve Curve\n\tswitch k.Type {\n\tcase X25519PrivateKeyBanner:\n\t\texpectedLen = 32\n\t\tcurve = Curve_CURVE25519\n\tcase P256PrivateKeyBanner:\n\t\texpectedLen = 32\n\t\tcurve = Curve_P256\n\tdefault:\n\t\treturn nil, r, 0, fmt.Errorf(\"bytes did not contain a proper private key banner\")\n\t}\n\tif len(k.Bytes) != expectedLen {\n\t\treturn nil, r, 0, fmt.Errorf(\"key was not %d bytes, is invalid %s private key\", expectedLen, curve)\n\t}\n\treturn k.Bytes, r, curve, nil\n}\n\nfunc UnmarshalSigningPrivateKeyFromPEM(b []byte) ([]byte, []byte, Curve, error) {\n\tk, r := pem.Decode(b)\n\tif k == nil {\n\t\treturn nil, r, 0, fmt.Errorf(\"input did not contain a valid PEM encoded block\")\n\t}\n\tvar curve Curve\n\tswitch k.Type {\n\tcase EncryptedEd25519PrivateKeyBanner:\n\t\treturn nil, nil, Curve_CURVE25519, ErrPrivateKeyEncrypted\n\tcase EncryptedECDSAP256PrivateKeyBanner:\n\t\treturn nil, nil, Curve_P256, ErrPrivateKeyEncrypted\n\tcase Ed25519PrivateKeyBanner:\n\t\tcurve = Curve_CURVE25519\n\t\tif len(k.Bytes) != ed25519.PrivateKeySize {","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/pem.go#L229-L265","documentation":"The PEM block had a valid nebula private key banner, but the decoded key bytes are not exactly 32 bytes, which both supported curves (X25519 and P256) require. The key body was truncated, extended, or otherwise corrupted after the banner was written. The library rejects it rather than deriving a broken key.","triggerScenarios":"Call UnmarshalPrivateKeyFromPEM with a block whose Type is X25519PrivateKeyBanner or P256PrivateKeyBanner but whose base64 body decodes to len(k.Bytes) != 32 — e.g. a half-pasted key, a key with extra bytes appended, or raw-key-size mismatch from manual encoding.","commonSituations":"Copy/paste truncation in editors or chat tools, secrets managers that mangled base64, hand-crafted PEM blocks from raw key material with wrong byte length, or converting from another tool's format incorrectly.","solutions":["Regenerate the host private key with nebula-cert keygen and redeploy it","Decode the PEM body and assert it is exactly 32 bytes before calling the API","Re-transfer the key file intact (compare checksums); avoid manual copy/paste of key material"],"exampleFix":"// before\nblock.Bytes = key[:20] // truncated\n// after\nif len(key) != 32 { return errors.New(\"bad key\") }\nblock.Bytes = key","handlingStrategy":"validation","validationCode":"blk, _ := pem.Decode(data)\nif blk != nil && len(blk.Bytes) != 32 {\n    return fmt.Errorf(\"host private key must decode to 32 bytes, got %d; regenerate the key\", len(blk.Bytes))\n}","typeGuard":"func hasValidHostKeyLength(b []byte) bool {\n    blk, _ := pem.Decode(b)\n    return blk != nil && len(blk.Bytes) == 32\n}","tryCatchPattern":"key, _, _, err := nebula.UnmarshalPrivateKeyFromPEM(raw)\nif err != nil {\n    return fmt.Errorf(\"host private key body is the wrong size; regenerate with nebula-cert keygen: %w\", err)\n}","preventionTips":["Verify checksums when distributing key files","Avoid copy/paste of key material through editors or chat tools","Treat any hand-modified key file as suspect and regenerate"],"tags":["pem","private-key","key-length","corruption"],"backgroundTag":"invalid-pem-key-length","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}