{"record":{"id":"10d7344eb6028d00","repo":"slackhq/nebula","slug":"bytes-did-not-contain-a-proper-private-key-banner","errorCode":null,"errorMessage":"bytes did not contain a proper private key banner","messagePattern":"bytes did not contain a proper private key banner","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/pem.go","lineNumber":244,"sourceCode":"\n// UnmarshalPrivateKeyFromPEM will try to unmarshal the first pem block in a byte array, returning any non\n// consumed data or an error on failure\nfunc 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","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/pem.go#L226-L262","documentation":"pem.Decode succeeded but the block's Type string does not match any recognized private key banner ('NEBULA X25519 PRIVATE KEY' or 'NEBULA ECDSA P256 PRIVATE KEY'). The input is valid PEM, but it is not a nebula private key of the supported kind — often it is a public key, a signing key, or a standard OpenSSL PEM type.","triggerScenarios":"Call UnmarshalPrivateKeyFromPEM with a PEM block whose k.Type is not X25519PrivateKeyBanner or P256PrivateKeyBanner, e.g. passing a signing (Ed25519/ECDSA) key PEM, a public key PEM, or a 'RSA PRIVATE KEY' / 'PRIVATE KEY' standard block.","commonSituations":"Swapping the tunl.private_key and tunl.signing_key_path config entries by mistake, pointing at the certificate/public key file instead of the key file, or using keys generated by openssl in standard PEM formats the library does not accept.","solutions":["Use the correct file: the entry for tunl.private_key must contain an 'X25519 PRIVATE KEY' or 'ECDSA P256 PRIVATE KEY' nebula banner","Regenerate the key with nebula-cert keygen so the banner matches what UnmarshalPrivateKeyFromPEM expects","Check that you are not passing a signing private key (that belongs in signing_key_path and is parsed by UnmarshalSigningPrivateKeyFromPEM)"],"exampleFix":"// before (config)\nfirewall: ...\ntunl: { private_key_path: ./signing.key } // wrong key\n// after\ntunl: { private_key_path: ./host.key } // X25519/ECDSA P256 private key banner","handlingStrategy":"validation","validationCode":"blk, _ := pem.Decode(data)\nif blk != nil && blk.Type != \"NEBULA X25519 PRIVATE KEY\" && blk.Type != \"NEBULA ECDSA P256 PRIVATE KEY\" {\n    return fmt.Errorf(\"expected a nebula host private key, got PEM type %q\", blk.Type)\n}","typeGuard":"func isHostPrivateKey(b []byte) bool {\n    blk, _ := pem.Decode(b)\n    return blk != nil && (blk.Type == \"NEBULA X25519 PRIVATE KEY\" || blk.Type == \"NEBULA ECDSA P256 PRIVATE KEY\")\n}","tryCatchPattern":"key, _, _, err := nebula.UnmarshalPrivateKeyFromPEM(raw)\nif err != nil {\n    return fmt.Errorf(\"key file has the wrong banner for a host private key: %w\", err)\n}","preventionTips":["Keep host keys and signing keys in clearly named separate files","Cross-check nebula config key_path vs signing_key_path entries before deploying","Inspect the BEGIN line of each key file once at startup"],"tags":["pem","private-key","key-banner","wrong-key-type"],"backgroundTag":"unrecognized-pem-key-type","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"}