123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- #! /bin/bash
- #
- # Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
- # Copyright (c) 2016 Viktor Dukhovni <openssl-users@dukhovni.org>.
- # All rights reserved.
- #
- # Licensed under the Apache License 2.0 (the "License"). You may not use
- # this file except in compliance with the License. You can obtain a copy
- # in the file LICENSE in the source distribution or at
- # https://www.openssl.org/source/license.html
- # This file is dual-licensed and is also available under other terms.
- # Please contact the author.
- # 100 years should be enough for now
- if [ -z "$DAYS" ]; then
- DAYS=36525
- fi
- if [ -z "$OPENSSL_SIGALG" ]; then
- OPENSSL_SIGALG=sha256
- fi
- if [ -z "$REQMASK" ]; then
- REQMASK=utf8only
- fi
- stderr_onerror() {
- (
- err=$("$@" >&3 2>&1) || {
- printf "%s\n" "$err" >&2
- exit 1
- }
- ) 3>&1
- }
- key() {
- local key=$1; shift
- local alg=rsa
- if [ -n "$OPENSSL_KEYALG" ]; then
- alg=$OPENSSL_KEYALG
- fi
- local bits=2048
- if [ -n "$OPENSSL_KEYBITS" ]; then
- bits=$OPENSSL_KEYBITS
- fi
- if [ ! -f "${key}.pem" ]; then
- args=(-algorithm "$alg")
- case $alg in
- rsa) args=("${args[@]}" -pkeyopt rsa_keygen_bits:$bits );;
- ec) args=("${args[@]}" -pkeyopt "ec_paramgen_curve:$bits")
- args=("${args[@]}" -pkeyopt ec_param_enc:named_curve);;
- dsa) args=(-paramfile "$bits");;
- ed25519) ;;
- ed448) ;;
- *) printf "Unsupported key algorithm: %s\n" "$alg" >&2; return 1;;
- esac
- stderr_onerror \
- openssl genpkey "${args[@]}" -out "${key}.pem"
- fi
- }
- # Usage: $0 req keyname dn1 dn2 ...
- req() {
- local key=$1; shift
- key "$key"
- local errs
- stderr_onerror \
- openssl req -new -"${OPENSSL_SIGALG}" -key "${key}.pem" \
- -config <(printf "string_mask=%s\n[req]\n%s\n%s\n[dn]\n" \
- "$REQMASK" "prompt = no" "distinguished_name = dn"
- for dn in "$@"; do echo "$dn"; done)
- }
- req_nocn() {
- local key=$1; shift
- key "$key"
- stderr_onerror \
- openssl req -new -"${OPENSSL_SIGALG}" -subj / -key "${key}.pem" \
- -config <(printf "[req]\n%s\n[dn]\nCN_default =\n" \
- "distinguished_name = dn")
- }
- cert() {
- local cert=$1; shift
- local exts=$1; shift
- stderr_onerror \
- openssl x509 -req -"${OPENSSL_SIGALG}" -out "${cert}.pem" \
- -extfile <(printf "%s\n" "$exts") "$@"
- }
- genroot() {
- local cn=$1; shift
- local key=$1; shift
- local cert=$1; shift
- local bcon="basicConstraints = critical,CA:true"
- local ku="keyUsage = keyCertSign,cRLSign"
- local skid="subjectKeyIdentifier = hash"
- local akid="authorityKeyIdentifier = keyid"
- exts=$(printf "%s\n%s\n%s\n" "$bcon" "$ku" "$skid" "$akid")
- for eku in "$@"
- do
- exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
- done
- csr=$(req "$key" "CN = $cn") || return 1
- echo "$csr" |
- cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days "${DAYS}"
- }
- genca() {
- local OPTIND=1
- local purpose=
- while getopts p:c: o
- do
- case $o in
- p) purpose="$OPTARG";;
- c) certpol="$OPTARG";;
- *) echo "Usage: $0 genca [-p EKU][-c policyoid] cn keyname certname cakeyname cacertname" >&2
- return 1;;
- esac
- done
- shift $((OPTIND - 1))
- local cn=$1; shift
- local key=$1; shift
- local cert=$1; shift
- local cakey=$1; shift
- local cacert=$1; shift
- local bcon="basicConstraints = critical,CA:true"
- local ku="keyUsage = keyCertSign,cRLSign"
- local skid="subjectKeyIdentifier = hash"
- local akid="authorityKeyIdentifier = keyid"
- exts=$(printf "%s\n%s\n%s\n" "$bcon" "$ku" "$skid" "$akid")
- if [ -n "$purpose" ]; then
- exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$purpose")
- fi
- if [ -n "$NC" ]; then
- exts=$(printf "%s\nnameConstraints = %s\n" "$exts" "$NC")
- fi
- if [ -n "$certpol" ]; then
- exts=$(printf "%s\ncertificatePolicies = %s\n" "$exts" "$certpol")
- fi
- csr=$(req "$key" "CN = $cn") || return 1
- echo "$csr" |
- cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
- -set_serial 2 -days "${DAYS}" "$@"
- }
- gen_nonbc_ca() {
- local cn=$1; shift
- local key=$1; shift
- local cert=$1; shift
- local cakey=$1; shift
- local cacert=$1; shift
- local skid="subjectKeyIdentifier = hash"
- local akid="authorityKeyIdentifier = keyid"
- exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid")
- exts=$(printf "%s\nkeyUsage = %s\n" "$exts" "keyCertSign, cRLSign")
- for eku in "$@"
- do
- exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
- done
- csr=$(req "$key" "CN = $cn") || return 1
- echo "$csr" |
- cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
- -set_serial 2 -days "${DAYS}"
- }
- # Usage: $0 genpc keyname certname eekeyname eecertname pcext1 pcext2 ...
- #
- # Note: takes csr on stdin, so must be used with $0 req like this:
- #
- # $0 req keyname dn | $0 genpc keyname certname eekeyname eecertname pcext ...
- genpc() {
- local key=$1; shift
- local cert=$1; shift
- local cakey=$1; shift
- local ca=$1; shift
- exts=$(printf "%s\n%s\n%s\n%s\n" \
- "subjectKeyIdentifier = hash" \
- "authorityKeyIdentifier = keyid, issuer:always" \
- "basicConstraints = CA:false" \
- "proxyCertInfo = critical, @pcexts";
- echo "[pcexts]";
- for x in "$@"; do echo $x; done)
- cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
- -set_serial 2 -days "${DAYS}"
- }
- geneeconfig() {
- local key=$1; shift
- local cert=$1; shift
- local cakey=$1; shift
- local ca=$1; shift
- local conf=$1; shift
- exts=$(printf "%s\n%s\n%s\n%s\n" \
- "subjectKeyIdentifier = hash" \
- "authorityKeyIdentifier = keyid" \
- "basicConstraints = CA:false"; \
- echo "$conf")
- cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
- -set_serial 2 -days "${DAYS}"
- }
- # Usage: $0 geneealt keyname certname cakeyname cacertname alt1 alt2 ...
- #
- # Note: takes csr on stdin, so must be used with $0 req like this:
- #
- # $0 req keyname dn | $0 geneealt keyname certname cakeyname cacertname alt ...
- geneealt() {
- local key=$1; shift
- local cert=$1; shift
- local cakey=$1; shift
- local ca=$1; shift
- conf=$(echo "subjectAltName = @alts"
- echo "[alts]";
- for x in "$@"; do echo "$x"; done)
- geneeconfig $key $cert $cakey $ca "$conf"
- }
- genee() {
- local OPTIND=1
- local purpose=serverAuth
- local ku=
- while getopts p:k: o
- do
- case $o in
- p) purpose="$OPTARG";;
- k) ku="keyUsage = $OPTARG";;
- *) echo "Usage: $0 genee [-k KU] [-p EKU] cn keyname certname cakeyname cacertname" >&2
- return 1;;
- esac
- done
- shift $((OPTIND - 1))
- local cn=$1; shift
- local key=$1; shift
- local cert=$1; shift
- local cakey=$1; shift
- local ca=$1; shift
- exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
- "subjectKeyIdentifier = hash" \
- "authorityKeyIdentifier = keyid, issuer" \
- "basicConstraints = CA:false" \
- "$ku" \
- "extendedKeyUsage = $purpose" \
- "subjectAltName = @alts" "DNS=${cn}")
- csr=$(req "$key" "CN = $cn") || return 1
- echo "$csr" |
- cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
- -set_serial 2 -days "${DAYS}" "$@"
- }
- geneeextra() {
- local OPTIND=1
- local purpose=serverAuth
- while getopts p: o
- do
- case $o in
- p) purpose="$OPTARG";;
- *) echo "Usage: $0 geneeextra [-p EKU] cn keyname certname cakeyname cacertname extraext" >&2
- return 1;;
- esac
- done
- shift $((OPTIND - 1))
- local cn=$1; shift
- local key=$1; shift
- local cert=$1; shift
- local cakey=$1; shift
- local ca=$1; shift
- local extraext=$1; shift
- exts=$(printf "%s\n%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
- "subjectKeyIdentifier = hash" \
- "authorityKeyIdentifier = keyid, issuer" \
- "basicConstraints = CA:false" \
- "extendedKeyUsage = $purpose" \
- "subjectAltName = @alts"\
- "$extraext" "DNS=${cn}")
- csr=$(req "$key" "CN = $cn") || return 1
- echo "$csr" |
- cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
- -set_serial 2 -days "${DAYS}" "$@"
- }
- geneenocsr() {
- local OPTIND=1
- local purpose=serverAuth
- while getopts p: o
- do
- case $o in
- p) purpose="$OPTARG";;
- *) echo "Usage: $0 geneenocsr [-p EKU] cn certname cakeyname cacertname" >&2
- return 1;;
- esac
- done
- shift $((OPTIND - 1))
- local cn=$1; shift
- local cert=$1; shift
- local cakey=$1; shift
- local ca=$1; shift
- exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
- "subjectKeyIdentifier = hash" \
- "authorityKeyIdentifier = keyid, issuer" \
- "basicConstraints = CA:false" \
- "extendedKeyUsage = $purpose" \
- "subjectAltName = @alts" "DNS=${cn}")
- cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
- -set_serial 2 -days "${DAYS}" "$@"
- }
- genss() {
- local cn=$1; shift
- local key=$1; shift
- local cert=$1; shift
- exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
- "subjectKeyIdentifier = hash" \
- "authorityKeyIdentifier = keyid, issuer" \
- "basicConstraints = CA:false" \
- "extendedKeyUsage = serverAuth" \
- "subjectAltName = @alts" "DNS=${cn}")
- csr=$(req "$key" "CN = $cn") || return 1
- echo "$csr" |
- cert "$cert" "$exts" -signkey "${key}.pem" \
- -set_serial 1 -days "${DAYS}" "$@"
- }
- gennocn() {
- local key=$1; shift
- local cert=$1; shift
- csr=$(req_nocn "$key") || return 1
- echo "$csr" |
- cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@"
- }
- genct() {
- local OPTIND=1
- local purpose=serverAuth
- while getopts p: o
- do
- case $o in
- p) purpose="$OPTARG";;
- *) echo "Usage: $0 genct [-p EKU] cn keyname certname cakeyname cacertname ctlogkey" >&2
- return 1;;
- esac
- done
- shift $((OPTIND - 1))
- local cn=$1; shift
- local key=$1; shift
- local cert=$1; shift
- local cakey=$1; shift
- local ca=$1; shift
- local logkey=$1; shift
- exts=$(printf "%s\n%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
- "subjectKeyIdentifier = hash" \
- "authorityKeyIdentifier = keyid, issuer" \
- "basicConstraints = CA:false" \
- "extendedKeyUsage = $purpose" \
- "1.3.6.1.4.1.11129.2.4.3 = critical,ASN1:NULL"\
- "subjectAltName = @alts" "DNS=${cn}")
- csr=$(req "$key" "CN = $cn") || return 1
- echo "$csr" |
- cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
- -set_serial 2 -days "${DAYS}" "$@"
- cat ${cert}.pem ${ca}.pem > ${cert}-chain.pem
- go run github.com/google/certificate-transparency-go/ctutil/sctgen \
- --log_private_key ${logkey}.pem \
- --timestamp="2020-01-01T00:00:00Z" \
- --cert_chain ${cert}-chain.pem \
- --tls_out ${cert}.tlssct
- rm ${cert}-chain.pem
- filesize=$(wc -c <${cert}.tlssct)
- exts=$(printf "%s\n%s\n%s\n%s\n%s%04X%04X%s\n%s\n[alts]\n%s\n" \
- "subjectKeyIdentifier = hash" \
- "authorityKeyIdentifier = keyid, issuer" \
- "basicConstraints = CA:false" \
- "extendedKeyUsage = $purpose" \
- "1.3.6.1.4.1.11129.2.4.2 = ASN1:FORMAT:HEX,OCT:" $((filesize+2)) $filesize `xxd -p ${cert}.tlssct | tr -d '\n'` \
- "subjectAltName = @alts" "DNS=${cn}")
- echo "$csr" |
- cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
- -set_serial 2 -days "${DAYS}" "$@"
- }
- "$@"
|