#!/usr/bin/env zsh # zeasypki -- easy PKI # Copyright (C) 2022 Sergey Matveev set -e KEY_ENCRYPT_RECIPIENT=${KEY_ENCRYPT_RECIPIENT:-12AD32689C660D426967FD75CB8205632107AD8A} COUNTRY=${COUNTRY:-RU} # Turn on PyGOST utilities path=(~/local/stow/py310/bin ~/work/pygost/pygost/asn1schemas $path) export -TU PYTHONPATH pythonpath pythonpath=(~/work/pygost ~/work/pyderasn) key_encrypt() { gpg --encrypt --recipient $KEY_ENCRYPT_RECIPIENT } key_decrypt() { gpg --decrypt } # ------------------------ >8 ------------------------ usage() { >&2 < $tmpl < $key certtool \ --generate-self-signed \ --load-privkey $key \ --template $tmpl \ --outfile $cert reply=(${mapfile[$key]} ${mapfile[$cert]}) } ee_key_new_ecdsa() { certtool_genkey 256 } ee_key_new_gost() { cert-selfsigned-example.py --cn does-not-matter --ai 256A --only-key } ee_renew_ecdsa() { local ca=$1 local domain=$2 local cakey=`mktemp` local key=`mktemp` local tmpl=`mktemp` local cert=`mktemp` trap "rm -f $cakey $key $tmpl $cert" HUP PIPE INT QUIT TERM EXIT key_get ca/ecdsa/$ca mapfile[$cakey]=$REPLY key_get ee/ecdsa/$ca/$domain mapfile[$key]=$REPLY > $tmpl <> $cakey < ca/gost/$ca/cer.pem key_get ee/gost/$ca/$domain mapfile[$key]=$REPLY cert-selfsigned-example.py \ --issue-with $cakey \ --reuse-key $key \ --cn $domain --country $COUNTRY --ai 256A } ca_new_gost() { local domain=$1 local key=`mktemp` local cert=`mktemp` trap "rm -f $key $cert" HUP PIPE INT QUIT TERM EXIT cert-selfsigned-example.py \ --ca \ --cn $domain \ --country $COUNTRY \ --serial 1 \ --ai 512C \ --out-key $key \ --out-cert $cert reply=(${mapfile[$key]} ${mapfile[$cert]}) } dane_ecdsa() { certtool --key-id --hash=sha256 } dane_gost() { cert-dane-hash.py } case $1 in (ca) [[ $# -eq 3 ]] || usage algo=$2 domain=$3 dst=ca/$algo/$domain zf_mkdir -p $dst [[ -s $dst/key.pem ]] && { print $dst/key.pem already exists >&2 exit 1 } ca_new_${algo} $domain _umask=`umask` umask 077 mapfile[${dst}/key.pem]=${reply[1]} umask $_umask mapfile[${dst}/cer.pem]=${reply[2]} print $dst ;; (encrypt) [[ $# -eq 2 ]] || usage key=$2/key.pem [[ -s $key ]] || { print no $key found >&2 exit 1 } umask 077 key_encrypt < $key > $key.enc rm $key ;; (new) [[ $# -eq 2 ]] || usage cols=(${(s:/:)2}) algo=${cols[2]} ca=${cols[3]} domain=${cols[4]} dst=ee/$algo/$ca/$domain [[ $dst = $2 ]] zf_mkdir -p $dst [[ -s $dst/key.pem ]] && { print $dst/key.pem already exists >&2 exit 1 } _umask=`umask` umask 077 ee_key_new_${algo} > $dst/key.pem umask $_umask ee_renew_${algo} $ca $domain > $dst/cer.pem ;; (renew) [[ $# -eq 2 ]] || usage cols=(${(s:/:)2}) algo=${cols[2]} ca=${cols[3]} domain=${cols[4]} ee_renew_${algo} $ca $domain > ee/$algo/$ca/$domain/cer.pem ;; (dane) [[ $# -eq 2 ]] || usage dane_${${(s:/:)2}[2]} < $2/cer.pem ;; (keypair) [[ $# -eq 2 ]] || usage key_get $2 print -- "$REPLY" cat $2/cer.pem ;; (rem) zmodload -F zsh/datetime b:strftime export LC_ALL=C for cer (**/cer.pem) { certtool --certificate-info < $cer | while read line ; do [[ $line =~ "^\s*Not After: .*" ]] && break done [[ $MATCH ]] # Not After: Sat Jul 02 10:02:29 UTC 2022 cols=(${=MATCH}) strftime -s ts_ugly -r "%b %d %H:%M:%S UTC %Y" ${(j: :)cols[4,-1]} strftime -s ts_good %F $ts_ugly print REM $ts_good +30 MSG $cer } ;; (list) print -C1 ee/*/*/*(/on) ;; (list-ca) print -C1 ca/*/*(/on) ;; (*) usage ;; esac