{"record":{"id":"98095ba1c33616d7","repo":"AdguardTeam/AdGuardHome","slug":"parsing-private-key-w","errorCode":null,"errorMessage":"parsing private key: %w","messagePattern":"parsing private key: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/aghtls/defaultmanager.go","lineNumber":797,"sourceCode":"\t// Go through all pem blocks, but take first valid pem block and drop the\n\t// rest.\n\tfor decoded, pemblock := pem.Decode([]byte(pkey)); decoded != nil; {\n\t\tif decoded.Type == \"PRIVATE KEY\" || strings.HasSuffix(decoded.Type, \" PRIVATE KEY\") {\n\t\t\tkey = decoded\n\n\t\t\tbreak\n\t\t}\n\n\t\tdecoded, pemblock = pem.Decode(pemblock)\n\t}\n\n\tif key == nil {\n\t\treturn \"\", errors.Error(\"no valid keys were found\")\n\t}\n\n\t_, keyType, err = parsePrivateKey(key.Bytes)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"parsing private key: %w\", err)\n\t}\n\n\tif keyType == keyTypeED25519 {\n\t\treturn \"\", errors.Error(\n\t\t\t\"ED25519 keys are not supported by browsers; \" +\n\t\t\t\t\"did you mean to use X25519 for key exchange?\",\n\t\t)\n\t}\n\n\treturn keyType, nil\n}\n\n// validateCertificates processes certificate data and its private key.  status\n// must not be nil, since it's used to accumulate the validation results.\n// logger and tlsManager must not be nil.  Other parameters are optional.\nfunc validateCertificates(\n\tctx context.Context,\n\tlogger *slog.Logger,","sourceCodeStart":779,"sourceCodeEnd":815,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/aghtls/defaultmanager.go#L779-L815","documentation":"The PEM private key block could not be parsed into a known key format by parsePrivateKey. The wrapped error indicates the key bytes are corrupt, truncated, encrypted in an unsupported way, or not a valid PKCS#1/PKCS#8/EC key.","triggerScenarios":"validatePKey runs during LoadTLSConfig; triggers when PrivateKeyData contains a PEM block whose DER payload fails parsing: wrong PEM type, encrypted (passphrase-protected) key, or corrupt base64/DER.","commonSituations":"Using a passphrase-protected key (Go's tls package does not decrypt them); pasting a public key instead of the private key; line-wrapping damage from copying the key through email/docs.","solutions":["Remove the passphrase: openssl rsa -in key.enc -out key.pem (or ec -in ... )","Confirm the file has a PRIVATE KEY header, not PUBLIC KEY","Re-copy the key preserving exact line breaks, or transfer via scp/base64 -d","Verify offline: openssl pkey -in key.pem -noout"],"exampleFix":"# before\nopenssl genrsa -aes256 ... # encrypted key\n# after\nopenssl rsa -in encrypted.key -out plain.key","handlingStrategy":"validation","validationCode":"block, _ := pem.Decode(keyPEM)\nif block == nil || !strings.Contains(block.Type, \"PRIVATE KEY\") {\n    return fmt.Errorf(\"not a private key PEM\")\n}\nif _, _, err := parsePrivateKey(block.Bytes); err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := mgr.LoadTLSConfig(ctx, conf); err != nil {\n    if strings.Contains(err.Error(), \"parsing private key\") { /* decrypt or replace the key */ }\n}","preventionTips":["Use unencrypted (no passphrase) keys for server TLS in Go","Validate keys with openssl pkey before deployment","Avoid Ed25519 keys for browser-facing TLS (explicitly rejected upstream)"],"tags":["tls","crypto","private-key","parsing"],"backgroundTag":"private-key-parse-error","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}