<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>openssl &amp;mdash; LinuxPizza</title>
    <link>https://blogs.linux.pizza/tag:openssl</link>
    <description>Personal notes and occasional posts - 100% human, 0% AI generated</description>
    <pubDate>Tue, 21 Apr 2026 11:21:21 +0000</pubDate>
    <item>
      <title>Secure your API with Client-certificate authenatication in NGINX</title>
      <link>https://blogs.linux.pizza/secure-your-api-with-client-certificate-authenatication-in-nginx</link>
      <description>&lt;![CDATA[After a few hours trying to make it work with my current CA, where the Root is stored offline, AIA, OCSP, CRL and all that stuff is done by the book - I gave up.&#xA;Somehow, the Open Source variant of Nginx does not really like my OCSP setup, no idea why and I have no idea how to troubleshoot that.&#xA;&#xA;Solution? KISS-principle!&#xA;&#xA;I&#39;ll write this down, quick and dirty. But hopefully it helps someone.&#xA;&#xA;Lets start with create the private key for the CA that we will create:&#xA;&#xA;openssl genpkey -algorithm RSA -out CAROOT.key -aes256&#xA;With this command, we have created a private key with AES256. You will be prompted to give a password - write that down.&#xA;And the following command will create a certificate from the private key, valid for 10 years.&#xA;&#xA;openssl req -x509 -new -nodes -key CAROOT.key -sha256 -days 3650 -out CAROOT.crt&#xA;Fill in the information that the above command wants of you, like country-code, and so on.&#xA;After that, your CA is done. The crude, ugly and honestly boring CA. But it&#39;ll work for this usecase.&#xA;&#xA;Let&#39;s create the client-certificate!&#xA;&#xA;First, will start by creating the private.key, and the .csr:&#xA;openssl genpkey -algorithm RSA -out client-cert.key&#xA;openssl req -new -key client.key -out client-cert.csr&#xA;And again, fill out the information wanted by openssl that will populate the .csr. Make it looks pretty.&#xA;Ideally, the commands shall be run on the client only, so the private-key never leaves the client. The .csr is what the CA will need to sign and create a valid certificate.&#xA;&#xA;Bring the .csr to the CA, and sign it:&#xA;&#xA;openssl x509 -req -in client-cert.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client-cert.crt -days 365 -sha256&#xA;This will give you a signed certificate for your client named &#34;client-cert.crt&#34; - you may bring that to the client-machine and install it.&#xA;&#xA;Firefox wants a .pfx:&#xA;&#xA;In order to import the certificate into Firefox, you&#39;ll need to convert it to p12/pfx format:&#xA;openssl pkcs12 -export -out client-cert.pfx -inkey client-cert.key -in client-cert.crt -certfile CAROOT.crt&#xA;Please note, that you&#39;ll need the CAROOT.crt file too that you created.&#xA;&#xA;Configure NGINX to do client-certificate authentication&#xA;&#xA;Navigate to the virtualhost you want to enable client-certificate authentication on, and add the following:&#xA;&#xA;    sslclientcertificate /etc/ssl/private/CAROOT.crt;&#xA;    sslverifyclient on;&#xA;    sslverifydepth 2;&#xA;Please note, that you have to place the CA_ROOT.crt file in &#xA;Restart NGINX and try to visit the site. You&#39;ll probably be asked for permission to use client-certificate authentication.&#xA;&#xA;#linux #openssl #nginx #pki&#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>After a few hours trying to make it work with my current CA, where the Root is stored offline, AIA, OCSP, CRL and all that stuff is done by the book – I gave up.
Somehow, the Open Source variant of Nginx does not really like my OCSP setup, no idea why and I have no idea how to troubleshoot that.</p>

<h4 id="solution-kiss-principle" id="solution-kiss-principle">Solution? KISS-principle!</h4>

<p>I&#39;ll write this down, quick and dirty. But hopefully it helps someone.</p>

<p>Lets start with create the private key for the CA that we will create:</p>

<pre><code>openssl genpkey -algorithm RSA -out CA_ROOT.key -aes256
</code></pre>

<p>With this command, we have created a private key with AES256. You will be prompted to give a password – write that down.
And the following command will create a certificate from the private key, valid for 10 years.</p>

<pre><code>openssl req -x509 -new -nodes -key CA_ROOT.key -sha256 -days 3650 -out CA_ROOT.crt
</code></pre>

<p>Fill in the information that the above command wants of you, like country-code, and so on.
After that, your CA is done. The crude, ugly and honestly boring CA. But it&#39;ll work for this usecase.</p>

<h4 id="let-s-create-the-client-certificate" id="let-s-create-the-client-certificate">Let&#39;s create the client-certificate!</h4>

<p>First, will start by creating the private.key, and the .csr:</p>

<pre><code>openssl genpkey -algorithm RSA -out client-cert.key
openssl req -new -key client.key -out client-cert.csr
</code></pre>

<p>And again, fill out the information wanted by openssl that will populate the .csr. Make it looks pretty.
Ideally, the commands shall be run on the client only, so the private-key never leaves the client. The .csr is what the CA will need to sign and create a valid certificate.</p>

<p>Bring the .csr to the CA, and sign it:</p>

<pre><code>openssl x509 -req -in client-cert.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client-cert.crt -days 365 -sha256
</code></pre>

<p>This will give you a signed certificate for your client named “client-cert.crt” – you may bring that to the client-machine and install it.</p>

<h4 id="firefox-wants-a-pfx" id="firefox-wants-a-pfx">Firefox wants a .pfx:</h4>

<p>In order to import the certificate into Firefox, you&#39;ll need to convert it to p12/pfx format:</p>

<pre><code>openssl pkcs12 -export -out client-cert.pfx -inkey client-cert.key -in client-cert.crt -certfile CA_ROOT.crt
</code></pre>

<p>Please note, that you&#39;ll need the CA_ROOT.crt file too that you created.</p>

<h4 id="configure-nginx-to-do-client-certificate-authentication" id="configure-nginx-to-do-client-certificate-authentication">Configure NGINX to do client-certificate authentication</h4>

<p>Navigate to the virtualhost you want to enable client-certificate authentication on, and add the following:</p>

<pre><code>    ssl_client_certificate /etc/ssl/private/CA_ROOT.crt;
    ssl_verify_client on;
    ssl_verify_depth 2;
</code></pre>

<p>Please note, that you have to place the CA_ROOT.crt file in <code>/etc/ssl/private/</code></p>

<p>Restart NGINX and try to visit the site. You&#39;ll probably be asked for permission to use client-certificate authentication.</p>

<p><a href="https://blogs.linux.pizza/tag:linux" class="hashtag"><span>#</span><span class="p-category">linux</span></a> <a href="https://blogs.linux.pizza/tag:openssl" class="hashtag"><span>#</span><span class="p-category">openssl</span></a> <a href="https://blogs.linux.pizza/tag:nginx" class="hashtag"><span>#</span><span class="p-category">nginx</span></a> <a href="https://blogs.linux.pizza/tag:pki" class="hashtag"><span>#</span><span class="p-category">pki</span></a></p>
]]></content:encoded>
      <guid>https://blogs.linux.pizza/secure-your-api-with-client-certificate-authenatication-in-nginx</guid>
      <pubDate>Sat, 15 Nov 2025 20:32:09 +0000</pubDate>
    </item>
    <item>
      <title>How to properly generate a .csr file</title>
      <link>https://blogs.linux.pizza/how-to-properly-generate-a-csr-file</link>
      <description>&lt;![CDATA[During my short IT-career, I have dealt with alot people who struggle with generating a .csr file (certificate signing request) on Linux. Windows (especially IIS) have a more clearer approach so that can most of the people figure out by themselves without having to ask to many  questions :)&#xA;&#xA;The following example generates a .csr and a .key file for the Company &#34;Company Name&#34;, located in some country in the city &#34;City&#34;. Just replace the variables to your liking.&#xA;&#xA;DOMAIN=www.example.com&#xA;COUNTRY=2 letter country code&#xA;ORG=&#34;Company Name&#34;&#xA;CITY=&#34;City&#34;&#xA;STATE=&#34;State&#34;&#xA;EMAIL=&#34;youremail@example.com&#34;&#xA;&#xA;openssl req -utf8 -nameopt multiline,utf8 -new -newkey rsa:2048 -nodes -sha256 -out $DOMAIN.csr -keyout $DOMAIN.key -subj &#34;/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=IT/CN=$DOMAIN/emailAddress=${EMAIL}&#34;&#xA;&#xA;Sometimes, you do want to generare a .csr file that includes two or more domains - a SAN certificate.&#xA;Using the same variable as above, we can now add more CN&#39;s to the .csr:&#xA;&#xA;openssl req -utf8 -nameopt multiline,utf8 -new -newkey rsa:2048 -nodes -sha256 -out $DOMAIN.csr -keyout $DOMAIN.key -subj &#34;/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=IT/CN=$DOMAIN/emailAddress=webmaster@example.com&#34; -config &lt;(&#xA;cat &lt;&lt;-EOF&#xA;[req]&#xA;defaultbits = 2048&#xA;defaultmd = sha256&#xA;reqextensions = reqext&#xA;distinguishedname = dn&#xA;[ dn ]&#xA;[ reqext ]&#xA;subjectAltName = @altnames&#xA;[altnames]&#xA;DNS.1 = www.example.se&#xA;DNS.2 = example.se&#xA;DNS.3 = www.example.it&#xA;DNS.3 = example.it&#xA;DNS.3 = www.example.fi&#xA;DNS.3 = example.fi&#xA;DNS.3 = www.example.org&#xA;DNS.3 = example.org&#xA;EOF&#xA;)&#xA;&#xA;Lets simplify this even more, with a script!&#xA;&#xA;Running this script, will prompt you with a small dialog that ask you for the domain-name you want a .csr file for.&#xA;It creates the .key and .csr, and prints out the .csr in the termina&#xA;!/bin/bash&#xA;echo -n &#34;Please enter the full Common Name (CN)&#34;&#xA;read DOMAIN&#xA;&#xA;COUNTRY=SE&#xA;ORG=&#34;Company&#34;&#xA;CITY=&#34;City&#34;&#xA;STATE=&#34;State&#34;&#xA;EMAIL=&#34;admin@domain.tld&#34;&#xA;&#xA;openssl req -utf8 -nameopt multiline,utf8 -new -newkey rsa:2048 -nodes -sha256 -out $DOMAIN.csr -keyout $DOMAIN.key -subj &#34;/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=IT/CN=$DOMAIN/emailAddress=$EMAIL&#34; -config &lt;(&#xA;cat &lt;&lt;-EOF&#xA;[req]&#xA;defaultbits = 2048&#xA;defaultmd = sha256&#xA;reqextensions = reqext&#xA;distinguishedname = dn&#xA;[ dn ]&#xA;[ reqext ]&#xA;subjectAltName = @altnames&#xA;[altnames]&#xA;DNS.1 = $DOMAIN&#xA;EOF&#xA;)&#xA;&#xA;echo &#34;private key and certificate request created&#34;&#xA;cat $DOMAIN.csr&#xA;exit 0 &#xA;&#xA;I hope this can prevent some headache for one or two :)&#xA;&#xA;#linux #openssl #csr #ssl #tls #certificate]]&gt;</description>
      <content:encoded><![CDATA[<p>During my short IT-career, I have dealt with alot people who struggle with generating a .csr file (certificate signing request) on Linux. Windows (especially IIS) have a more clearer approach so that can most of the people figure out by themselves without having to ask to many  questions :)</p>

<p>The following example generates a .csr and a .key file for the Company “Company Name”, located in some country in the city “City”. Just replace the variables to your liking.</p>

<pre><code>DOMAIN=www.example.com
COUNTRY=2 letter country code
ORG=&#34;Company Name&#34;
CITY=&#34;City&#34;
STATE=&#34;State&#34;
EMAIL=&#34;youremail@example.com&#34;

openssl req -utf8 -nameopt multiline,utf8 -new -newkey rsa:2048 -nodes -sha256 -out $DOMAIN.csr -keyout $DOMAIN.key -subj &#34;/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=IT/CN=$DOMAIN/emailAddress=${EMAIL}&#34;
</code></pre>

<p>Sometimes, you do want to generare a .csr file that includes two or more domains – a SAN certificate.
Using the same variable as above, we can now add more CN&#39;s to the .csr:</p>

<pre><code>openssl req -utf8 -nameopt multiline,utf8 -new -newkey rsa:2048 -nodes -sha256 -out $DOMAIN.csr -keyout $DOMAIN.key -subj &#34;/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=IT/CN=$DOMAIN/emailAddress=webmaster@example.com&#34; -config &lt;(
cat &lt;&lt;-EOF
[req]
default_bits = 2048
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[ dn ]
[ req_ext ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = www.example.se
DNS.2 = example.se
DNS.3 = www.example.it
DNS.3 = example.it
DNS.3 = www.example.fi
DNS.3 = example.fi
DNS.3 = www.example.org
DNS.3 = example.org
EOF
)
</code></pre>

<h2 id="lets-simplify-this-even-more-with-a-script" id="lets-simplify-this-even-more-with-a-script">Lets simplify this even more, with a script!</h2>

<p>Running this script, will prompt you with a small dialog that ask you for the domain-name you want a .csr file for.
It creates the .key and .csr, and prints out the .csr in the termina</p>

<pre><code>#!/bin/bash
echo -n &#34;Please enter the full Common Name (CN)&#34;
read DOMAIN

COUNTRY=SE
ORG=&#34;Company&#34;
CITY=&#34;City&#34;
STATE=&#34;State&#34;
EMAIL=&#34;admin@domain.tld&#34;

openssl req -utf8 -nameopt multiline,utf8 -new -newkey rsa:2048 -nodes -sha256 -out $DOMAIN.csr -keyout $DOMAIN.key -subj &#34;/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=IT/CN=$DOMAIN/emailAddress=$EMAIL&#34; -config &lt;(
cat &lt;&lt;-EOF
[req]
default_bits = 2048
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[ dn ]
[ req_ext ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
EOF
)

echo &#34;private key and certificate request created&#34;
cat $DOMAIN.csr
exit 0 
</code></pre>

<p>I hope this can prevent some headache for one or two :)</p>

<p><a href="https://blogs.linux.pizza/tag:linux" class="hashtag"><span>#</span><span class="p-category">linux</span></a> <a href="https://blogs.linux.pizza/tag:openssl" class="hashtag"><span>#</span><span class="p-category">openssl</span></a> <a href="https://blogs.linux.pizza/tag:csr" class="hashtag"><span>#</span><span class="p-category">csr</span></a> <a href="https://blogs.linux.pizza/tag:ssl" class="hashtag"><span>#</span><span class="p-category">ssl</span></a> <a href="https://blogs.linux.pizza/tag:tls" class="hashtag"><span>#</span><span class="p-category">tls</span></a> <a href="https://blogs.linux.pizza/tag:certificate" class="hashtag"><span>#</span><span class="p-category">certificate</span></a></p>
]]></content:encoded>
      <guid>https://blogs.linux.pizza/how-to-properly-generate-a-csr-file</guid>
      <pubDate>Thu, 20 Jun 2019 18:17:13 +0000</pubDate>
    </item>
  </channel>
</rss>