]> Sergey Matveev's repositories - zeasypki.git/blobdiff - zeasypki
Style fixes
[zeasypki.git] / zeasypki
index ba520905c6d8429cf22428f2e5683e70b74ef3ae..230acf7ed796c01b710a73ddd8fba1977d711063 100755 (executable)
--- a/zeasypki
+++ b/zeasypki
@@ -1,42 +1,39 @@
 #!/usr/bin/env zsh
 # zeasypki -- easy PKI
-# Copyright (C) 2022 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2022-2024 Sergey Matveev <stargrave@stargrave.org>
 
-set -e
+setopt ERR_EXIT PIPE_FAIL
 
-CERTTOOL=${CERTTOOL:-certtool}
-GPG=${GPG:-gpg}
-KEY_ENCRYPT_RECIPIENT=${KEY_ENCRYPT_RECIPIENT:-CF60E89A59231E76E2636422AE1A8109E49857EF}
 COUNTRY=${COUNTRY:-RU}
 
-goston() {
-    path=(~/local/stow/py310/bin ~/work/pygost/pygost/asn1schemas $path)
-    export -TU PYTHONPATH pythonpath
-    pythonpath=(~/work/pygost ~/work/pyderasn)
-}
+path=(
+    ~/work/gogost/cmd/cer-selfsigned-example
+    ~/work/gogost/cmd/cer-dane-hash
+    $path
+)
 
 key_encrypt() {
-    ${=GPG} --encrypt --recipient $KEY_ENCRYPT_RECIPIENT
+    age -R ~/.age/general.pub
 }
 
 key_decrypt() {
-    ${=GPG} --decrypt
+    age -d -i ~/.age/general.age
 }
 
 # ------------------------ >8 ------------------------
 
 usage() {
-    >&2 <<EOF
+    cat >&2 <<EOF
 Usage:
-  \$ $0:t ca [ecdsa|gost] NAME -- new CA keypair
-  \$ $0:t list-ca              -- list CA keypairs
-  \$ $0:t list                 -- list EE ones
-  \$ $0:t rem                  -- list certificate expirations
-  \$ $0:t new KEY              -- new EE
-  \$ $0:t renew KEY            -- renew EE
-  \$ $0:t dane KEY             -- show DANE SHA256 hash
-  \$ $0:t encrypt KEY          -- encrypt private key
-  \$ $0:t keypair KEY          -- PEM-encoded full keypair
+  \$ $ZSH_ARGZERO:t ca [ecdsa|gost|eddsa] NAME -- new CA keypair
+  \$ $ZSH_ARGZERO:t list-ca                    -- list CA keypairs
+  \$ $ZSH_ARGZERO:t list                       -- list EE ones
+  \$ $ZSH_ARGZERO:t rem                        -- list certificate expirations
+  \$ $ZSH_ARGZERO:t new KEY                    -- new EE
+  \$ $ZSH_ARGZERO:t renew KEY                  -- renew EE
+  \$ $ZSH_ARGZERO:t dane KEY                   -- show DANE SHA256 hash
+  \$ $ZSH_ARGZERO:t encrypt KEY                -- encrypt private key
+  \$ $ZSH_ARGZERO:t keypair KEY                -- PEM-encoded full keypair
 EOF
     exit 1
 }
@@ -45,31 +42,32 @@ zmodload -F zsh/files b:zf_mkdir
 zmodload zsh/mapfile
 
 key_get() {
-    [[ -s $1/key.pem ]] &&
-        REPLY=`< ${1}/key.pem` ||
+    if [[ -s $1/key.pem ]] ; then
+        REPLY=`< ${1}/key.pem`
+    else
         REPLY=`key_decrypt < ${1}/key.pem.enc`
+    fi
 }
 
 certtool_genkey() {
-    local bits=$1
-    ${=CERTTOOL} --generate-privkey --ecc --bits $bits --no-text
+    certtool --generate-privkey ${=1} --no-text
 }
 
-ca_new_ecdsa() {
-    local domain=$1
+ca_new_xdsa() {
+    local keytype=$1
+    local domain=$2
     local key=`mktemp`
     local tmpl=`mktemp`
     local cert=`mktemp`
     trap "rm -f $key $tmpl $cert" HUP PIPE INT QUIT TERM EXIT
-    > $tmpl <<EOF
+    cat > $tmpl <<EOF
 dn = "cn=$domain,c=$COUNTRY"
-serial = 1
 expiration_days = 3650
 ca
 cert_signing_key
 EOF
-    certtool_genkey 512 > $key
-    ${=CERTTOOL} \
+    certtool_genkey "$keytype" > $key
+    certtool \
         --generate-self-signed \
         --load-privkey $key \
         --template $tmpl \
@@ -77,99 +75,120 @@ EOF
     reply=(${mapfile[$key]} ${mapfile[$cert]})
 }
 
+ca_new_ecdsa() {
+    ca_new_xdsa "--key-type=ecdsa --bits 512" $1
+}
+
 ee_key_new_ecdsa() {
-    certtool_genkey 256
+    certtool_genkey "--key-type=ecdsa --bits 256"
+}
+
+ca_new_eddsa() {
+    ca_new_xdsa "--key-type=ed25519" $1
+}
+
+ee_key_new_eddsa() {
+    certtool_genkey "--key-type=ed25519"
 }
 
 ee_key_new_gost() {
-    goston
-    cert-selfsigned-example.py --cn does-not-matter --ai 256A --only-key
+    cer-selfsigned-example -cn does-not-matter -ai 256A -only-key
 }
 
-ee_renew_ecdsa() {
-    local ca=$1
-    local domain=$2
+ee_renew_xdsa() {
+    local algo=$1
+    local ca=$2
+    local domain=$3
     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
+    key_get ca/$algo/$ca
     mapfile[$cakey]=$REPLY
-    key_get ee/ecdsa/$ca/$domain
+    key_get ee/$algo/$ca/$domain
     mapfile[$key]=$REPLY
-    > $tmpl <<EOF
+    cat > $tmpl <<EOF
 dn = "cn=$domain,c=RU"
 expiration_days = 365
 signing_key
 dns_name = "$domain"
 EOF
-    ${=CERTTOOL} \
-        --load-ca-certificate ca/ecdsa/$ca/cer.pem \
+    certtool \
+        --load-ca-certificate ca/$algo/$ca/cer.pem \
         --load-ca-privkey $cakey \
         --generate-certificate \
         --load-privkey $key \
         --template $tmpl
 }
 
+ee_renew_ecdsa() {
+    ee_renew_xdsa ecdsa "$1" "$2"
+}
+
+ee_renew_eddsa() {
+    ee_renew_xdsa eddsa "$1" "$2"
+}
+
 ee_renew_gost() {
     local ca=$1
     local domain=$2
-    goston
     local cakey=`mktemp`
     local key=`mktemp`
     local cert=`mktemp`
     trap "rm -f $cakey $key $cert" HUP PIPE INT QUIT TERM EXIT
     key_get ca/gost/$ca
     mapfile[$cakey]=$REPLY
-    >> $cakey < ca/gost/$ca/cer.pem
+    print >> $cakey
+    cat >> $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
+    cer-selfsigned-example \
+        -issue-with $cakey \
+        -reuse-key $key \
+        -cn $domain -country $COUNTRY -ai 256A
 }
 
 ca_new_gost() {
     local domain=$1
-    goston
     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
+    cer-selfsigned-example \
+        -ca \
+        -cn $domain \
+        -country $COUNTRY \
+        -ai 512C \
+        -out-key $key \
+        -out-cert $cert
     reply=(${mapfile[$key]} ${mapfile[$cert]})
 }
 
 dane_ecdsa() {
-    ${=CERTTOOL} --key-id --hash=sha256
+    certtool --key-id --hash=sha256
+}
+
+dane_eddsa() {
+    dane_ecdsa
 }
 
 dane_gost() {
-    goston
-    cert-dane-hash.py
+    cer-dane-hash
 }
 
 case $1 in
 (ca)
     [[ $# -eq 3 ]] || usage
-    local algo=$2
-    local domain=$3
-    local dst=ca/$algo/$domain
+    algo=$2
+    domain=$3
+    dst=ca/$algo/$domain
     zf_mkdir -p $dst
-    [[ -s $dst/key.pem ]] && {
+    [[ ! -s $dst/key.pem ]] || {
         print $dst/key.pem already exists >&2
         exit 1
     }
     ca_new_${algo} $domain
-    local _umask=`umask`
+    _umask=`umask`
     umask 077
     mapfile[${dst}/key.pem]=${reply[1]}
     umask $_umask
@@ -178,7 +197,7 @@ case $1 in
     ;;
 (encrypt)
     [[ $# -eq 2 ]] || usage
-    local key=$2/key.pem
+    key=$2/key.pem
     [[ -s $key ]] || {
         print no $key found >&2
         exit 1
@@ -189,18 +208,18 @@ case $1 in
     ;;
 (new)
     [[ $# -eq 2 ]] || usage
-    local cols=(${(s:/:)2})
-    local algo=${cols[2]}
-    local ca=${cols[3]}
-    local domain=${cols[4]}
-    local dst=ee/$algo/$ca/$domain
+    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 ]] && {
+    [[ ! -s $dst/key.pem ]] || {
         print $dst/key.pem already exists >&2
         exit 1
     }
-    local _umask=`umask`
+    _umask=`umask`
     umask 077
     ee_key_new_${algo} > $dst/key.pem
     umask $_umask
@@ -208,10 +227,10 @@ case $1 in
     ;;
 (renew)
     [[ $# -eq 2 ]] || usage
-    local cols=(${(s:/:)2})
-    local algo=${cols[2]}
-    local ca=${cols[3]}
-    local domain=${cols[4]}
+    cols=(${(s:/:)2})
+    algo=${cols[2]}
+    ca=${cols[3]}
+    domain=${cols[4]}
     ee_renew_${algo} $ca $domain > ee/$algo/$ca/$domain/cer.pem
     ;;
 (dane)
@@ -225,13 +244,18 @@ case $1 in
     cat $2/cer.pem
     ;;
 (rem)
-    setopt GLOB_STAR_SHORT
+    zmodload -F zsh/datetime b:strftime
     export LC_ALL=C
     for cer (**/cer.pem) {
-        date_bad_format=`certtool -i < $cer |
-        perl -ne '/Not After: \w+ (\w+ \d+ \d+:\d+):\d+ UTC (\d+)/ && print "$1 $2"'`
-        date_good_format=`date -j -f "%b %d %H:%M %Y" "$date_bad_format" +"%Y-%m-%d"`
-        print REM $date_good_format +30 MSG $cer
+        certtool --certificate-info < $cer | while read line ; do
+            [[ ! $line =~ "^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) ;;