#!/bin/sh # Generate CA + wildcard cert for any hostname CA_name='local CA' helptext='Usage: ./CA.sh Generate a CA and sign a wildacrd cert for with it.' set -o errexit # (-e) exit immediately if any command has a non-zero exit status set -o nounset # (-u) don't accept undefined variables #set -o xtrace # for debugging # Check input. if [ "$#" -lt 1 ] || [ "$#" -gt 1 ]; then >&2 echo "$helptext" exit 1 fi host="$1" # Check if host is an IP address. ip=0 # If `ipcalc-ng` is available, use it. if command -v ipcalc-ng >/dev/null; then if ipcalc-ng -sc "$host"; then ip=1 fi # Else if `ip` is available, use it. # Note: a simple number also passes this check, # but it's good enough for our purposes. elif command -v ip >/dev/null; then if ip route get "$host" >/dev/null 2>&1; then ip=1 fi fi # If host is an IDN, convert it to punycode. # Use the `idn` command, if available. if command -v idn >/dev/null; then host=$(echo "$host" | idn) fi # Create CA directory, if it does not exist. mkdir -p CA cd CA # Generate CA. if [ ! -f "ca.key" ] && [ ! -f "ca.crt" ]; then openssl genrsa -out ca.key 2048 openssl req -new -x509 -key ca.key -out ca.crt -subj "/CN=$CA_name" -days 30 openssl x509 -in ca.crt -noout -text # Copy the CA cert under a new name, allowing it to be accepted in the # Android trust store (/system/etc/security/cacerts/). mkdir -p android filename=$(openssl x509 -inform PEM -subject_hash_old -in ca.crt | head -1) cp ca.crt "android/$filename.0" fi # Generate wildcard cert. if [ ! -f "$host.key" ] && [ ! -f "$host.crt" ]; then # Set the Subject Alternative Name based on whether # the host is an IP address or not. if [ $ip -eq 1 ]; then SAN1="IP:$host" SAN2="IP = $host" else SAN1="DNS:*.$host, DNS:$host" SAN2="DNS.1 = *.$host DNS.2 = $host" fi openssl genrsa -out "$host.key" 2048 openssl req -new -key "$host.key" -out "$host.csr" -subj "/CN=$host" \ -addext "subjectAltName = $SAN1" #openssl req -in "$host.csr" -noout -text # Prepare X.509 extensions file. echo "basicConstraints=CA:FALSE subjectAltName=@my_subject_alt_names subjectKeyIdentifier = hash [ my_subject_alt_names ] $SAN2" > ext.conf # Sign the cert. openssl x509 -req -in "$host.csr" -out "$host.crt" -days 30 \ -CA ca.crt -CAkey ca.key -extfile ext.conf -CAcreateserial openssl x509 -in "$host.crt" -noout -text rm "$host.csr" # Remove X.509 extensions file. rm ext.conf fi # Create bundle (probably not be required). #cat "$host.crt" ca.crt > "$host.bundle.crt" # Show generated files. if command -v tree >/dev/null; then cd .. echo '=== Generated files ===' tree CA fi