{"id":1470,"date":"2024-04-18T01:20:03","date_gmt":"2024-04-17T22:20:03","guid":{"rendered":"https:\/\/www.fibacloud.com\/community\/tutorials\/?p=1470"},"modified":"2026-10-04T22:57:46","modified_gmt":"2026-10-04T19:57:46","slug":"csr-code-generation","status":"publish","type":"post","link":"https:\/\/www.fibacloud.com\/community\/tutorials\/en\/csr-code-generation\/","title":{"rendered":"CSR Code Generation: SAN and Private Key Checks"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"1470\" class=\"elementor elementor-1470\" data-elementor-post-type=\"post\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1b7c48c e-con-full e-flex e-con e-parent\" data-id=\"1b7c48c\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-6dee37e elementor-widget elementor-widget-text-editor\" data-id=\"6dee37e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<style>\/*! elementor - v3.21.0 - 08-05-2024 *\/\n.elementor-widget-text-editor.elementor-drop-cap-view-stacked .elementor-drop-cap{background-color:#69727d;color:#fff}.elementor-widget-text-editor.elementor-drop-cap-view-framed .elementor-drop-cap{color:#69727d;border:3px solid;background-color:transparent}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap{margin-top:8px}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap-letter{width:1em;height:1em}.elementor-widget-text-editor .elementor-drop-cap{float:left;text-align:center;line-height:1;font-size:50px}.elementor-widget-text-editor .elementor-drop-cap-letter{display:inline-block}<\/style>\t\t\t\t<p>A Certificate Signing Request (CSR) asks a certificate authority to issue a TLS certificate. It contains the public key, request details and a signature created with the private key. <strong>The private key is not part of the CSR and must not be sent to the certificate authority.<\/strong> Browsers check domain names against the certificate\u2019s Subject Alternative Name (SAN) extension; a Common Name (CN) alone is insufficient.<\/p>\n<h2>Scope and prerequisites<\/h2>\n<p>This guide covers domain CSRs with OpenSSL 3.x and explains how the same information applies to cPanel. Commands target a Linux terminal. Replace <code>example.com<\/code> and <code>www.example.com<\/code> with domains you control. Treat the apex domain, <code>www<\/code> and other subdomains separately: <code>*.example.com<\/code> does not itself cover <code>example.com<\/code>.<\/p>\n<p>Check your certificate provider\u2019s required names, key type and validation method first. DV, OV and EV certificates do not have identical organizational requirements. Supply verified company information when your provider requires it. You also need DNS or web access suitable for domain validation.<\/p>\n<p>Creating a CSR does not change the running web server. For renewals, preserve existing certificate and key files and use a separate directory with restricted access.<\/p>\n<figure class=\"fc-editorial-figure\" data-fc-visual=\"20261004\" aria-labelledby=\"fc-editorial-caption-1470\"><a href=\"https:\/\/www.fibacloud.com\/community\/assets\/editorial-20261004\/fc-csr-en-desktop-20261004.webp\" target=\"_blank\" rel=\"noopener\" aria-label=\"Open the full-size illustration\"><picture><source media=\"(max-width: 600px)\" srcset=\"https:\/\/www.fibacloud.com\/community\/assets\/editorial-20261004\/fc-csr-en-mobile-20261004.webp\" width=\"720\" height=\"1140\"><img loading=\"lazy\" src=\"https:\/\/www.fibacloud.com\/community\/assets\/editorial-20261004\/fc-csr-en-desktop-20261004.webp\" width=\"1440\" height=\"1160\" alt=\"A CSR carries the public key, requested DNS SAN names and a locally created signature. The private key is not shared. Verify the issued certificate\u2019s SAN names and key match before installation.\"  decoding=\"async\"><\/picture><\/a><figcaption id=\"fc-editorial-caption-1470\"><strong>CSR: What goes where?<\/strong> A CSR carries the public key, requested DNS SAN names and a locally created signature. The private key is not shared. Verify the issued certificate\u2019s SAN names and key match before installation.<details><summary>Text description of the illustration<\/summary><ol><li>Keep the private key local; do not send it with the CSR.<\/li><li>Include the public key and required DNS SAN names in the CSR, signed locally.<\/li><li>Submit the CSR; the CA validates the domain according to its policy.<\/li><li>Check the issued certificate\u2019s SAN names and match to the private key.<\/li><\/ol><\/details><\/figcaption><\/figure>\n<h2>Generate a key and CSR with SAN names<\/h2>\n<p>Check the OpenSSL version and create a private working directory:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c72ee2b elementor-widget elementor-widget-text-editor\" data-id=\"c72ee2b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<pre><code class=\"language-bash\">openssl version\ninstall -d -m 700 \"$HOME\/tls-example\"\ncd \"$HOME\/tls-example\"\numask 077<\/code><\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5fbc6e5 elementor-widget elementor-widget-text-editor\" data-id=\"5fbc6e5\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>The following creates an RSA 3072-bit key and requests two DNS names. Stop if these filenames already exist; do not overwrite an existing key.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c7e92bf elementor-widget elementor-widget-text-editor\" data-id=\"c7e92bf\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<pre><code class=\"language-bash\">openssl req -new -newkey rsa:3072 -sha256 -noenc \\\n  -keyout example.com.key \\\n  -out example.com.csr \\\n  -subj \"\/CN=example.com\" \\\n  -addext \"subjectAltName=DNS:example.com,DNS:www.example.com\"\nchmod 600 example.com.key<\/code><\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-268fc7d elementor-widget elementor-widget-text-editor\" data-id=\"268fc7d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p><code>-noenc<\/code> leaves the private key file without passphrase encryption. This can support unattended service startup, but makes file permissions, server access and secure backups essential. If your policy requires an encrypted key, omit <code>-noenc<\/code> and plan how the TLS service will obtain its passphrase. Do not put the passphrase in command arguments or published examples.<\/p>\n<h2>Verify the request before submission<\/h2>\n<p>Check the request signature, requested SAN names and file permissions:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-767d347 elementor-widget elementor-widget-text-editor\" data-id=\"767d347\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<pre><code class=\"language-bash\">openssl req -in example.com.csr -noout -verify -text\nopenssl pkey -in example.com.key -check -noout\nstat -c '%a %n' example.com.key<\/code><\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-028a0c6 elementor-widget elementor-widget-text-editor\" data-id=\"028a0c6\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>The signature check should succeed. <code>X509v3 Subject Alternative Name<\/code> should list only the required DNS names. The key file should have mode <code>600<\/code>, allowing its owner to read and write it. Do not store it in a web root, public repository or support message.<\/p>\n<p>Compare public-key digests to confirm that the CSR and private key belong together without displaying the private key:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-372299e elementor-widget elementor-widget-text-editor\" data-id=\"372299e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<pre><code class=\"language-bash\">openssl req -in example.com.csr -pubkey -noout \\\n  | openssl pkey -pubin -outform DER \\\n  | openssl dgst -sha256\nopenssl pkey -in example.com.key -pubout -outform DER \\\n  | openssl dgst -sha256<\/code><\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-87cb593 elementor-widget elementor-widget-text-editor\" data-id=\"87cb593\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Both digests must match. If they differ, create a new request with the intended key. Similar filenames do not establish a match.<\/p>\n<h2>Using cPanel<\/h2>\n<p>Open <strong>SSL\/TLS \u2192 Certificate Signing Requests (CSR)<\/strong> in your account. Enter the required domains and the information requested by the provider. The interface varies with panel version and account permissions. If it does not expose a SAN field, do not assume that CN covers every name: follow the provider\u2019s multi-domain request instructions or use the OpenSSL procedure above.<\/p>\n<p>A panel-generated key differs from a key generated in your terminal. Do not combine the CSR from one method with the private key from the other. Installing a terminal-generated certificate in cPanel also requires securely importing its matching private key into the same account. Do not reuse another customer\u2019s or application\u2019s key.<\/p>\n<h2>Submit the request and verify the issued certificate<\/h2>\n<p>Submit only the CSR to the provider. Complete domain validation through DNS, HTTP or another method the provider permits. Issuance does not mean that every requested field was accepted unchanged; inspect the returned certificate.<\/p>\n<p>Assuming you saved the issued PEM leaf certificate as <code>server.crt<\/code> in the working directory:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ab76c29 elementor-widget elementor-widget-text-editor\" data-id=\"ab76c29\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<pre><code class=\"language-bash\">openssl x509 -in server.crt -noout -issuer -dates -ext subjectAltName\nopenssl x509 -in server.crt -noout -checkhost example.com\nopenssl x509 -in server.crt -noout -checkhost www.example.com\nopenssl x509 -in server.crt -pubkey -noout \\\n  | openssl pkey -pubin -outform DER \\\n  | openssl dgst -sha256<\/code><\/pre>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3f76862 elementor-widget elementor-widget-text-editor\" data-id=\"3f76862\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>The last digest must match the private key\u2019s public-key digest. Also verify the certificate chain, validity period and files configured in your web server. <code>-checkhost<\/code> checks name matching; it does not establish chain trust or prove that the live site serves this certificate. After installation, test the actual HTTPS endpoint with a browser and TLS client.<\/p>\n<h2>Troubleshooting and rollback<\/h2>\n<ul>\n<li><strong>Missing or incorrect SAN:<\/strong> Create a request with the intended DNS names and ask the provider to reissue the certificate. Changing only CN is insufficient.<\/li>\n<li><strong>Key mismatch:<\/strong> Identify which request and key produced the certificate. Do not change the live service until you have the matching pair.<\/li>\n<li><strong>Lost private key:<\/strong> A CSR or certificate cannot reconstruct it. Create a new key and request, then obtain a replacement certificate.<\/li>\n<li><strong>Exposed private key:<\/strong> Do not roll back to the compromised key. Generate a new key, replace the certificate and follow the provider\u2019s revocation procedure.<\/li>\n<li><strong>Service fails after installation:<\/strong> If the old key remains secure and its certificate is valid, restore the previous verified configuration. Run the server\u2019s configuration test before restarting production.<\/li>\n<\/ul>\n<h2>Sources<\/h2>\n<ul>\n<li><a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc2986.html\" rel=\"nofollow noopener\" target=\"_blank\">RFC 2986 \u2014 CSR content and signature structure<\/a><\/li>\n<li><a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc9525.html\" rel=\"nofollow noopener\" target=\"_blank\">RFC 9525 \u2014 TLS service identity and SAN verification<\/a><\/li>\n<li><a href=\"https:\/\/docs.openssl.org\/3.5\/man1\/openssl-req\/\" rel=\"nofollow noopener\" target=\"_blank\">OpenSSL 3.5 \u2014 req: request generation, SAN extensions and verification<\/a><\/li>\n<li>\n<p><a href=\"https:\/\/docs.openssl.org\/3.5\/man1\/openssl-x509\/\" rel=\"nofollow noopener\" target=\"_blank\">OpenSSL 3.5 \u2014 x509: certificate and hostname checks<\/a><\/p>\n<\/li>\n<li><a href=\"https:\/\/docs.cpanel.net\/cpanel\/security\/ssl-tls\/\" rel=\"nofollow noopener\" target=\"_blank\">cPanel \u2014 SSL\/TLS, CSR and private-key management<\/a><\/li>\n<\/ul>\n<p class=\"fc-article-review-date\">Technical content and sources reviewed on October 4, 2026. Recheck the relevant official documentation when a version or provider changes.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Generate a CSR with SAN names using OpenSSL or cPanel. Protect the private key and verify certificate names and the public-key match.<\/p>\n","protected":false},"author":1,"featured_media":2517,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[78,110],"class_list":["post-1470","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials-en","tag-security","tag-web"],"lang":"en","translations":{"en":1470,"tr":1370},"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/posts\/1470","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/comments?post=1470"}],"version-history":[{"count":17,"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/posts\/1470\/revisions"}],"predecessor-version":[{"id":1487,"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/posts\/1470\/revisions\/1487"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/media\/2517"}],"wp:attachment":[{"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/media?parent=1470"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/categories?post=1470"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fibacloud.com\/community\/tutorials\/wp-json\/wp\/v2\/tags?post=1470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}