#!/bin/bash
# Generate a "modern" self-signed TLS certificate (using SANs and ECC)

# Copyright (C) 2022  Johannes Truschnigg <johannes@truschnigg.info>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.

echo 'Hostnames (space-separated, 1st will be CN, issuer, and filename prefix): '
read -r -e -i "${hostname:-host.example.com}" hostnames
echo 'IP addresses (optional; space-separated): '
read -r -e -i "${ip:-192.168.2.1}"  ips

umask 0077

san_dns=''
for h in ${hostnames}
do
  [[ -z ${cn} ]] && dn="CN=${h}" && cn="${h}"
  san_dns="DNS:${h},${san_dns}"
done

for i in ${ips}
do
  san_ip="IP:${i},${san_ip}"
done

subjectAltName="${san_dns}"
[[ -n ${san_ip} ]] && subjectAltName="${subjectAltName}${san_ip}"
subjectAltName="${subjectAltName%,*}"

set -u
set -e
openssl ecparam -genkey -name secp521r1 -noout -out "${cn}.key.pem"
openssl req -reqexts san_details -new -key "${cn}.key.pem" -sha256 -days "${days:-10000}" -x509 -extensions san_details -out "${cn}.crt.pem" -config <(printf '[req] \n prompt=no \n utf8=yes \n distinguished_name=dn_details \n req_extensions=san_details \n [dn_details] \n %s \n [san_details] \n subjectAltName=%s\n' "${dn}" "${subjectAltName}")

echo "========================================================================================"
echo "All done, cert data follows:"
openssl x509 -in "${cn}.crt.pem" -noout -text
ls -l "./${cn}.key.pem" "./${cn}.crt.pem"
