{"record":{"id":"a4170a3a61fc0ad1","repo":"TechnitiumSoftware/DnsServer","slug":"dns-server-tls-certificate-file-must-be-pkcs-12-f","errorCode":null,"errorMessage":"DNS Server TLS certificate file must be PKCS #12 formatted with .pfx or .p12 extension: {tlsCertificatePath}","messagePattern":"DNS Server TLS certificate file must be PKCS #12 formatted with \\.pfx or \\.p12 extension: (.+?)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/DnsServer.cs","lineNumber":1573,"sourceCode":"                _tlsCertificateUpdateTimer = null;\n            }\n        }\n\n        private void LoadDnsTlsCertificate(string tlsCertificatePath, string tlsCertificatePassword)\n        {\n            FileInfo fileInfo = new FileInfo(tlsCertificatePath);\n\n            if (!fileInfo.Exists)\n                throw new ArgumentException(\"DNS Server TLS certificate file does not exists: \" + tlsCertificatePath);\n\n            switch (Path.GetExtension(tlsCertificatePath).ToLowerInvariant())\n            {\n                case \".pfx\":\n                case \".p12\":\n                    break;\n\n                default:\n                    throw new ArgumentException(\"DNS Server TLS certificate file must be PKCS #12 formatted with .pfx or .p12 extension: \" + tlsCertificatePath);\n            }\n\n            X509Certificate2Collection certificateCollection = X509CertificateLoader.LoadPkcs12CollectionFromFile(tlsCertificatePath, tlsCertificatePassword, X509KeyStorageFlags.PersistKeySet);\n            X509Certificate2 serverCertificate = null;\n\n            foreach (X509Certificate2 certificate in certificateCollection)\n            {\n                if (certificate.HasPrivateKey)\n                {\n                    serverCertificate = certificate;\n                    break;\n                }\n            }\n\n            if (serverCertificate is null)\n                throw new ArgumentException(\"DNS Server TLS certificate file must contain a certificate with private key.\");\n\n            SslStreamCertificateContext certificateContext = SslStreamCertificateContext.Create(serverCertificate, certificateCollection, false);","sourceCodeStart":1555,"sourceCodeEnd":1591,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/DnsServer.cs#L1555-L1591","documentation":"Thrown by LoadDnsTlsCertificate when the file extension is neither .pfx nor .p12. The server only loads PKCS #12 bundles via X509CertificateLoader.LoadPkcs12CollectionFromFile; PEM/DER/CER are not accepted for DoT/DoH/DoQ.","triggerScenarios":"Setting a TLS cert path whose extension is .pem, .crt, .cer, .key, or anything other than .pfx/.p12. The extension switch fires before any parse attempt.","commonSituations":"Admin generates a PEM cert chain (common with Let's Encrypt / certbot --pem) and points the server at it; copying a CA's .crt instead of the bundled .pfx; case variations are handled (ToLowerInvariant) but a missing or wrong extension is not.","solutions":["Convert the PEM cert + key into a PKCS #12 bundle: openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.pfx -password pass:secret.","Rename only if the file is already PKCS #12 but mislabeled; otherwise convert.","Re-export from your CA tooling choosing the .pfx option.","For Let's Encrypt, use certbot with --deploy-hook that builds the .pfx on each renewal."],"exampleFix":"# before: server.pem passed to SetDnsTlsCertificate\n\n# after\nopenssl pkcs12 -export -in fullchain.pem -inkey privkey.pem \\\n  -out dns.pfx -password pass:secret\n# then server.SetDnsTlsCertificate(\"dns.pfx\", \"secret\")","handlingStrategy":"validation","validationCode":"static readonly HashSet<string> Pkcs12 = new(StringComparer.OrdinalIgnoreCase) { \".pfx\", \".p12\" };\nbool IsPkcs12Path(string path) => Pkcs12.Contains(Path.GetExtension(path));","typeGuard":"static bool IsValidTlsCertExtension(string path)\n{\n    var ext = Path.GetExtension(path).ToLowerInvariant();\n    return ext is \".pfx\" or \".p12\";\n}","tryCatchPattern":"try { server.SetDnsTlsCertificate(path, pass, throwException: true); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"PKCS #12\")) { log.Error(\"Convert the cert to a .pfx/.p12 bundle\"); }","preventionTips":["Always convert PEM to PKCS #12 before configuring.","Standardize on .pfx in your provisioning scripts.","Reject non-pfx uploads in the UI before submission."],"tags":["tls","certificate","pkcs12","format"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}