3 # Copyright (C) 2022-2023 Sergey Matveev <stargrave@stargrave.org>
7 KEY_ENCRYPT_RECIPIENT=${KEY_ENCRYPT_RECIPIENT:-12AD32689C660D426967FD75CB8205632107AD8A}
10 # Turn on PyGOST utilities
11 path=(~/local/stow/py310/bin ~/work/pygost/pygost/asn1schemas $path)
12 export -TU PYTHONPATH pythonpath
13 pythonpath=(~/work/pygost ~/work/pyderasn)
16 gpg --encrypt --recipient $KEY_ENCRYPT_RECIPIENT
23 # ------------------------ >8 ------------------------
28 \$ $ZSH_ARGZERO:t ca [ecdsa|gost|eddsa] NAME -- new CA keypair
29 \$ $ZSH_ARGZERO:t list-ca -- list CA keypairs
30 \$ $ZSH_ARGZERO:t list -- list EE ones
31 \$ $ZSH_ARGZERO:t rem -- list certificate expirations
32 \$ $ZSH_ARGZERO:t new KEY -- new EE
33 \$ $ZSH_ARGZERO:t renew KEY -- renew EE
34 \$ $ZSH_ARGZERO:t dane KEY -- show DANE SHA256 hash
35 \$ $ZSH_ARGZERO:t encrypt KEY -- encrypt private key
36 \$ $ZSH_ARGZERO:t keypair KEY -- PEM-encoded full keypair
41 zmodload -F zsh/files b:zf_mkdir
45 [[ -s $1/key.pem ]] &&
46 REPLY=`< ${1}/key.pem` ||
47 REPLY=`key_decrypt < ${1}/key.pem.enc`
51 certtool --generate-privkey ${=1} --no-text
60 trap "rm -f $key $tmpl $cert" HUP PIPE INT QUIT TERM EXIT
62 dn = "cn=$domain,c=$COUNTRY"
64 expiration_days = 3650
68 certtool_genkey "$keytype" > $key
70 --generate-self-signed \
74 reply=(${mapfile[$key]} ${mapfile[$cert]})
78 ca_new_xdsa "--key-type=ecdsa --bits 512" $1
82 certtool_genkey "--key-type=ecdsa --bits 256"
86 ca_new_xdsa "--key-type=ed25519" $1
90 certtool_genkey "--key-type=ed25519"
94 cert-selfsigned-example.py --cn does-not-matter --ai 256A --only-key
105 trap "rm -f $cakey $key $tmpl $cert" HUP PIPE INT QUIT TERM EXIT
107 mapfile[$cakey]=$REPLY
108 key_get ee/$algo/$ca/$domain
111 dn = "cn=$domain,c=RU"
112 expiration_days = 365
117 --load-ca-certificate ca/$algo/$ca/cer.pem \
118 --load-ca-privkey $cakey \
119 --generate-certificate \
120 --load-privkey $key \
125 ee_renew_xdsa ecdsa "$1" "$2"
129 ee_renew_xdsa eddsa "$1" "$2"
138 trap "rm -f $cakey $key $cert" HUP PIPE INT QUIT TERM EXIT
140 mapfile[$cakey]=$REPLY
141 cat >> $cakey < ca/gost/$ca/cer.pem
142 key_get ee/gost/$ca/$domain
144 cert-selfsigned-example.py \
145 --issue-with $cakey \
147 --cn $domain --country $COUNTRY --ai 256A
154 trap "rm -f $key $cert" HUP PIPE INT QUIT TERM EXIT
155 cert-selfsigned-example.py \
163 reply=(${mapfile[$key]} ${mapfile[$cert]})
167 certtool --key-id --hash=sha256
180 [[ $# -eq 3 ]] || usage
185 [[ -s $dst/key.pem ]] && {
186 print $dst/key.pem already exists >&2
189 ca_new_${algo} $domain
192 mapfile[${dst}/key.pem]=${reply[1]}
194 mapfile[${dst}/cer.pem]=${reply[2]}
198 [[ $# -eq 2 ]] || usage
201 print no $key found >&2
205 key_encrypt < $key > $key.enc
209 [[ $# -eq 2 ]] || usage
214 dst=ee/$algo/$ca/$domain
217 [[ -s $dst/key.pem ]] && {
218 print $dst/key.pem already exists >&2
223 ee_key_new_${algo} > $dst/key.pem
225 ee_renew_${algo} $ca $domain > $dst/cer.pem
228 [[ $# -eq 2 ]] || usage
233 ee_renew_${algo} $ca $domain > ee/$algo/$ca/$domain/cer.pem
236 [[ $# -eq 2 ]] || usage
237 dane_${${(s:/:)2}[2]} < $2/cer.pem
240 [[ $# -eq 2 ]] || usage
246 zmodload -F zsh/datetime b:strftime
248 for cer (**/cer.pem) {
249 certtool --certificate-info < $cer | while read line ; do
250 [[ $line =~ "^\s*Not After: .*" ]] && break
253 # Not After: Sat Jul 02 10:02:29 UTC 2022
255 strftime -s ts_ugly -r "%b %d %H:%M:%S UTC %Y" ${(j: :)cols[4,-1]}
256 strftime -s ts_good %F $ts_ugly
257 print REM $ts_good +30 MSG $cer
260 (list) print -C1 ee/*/*/*(/on) ;;
261 (list-ca) print -C1 ca/*/*(/on) ;;