From 468c5311d32df4dfc3755f6f9904930d1481baab Mon Sep 17 00:00:00 2001 From: Luca Bilke Date: Thu, 27 Jun 2024 18:45:08 +0200 Subject: [PATCH] git: stupid hack to enable signing key fallbacks --- .config/git/config | 7 ++-- .config/git/gpg-fallback-keys | 66 +++++++++++++++++++++++++++++++++++ .config/zsh/.zprofile | 1 + 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100755 .config/git/gpg-fallback-keys diff --git a/.config/git/config b/.config/git/config index 6b7b1967c..c7f93697d 100644 --- a/.config/git/config +++ b/.config/git/config @@ -1,3 +1,4 @@ +# vim: set ft=gitconfig: [init] defaultBranch = main [push] @@ -11,10 +12,12 @@ helper = store [commit] gpgsign = true +[tag] + gpgsign = true +[gpg] + program = /home/luca/.config/git/gpg-fallback-keys [include] path = ~/.config/git/host -[includeIf "gitdir:~/Documents/code/tralios/"] - path = ~/.config/git/tralios [filter "lfs"] clean = git-lfs clean -- %f smudge = git-lfs smudge -- %f diff --git a/.config/git/gpg-fallback-keys b/.config/git/gpg-fallback-keys new file mode 100755 index 000000000..d8c29e680 --- /dev/null +++ b/.config/git/gpg-fallback-keys @@ -0,0 +1,66 @@ +#!/bin/bash + +# This is a small wrapper script for gpg intended to be used by git +# As far as I can tell, git cannot automatically pick a fallback signing key by itself +# Setting GIT_SIGN_FALLBACK_KEY_IDS="config" or leaving it unset will make the program try all keys listed by git config +# Setting GIT_SIGN_FALLBACK_KEY_IDS="all" will make the program try all keys listed by gpg +# Setting the fallback keys manually can be done like this: GIT_SIGN_FALLBACK_KEY_IDS=" " +# This script was written in about two hours, if you find any bugs, tell Luca! + +set -eu + +# A quick and dirty array filtering function +function reject { + predicate=$1 + shift + + for el in "$@"; do + if ! eval ":() { [[ $predicate ]]; }; : '$el'"; then + echo "$el" + fi + done +} + +case "$*" in + # Git is trying to sign a commit + *-bsau*) + # The key passed by git + primary_key=$(echo "$*" | grep -oP '(?<=-bsau )[A-Z0-9]{16}') + + # Select fallback keys based on config + case "${GIT_SIGN_FALLBACK_KEY_IDS:-}" in + "" | "config") + mapfile -t signing_keys < <(git config --get-all user.signingKey) + mapfile -t fallback_keys < <(reject "\$1 == $primary_key" "${signing_keys[@]}") + ;; + "all") + mapfile -t signing_keys < <(gpg --list-keys --with-colons | awk -F: '/^pub:/ {print $5}') + mapfile -t fallback_keys < <(reject "\$1 == $primary_key" "${signing_keys[@]}") + ;; + *) + mapfile -t fallback_keys < <(echo "$GIT_SIGN_FALLBACK_KEY_IDS" | xargs -n 1) + ;; + esac + + # Number of signing keys + n_keys=$(($(echo "${fallback_keys[*]}" | wc -w) + 1)) + + # Unaccounted for gpg flags + mapfile -t extra_flags < <(reject "\$1 == -bsau || \$1 == --status-fd=2 || \$1 == $primary_key" "$@") + gpg_flags=("${extra_flags[@]}" --status-fd=2 -bsau) + + # Try signing with the primary key first, then try the fallback keys + counter=0 + try_key=$primary_key + while + [ "$counter" -lt "$n_keys" ] && + ! gpg "${gpg_flags[@]}" "$try_key" + do + try_key="${fallback_keys[$counter - 1]}" + counter=$((counter + 1)) + done + ;; + + # Git is trying to do something else, so we just pass the flags through + *) gpg "$@" ;; +esac diff --git a/.config/zsh/.zprofile b/.config/zsh/.zprofile index 3842e0946..14ae02c7a 100644 --- a/.config/zsh/.zprofile +++ b/.config/zsh/.zprofile @@ -120,6 +120,7 @@ export XBPS_DISTDIR="$XDG_DOCUMENTS_DIR/dev/server/void-packages" export ZK_NOTEBOOK_DIR="$XDG_DOCUMENTS_DIR/notes" export ZSH_COMPDUMP="$XDG_CACHE_HOME/zcompdump" export _JAVA_OPTIONS="-Djava.util.prefs.userRoot=$XDG_CONFIG_HOME/java" +export GIT_SIGN_FALLBACK_KEY_IDS="config" localpath="" export PATH="$PATH:$localpath"