{"record":{"id":"f70d49c2773936a9","repo":"slackhq/nebula","slug":"key-was-not-d-bytes-is-invalid-ed25519-private-k-f70d49","errorCode":null,"errorMessage":"key was not %d bytes, is invalid Ed25519 private key","messagePattern":"key was not (.+?) bytes, is invalid Ed25519 private key","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/pem.go","lineNumber":266,"sourceCode":"\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 {\n\t\t\treturn nil, r, 0, fmt.Errorf(\"key was not %d bytes, is invalid Ed25519 private key\", ed25519.PrivateKeySize)\n\t\t}\n\tcase ECDSAP256PrivateKeyBanner:\n\t\tcurve = Curve_P256\n\t\tif len(k.Bytes) != 32 {\n\t\t\treturn nil, r, 0, fmt.Errorf(\"key was not 32 bytes, is invalid ECDSA P256 private key\")\n\t\t}\n\tdefault:\n\t\treturn nil, r, 0, fmt.Errorf(\"bytes did not contain a proper Ed25519/ECDSA private key banner\")\n\t}\n\treturn k.Bytes, r, curve, nil\n}\n","sourceCodeStart":248,"sourceCodeEnd":278,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/pem.go#L248-L278","documentation":"The PEM block was recognized as an Ed25519 signing private key (Ed25519PrivateKeyBanner), but the decoded bytes are not ed25519.PrivateKeySize (64) bytes long. Ed25519 private keys are 64 bytes (seed + public half); anything else means the key body is damaged or was encoded incorrectly.","triggerScenarios":"Call UnmarshalSigningPrivateKeyFromPEM with a block of type Ed25519PrivateKeyBanner whose k.Bytes length != 64, e.g. a 32-byte seed pasted under the full-key banner or a truncated file.","commonSituations":"Storing only the 32-byte seed but labeling it as the full private key, truncation during copy/paste or through line-wrapping tools, or regenerating the CA and mixing old banner with new (short) material.","solutions":["Regenerate the CA signing key with nebula-cert ca so a full 64-byte Ed25519 private key is emitted","Decode the PEM body and verify it is exactly ed25519.PrivateKeySize (64) bytes before calling","If you only have the 32-byte seed, expand it with ed25519.NewKeyFromSeed before PEM-encoding"],"exampleFix":"// before\npem.Encode(file, &pem.Block{Type: banner, Bytes: seed}) // 32 bytes\n// after\nfull := ed25519.NewKeyFromSeed(seed)\npem.Encode(file, &pem.Block{Type: banner, Bytes: full}) // 64 bytes","handlingStrategy":"validation","validationCode":"blk, _ := pem.Decode(data)\nif blk != nil && blk.Type == \"NEBULA ED25519 SIGNING PRIVATE KEY\" && len(blk.Bytes) != ed25519.PrivateKeySize {\n    return fmt.Errorf(\"Ed25519 signing key must be 64 bytes, got %d\", len(blk.Bytes))\n}","typeGuard":"func isValidEd25519SigningKey(b []byte) bool {\n    blk, _ := pem.Decode(b)\n    return blk != nil && blk.Type == \"NEBULA ED25519 SIGNING PRIVATE KEY\" && len(blk.Bytes) == ed25519.PrivateKeySize\n}","tryCatchPattern":"key, _, _, err := nebula.UnmarshalSigningPrivateKeyFromPEM(raw)\nif err != nil {\n    return fmt.Errorf(\"Ed25519 signing key is malformed (expected 64 bytes): %w\", err)\n}","preventionTips":["Never store just the 32-byte seed under a full-private-key banner","If you only have a seed, expand it with ed25519.NewKeyFromSeed before encoding","Regenerate the CA rather than reconstructing its key by hand"],"tags":["pem","ed25519","signing-key","key-length"],"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"}