Monday, December 19, 2016

create self signed cert

Thanks to jpmens@gmail.com

Generate CA
#!/usr/bin/env bash
#(@)generate-CA.sh - Create CA key-pair and server key-pair signed by CA

# Copyright (c) 2013-2016 Jan-Piet Mens <jpmens()gmail.com>
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of mosquitto nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

#
# Usage:
# ./generate-CA.sh  creates ca.crt and server.{key,crt}
# ./generate-CA.sh hostname creates hostname.{key,crt}
# ./generate-CA.sh client email creates email.{key,crt}
#
# Set the following optional environment variables before invocation
# to add the specified IP addresses and/or hostnames to the subjAltName list
# These contain white-space-separated values
#
# IPLIST="172.13.14.15 192.168.1.1"
# HOSTLIST="a.example.com b.example.com"

set -e

export LANG=C

kind=server

if [ $# -ne 2 ]; then
 kind=server
 host=$(hostname -f)
 if [ -n "$1" ]; then
  host="$1"
 fi
else
 kind=client
 CLIENT="$2"
fi

[ -z "$USER" ] && USER=root

DIR=${TARGET:='.'}
# A space-separated list of alternate hostnames (subjAltName)
# may be empty ""
ALTHOSTNAMES=${HOSTLIST}
ALTADDRESSES=${IPLIST}
CA_ORG='/O=OwnTracks.org/OU=generate-CA/emailAddress=nobody@example.net'
CA_DN="/CN=An MQTT broker${CA_ORG}"
CACERT=${DIR}/ca
SERVER="${DIR}/${host}"
SERVER_DN="/CN=${host}$CA_ORG"
keybits=2048
openssl=$(which openssl)
MOSQUITTOUSER=${MOSQUITTOUSER:=$USER}

# Signature Algorithm. To find out which are supported by your
# version of OpenSSL, run `openssl dgst -help` and set your
# signature algorithm here. For example:
#
# defaultmd="-sha256"
#
defaultmd="-sha512"

function maxdays() {
 nowyear=$(date +%Y)
 years=$(expr 2032 - $nowyear)
 days=$(expr $years '*' 365)

 echo $days
}

function getipaddresses() {
 /sbin/ifconfig |
  grep -v tunnel |
  sed -En '/inet6? /p' |
  sed -Ee 's/inet6? (addr:)?//' |
  awk '{print $1;}' |
  sed -e 's/[%/].*//' |
  egrep -v '(::1|127\.0\.0\.1)' # omit loopback to add it later
}


function addresslist() {

 ALIST=""
 for a in $(getipaddresses); do
  ALIST="${ALIST}IP:$a,"
 done
 ALIST="${ALIST}IP:127.0.0.1,IP:::1,"

 for ip in $(echo ${ALTADDRESSES}); do
  ALIST="${ALIST}IP:${ip},"
 done
 for h in $(echo ${ALTHOSTNAMES}); do
  ALIST="${ALIST}DNS:$h,"
 done
 ALIST="${ALIST}DNS:localhost"
 echo $ALIST

}

days=$(maxdays)

if [ -n "$CAKILLFILES" ]; then
 rm -f $CACERT.??? $SERVER.??? $CACERT.srl
fi

if [ ! -f $CACERT.crt ]; then

 #    ____    _    
 #   / ___|  / \   
 #  | |     / _ \  
 #  | |___ / ___ \ 
 #   \____/_/   \_\
 #                 

 # Create un-encrypted (!) key
 $openssl req -newkey rsa:${keybits} -x509 -nodes $defaultmd -days $days -extensions v3_ca -keyout $CACERT.key -out $CACERT.crt -subj "${CA_DN}"
 echo "Created CA certificate in $CACERT.crt"
 $openssl x509 -in $CACERT.crt -nameopt multiline -subject -noout

 chmod 400 $CACERT.key
 chmod 444 $CACERT.crt
 chown $MOSQUITTOUSER $CACERT.*
 echo "Warning: the CA key is not encrypted; store it safely!"
fi


if [ $kind == 'server' ]; then

 #   ____                           
 #  / ___|  ___ _ ____   _____ _ __ 
 #  \___ \ / _ \ '__\ \ / / _ \ '__|
 #   ___) |  __/ |   \ V /  __/ |   
 #  |____/ \___|_|    \_/ \___|_|   
 #                                  

 if [ ! -f $SERVER.key ]; then
  echo "--- Creating server key and signing request"
  $openssl genrsa -out $SERVER.key $keybits
  $openssl req -new $defaultmd \
   -out $SERVER.csr \
   -key $SERVER.key \
   -subj "${SERVER_DN}"
  chmod 400 $SERVER.key
  chown $MOSQUITTOUSER $SERVER.key
 fi

 if [ -f $SERVER.csr -a ! -f $SERVER.crt ]; then

  # There's no way to pass subjAltName on the CLI so
  # create a cnf file and use that.

  CNF=`mktemp /tmp/cacnf.XXXXXXXX` || { echo "$0: can't create temp file" >&2; exit 1; }
  sed -e 's/^.*%%% //' > $CNF <<\!ENDconfig
  %%% [ JPMextensions ]
  %%% basicConstraints        = critical,CA:false
  %%% nsCertType              = server
  %%% keyUsage                = nonRepudiation, digitalSignature, keyEncipherment
  %%% nsComment               = "Broker Certificate"
  %%% subjectKeyIdentifier    = hash
  %%% authorityKeyIdentifier  = keyid,issuer:always
  %%% subjectAltName          = $ENV::SUBJALTNAME
  %%% # issuerAltName           = issuer:copy
  %%% ## nsCaRevocationUrl       = http://mqttitude.org/carev/
  %%% ## nsRevocationUrl         = http://mqttitude.org/carev/
  %%% certificatePolicies     = ia5org,@polsection
  %%% 
  %%% [polsection]
  %%% policyIdentifier     = 1.3.5.8
  %%% CPS.1      = "http://localhost"
  %%% userNotice.1     = @notice
  %%% 
  %%% [notice]
  %%% explicitText            = "This CA is for a local MQTT broker installation only"
  %%% organization            = "OwnTracks"
  %%% noticeNumbers           = 1

!ENDconfig

  SUBJALTNAME="$(addresslist)"
  export SUBJALTNAME  # Use environment. Because I can. ;-)

  echo "--- Creating and signing server certificate"
  $openssl x509 -req $defaultmd \
   -in $SERVER.csr \
   -CA $CACERT.crt \
   -CAkey $CACERT.key \
   -CAcreateserial \
   -CAserial "${DIR}/ca.srl" \
   -out $SERVER.crt \
   -days $days \
   -extfile ${CNF} \
   -extensions JPMextensions

  rm -f $CNF
  chmod 444 $SERVER.crt
  chown $MOSQUITTOUSER $SERVER.crt
 fi
else
 #    ____ _ _            _   
 #   / ___| (_) ___ _ __ | |_ 
 #  | |   | | |/ _ \ '_ \| __|
 #  | |___| | |  __/ | | | |_ 
 #   \____|_|_|\___|_| |_|\__|
 #                            

 if [ ! -f $CLIENT.key ]; then
  echo "--- Creating client key and signing request"
  $openssl genrsa -out $CLIENT.key $keybits

  CNF=`mktemp /tmp/cacnf-req.XXXXXXXX` || { echo "$0: can't create temp file" >&2; exit 1; }
  # Mosquitto's use_identity_as_username takes the CN attribute
  # so we're populating that with the client's name
  sed -e 's/^.*%%% //' > $CNF <<!ENDClientconfigREQ
  %%% [ req ]
  %%% distinguished_name = req_distinguished_name
  %%% prompt   = no
  %%% output_password  = secret
  %%% 
  %%% [ req_distinguished_name ]
  %%% # O                       = OwnTracks
  %%% # OU                      = MQTT
  %%% # CN                      = Suzie Smith
  %%% CN                        = $CLIENT
  %%% # emailAddress            = $CLIENT
!ENDClientconfigREQ

  $openssl req -new $defaultmd \
   -out $CLIENT.csr \
   -key $CLIENT.key \
   -config $CNF
  chmod 400 $CLIENT.key
 fi

 if [ -f $CLIENT.csr -a ! -f $CLIENT.crt ]; then

  CNF=`mktemp /tmp/cacnf-cli.XXXXXXXX` || { echo "$0: can't create temp file" >&2; exit 1; }
  sed -e 's/^.*%%% //' > $CNF <<\!ENDClientconfig
  %%% [ JPMclientextensions ]
  %%% basicConstraints        = critical,CA:false
  %%% subjectAltName          = email:copy
  %%% nsCertType              = client,email
  %%% extendedKeyUsage        = clientAuth,emailProtection
  %%% keyUsage                = digitalSignature, keyEncipherment, keyAgreement
  %%% nsComment               = "Client Broker Certificate"
  %%% subjectKeyIdentifier    = hash
  %%% authorityKeyIdentifier  = keyid,issuer:always

!ENDClientconfig

  SUBJALTNAME="$(addresslist)"
  export SUBJALTNAME  # Use environment. Because I can. ;-)

  echo "--- Creating and signing client certificate"
  $openssl x509 -req $defaultmd \
   -in $CLIENT.csr \
   -CA $CACERT.crt \
   -CAkey $CACERT.key \
   -CAcreateserial \
   -CAserial "${DIR}/ca.srl" \
   -out $CLIENT.crt \
   -days $days \
   -extfile ${CNF} \
   -extensions JPMclientextensions

  rm -f $CNF
  chmod 444 $CLIENT.crt
 fi
fi

 Generate Client
#!/bin/bash
#  generate-client - Create client key-pair for MQTT signed by CA
#
#  The key is not encrypted so that the certificate can be used on
#  embedded devices.

# Copyright 2015 Jerry Dunmire <jedunmire-AT-gmail>
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of mosquitto nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

#
# Usage:
#   ./generate-client.sh client_name
#     creates client_name{key,crt}
set -e

if [ -n "$1" ]; then
    client="$1"
else
   echo "ERROR: missing client_name argument." >&2
   echo "USAGE: $0 client_name" >&2
   echo "exiting... " >&2
   exit 1
fi

[ -z "$USER" ] && USER=root

DIR=${TARGET:='.'}
# CA_ORG set to match generate-CA.sh
CA_ORG='/O=MQTTitude.org/emailAddress=nobody@example.net'
CACERT=${DIR}/ca
CLIENT="${DIR}/${client}"
CLIENT_DN="/CN=${client}$CA_ORG"
keybits=2048
openssl=$(which openssl)

function maxdays() {
    nowyear=$(date +%Y)
    years=$(expr 2032 - $nowyear)
    days=$(expr $years '*' 365)

    echo $days
}

days=$(maxdays)

if [ ! -f $CACERT.crt ]
then
    echo "ERROR: Could not find CA certificate: $CACERT.crt" >&2
    echo "Exiting..." >&2
    exit 1
fi

if [ ! -f $CLIENT.key ]
then
    echo "--- Creating client key and signing request"
    echo "--- WARNING: key is not encrypted, keep it safe!"
    $openssl genrsa -out $CLIENT.key $keybits
    $openssl req -new \
        -out $CLIENT.csr \
        -key $CLIENT.key \
        -subj "${CLIENT_DN}"
    chmod 400 $CLIENT.key
fi

if [ -f $CLIENT.csr -a ! -f $CLIENT.crt ]
then
    echo "--- Creating and signing client certificate"
    $openssl x509 -req \
        -in $CLIENT.csr \
        -CA $CACERT.crt \
        -CAkey $CACERT.key \
        -CAserial "${DIR}/ca.srl" \
        -out $CLIENT.crt \
        -days $days \
        -addtrust clientAuth

    chmod 444 $CLIENT.crt
fi