title: How to verify ECDSA and RSA certificates
body: <p>I am going to run acme-tiny on a central webserver in order to get the certificates for my two Nginx reverse proxies issued. The newly created certificates are published over https and available to the reverse proxies via download.</p>
  
  <p>I want the Nginx servers to check the newly created certificates before replacing the old certificates with the new ones. For this purpose, I wrote the following bash script, which is run on each Nginx server. I would like to know whether I missed something or whether you have ideas for improvement. Or is there a better way to realise this?</p>
  
  <pre><code>#!/bin/bash
  
  set -e
  
  # Commands for deriving the public keys:
  # openssl ec  -in ecdsa.key -pubout &gt; ecdsa_public_key.pem
  # openssl rsa -in rsa.key   -pubout &gt; rsa_public_key.pem
  
  curl -O https://example.org/ecdsa.pem
  curl -O https://example.org/intermediate.pem
  curl -O https://example.org/rsa.pem
  
  # Are the certificates not expired?
  # Have they (ecdsa.pem, rsa.pem) been recently issued (validity &gt;= 80 days)?
  openssl x509 -checkend 6912000 -noout -in intermediate.pem
  openssl x509 -checkend 6912000 -noout -in ecdsa.pem
  openssl x509 -checkend 6912000 -noout -in rsa.pem
  
  # Do the private keys and certificates belong together?
  openssl x509 -in ecdsa.pem -pubkey | \
     sed -n '/-----BEGIN PUBLIC KEY-----/,/-----END PUBLIC KEY-----/p' | \
     cmp - ecdsa_public_key.pem
  openssl x509 -in rsa.pem   -pubkey | \
     sed -n '/-----BEGIN PUBLIC KEY-----/,/-----END PUBLIC KEY-----/p' | \
     cmp - rsa_public_key.pem
  
  # Is the certificate chain valid?
  openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt intermediate.pem
  openssl verify -CAfile intermediate.pem ecdsa.pem
  openssl verify -CAfile intermediate.pem rsa.pem
  
  # Are the certificates issued for the correct domain names?
  (openssl x509 -noout -subject -in ecdsa.pem | awk -F'CN=' '{print $2}' | \
     awk -F'/' '{print $1}'; \
     openssl x509 -noout -text -in ecdsa.pem | grep "^[[:space:]]*DNS:" | \
     xargs | tr ' ' '\n' | grep ^DNS | sed 's/^DNS://' | sed 's/,$//')| \
     sort | uniq | cmp - domains.txt
  (openssl x509 -noout -subject -in rsa.pem   | awk -F'CN=' '{print $2}' | \
     awk -F'/' '{print $1}'; \
     openssl x509 -noout -text -in rsa.pem   | grep "^[[:space:]]*DNS:" | \
     xargs | tr ' ' '\n' | grep ^DNS | sed 's/^DNS://' | sed 's/,$//')| \
     sort | uniq | cmp - domains.txt
  </code></pre>
  
  <p><strong>UPDATE 1:</strong></p>
  
  <p>As I have stated I want to check every aspect of the certificate not just the validity of the certificate chain. It currently checks:</p>
  
  <ul>
  <li>the chains validity,</li>
  <li>whether private key and certificate match,</li>
  <li>whether the cert has been recently issued making replacement of the older cert necessary</li>
  <li>whether the cert has been issued for the desired domain names</li>
  </ul>
  
  <p><strong>Therefore, it isn't a duplicate to the linked questions. And, I would like to know whether I have forgotten some check or whether there is space for improvement.</strong> Below is an update to the bash script. Beware I have not tested it thoroughly, yet.</p>
  
  <pre><code>#!/bin/bash
  set -e
  
  # Execute the script:
  # ( cd /path_to_workdir &amp;&amp; \
  #   su - james -c "./check_cert.sh https://www.example.org intermediate.pem ecdsa.pem ecdsa_pubkey.pem /etc/ssl/certs/ca-certificates.crt domains.txt pass.txt" &amp;&amp; \
  #   su - james -c "./check_cert.sh https://www.example.org intermediate.pem rsa.pem rsa_pubkey.pem /etc/ssl/certs/ca-certificates.crt domains.txt pass.txt" &amp;&amp; \
  #   cat ecdsa.pem intermediate.pem &gt; /etc/nginx/ssl/ecdsa_bundle.pem ) &amp;&amp; \
  #   cat rsa.pem intermediate.pem &gt; /etc/nginx/ssl/rsa_bundle.pem ) &amp;&amp; \
  # /etc/init.d/nginx reload
  
  # Download URL, e.g. https://example.org
  URL=$1
  
  # Intermediate certificate of certificate chain
  INTERMEDIATE=$2
  
  # Issued certificate, e.g. ecdsa.pem
  CERT=$3 
  
  # Public key derived from private key via:
  # openssl ec  -in ecdsa.key -pubout &gt; ecdsa_pubkey.pem
  # openssl rsa -in rsa.key   -pubout &gt; rsa_pubkey.pem
  PUBKEY=$4
  
  # ca-certificates file, e.g. /etc/ssl/certs/ca-certificates.crt
  CACERTS=$5
  
  # Domains that the cert should cover
  DOMAINS=$6
  
  # password-file.txt possible content:
  # machine example.org login james password H3Llo
  PASS=$7
  
  # Download files if newer than local.
  if [[ $(curl -s -O --netrc-file "$PASS" -w "%{http_code}" -z "$CERT" "$URL/$CERT") -eq 304 ]]; then
     echo "No new certificate issued. Nothing to do!"
     exit 1
  fi
  curl -s -O --netrc-file "$PASS" -z "$INTERMEDIATE" "$URL/$INTERMEDIATE"
  
  # Is the certificate chain valid?
  openssl verify -CAfile "$CACERTS" -untrusted "$INTERMEDIATE" "$CERT"
  
  # Do the private keys and certificates belong together?
  openssl x509 -in "$CERT" -pubkey | \
     sed -n '/-----BEGIN PUBLIC KEY-----/,/-----END PUBLIC KEY-----/p' | \
     cmp - "${PUBKEY}"
  
  # Has the Let's Encrypt certificate been recently issued (validity &gt;= 80 days)?
  openssl x509 -checkend 6912000 -noout -in "$CERT"
  
  # Are the certificates issued for the correct domain names?
  (openssl x509 -noout -subject -in "$CERT" | awk -F'CN=' '{print $2}' | \
     awk -F'/' '{print $1}'; \
     openssl x509 -noout -text -in "$CERT" | grep "^[[:space:]]*DNS:" | \
     xargs | tr ' ' '\n' | grep ^DNS | sed 's/^DNS://' | sed 's/,$//')| \
     sort | uniq | cmp - "$DOMAINS"
  </code></pre>
  
  <p>The code might be run via cronjob:</p>
  
  <pre><code>0 1 * * * /usr/local/bin/update_cert.sh &gt;/dev/null 2&gt;&amp;1
  </code></pre>
  
  <p>The content of update_cert.sh might be:</p>
  
  <pre><code>#!/bin/bash
  ( cd /path_to_workdir &amp;&amp; \
     su - james -c "./check_cert.sh https://www.example.org intermediate.pem ecdsa.pem ecdsa_pubkey.pem /etc/ssl/certs/ca-certificates.crt domains.txt pass.txt" &amp;&amp; \
     su - james -c "./check_cert.sh https://www.example.org intermediate.pem rsa.pem rsa_pubkey.pem /etc/ssl/certs/ca-certificates.crt domains.txt pass.txt" &amp;&amp; \
     cat ecdsa.pem intermediate.pem &gt; /etc/nginx/ssl/ecdsa_bundle.pem ) &amp;&amp; \
     cat rsa.pem intermediate.pem &gt; /etc/nginx/ssl/rsa_bundle.pem ) &amp;&amp; \
  /etc/init.d/nginx reload
  </code></pre>