penguin/utils

my env utils

bash/tools/sign-rbashrc.sh

raw ยท 2680 bytes

#!/usr/bin/env bash
set -euo pipefail

cd "$(dirname "${BASH_SOURCE[0]}")/../.."

DIST="bash/dist"
TARGET="$DIST/rbashrc"
SIG="$DIST/rbashrc.asc"
PUBKEY="$DIST/rbash-signing-key.asc"

KEY_NAME_DEFAULT="rbash release signing"
KEY_EMAIL_DEFAULT="rbash@astropenguin.net"
KEY_COMMENT_DEFAULT="rbash release signing key"

die() {
	echo "error: $*" >&2
	exit 1
}

need() {
	command -v "$1" >/dev/null 2>&1 || die "$1 is required"
}

prompt() {
	local var_name="$1"
	local label="$2"
	local default_value="${3:-}"
	local value

	if [ -n "$default_value" ]; then
		read -r -p "$label [$default_value]: " value
		value="${value:-$default_value}"
	else
		read -r -p "$label: " value
	fi

	printf -v "$var_name" '%s' "$value"
}

gpg_key_exists() {
	local email="$1"

	gpg --list-secret-keys --with-colons "$email" 2>/dev/null |
		awk -F: '$1 == "sec" { found = 1 } END { exit !found }'
}

gpg_key_fpr() {
	local email="$1"

	gpg --list-secret-keys --with-colons --fingerprint "$email" |
		awk -F: '$1 == "fpr" { print $10; exit }'
}

create_key() {
	local name email comment expire batch_file

	echo "No rbash signing key found."
	echo

	prompt name "Name" "$KEY_NAME_DEFAULT"
	prompt email "Email" "$KEY_EMAIL_DEFAULT"
	prompt comment "Comment" "$KEY_COMMENT_DEFAULT"
	prompt expire "Expire-Date, e.g. 2y, 5y, 0 for never" "5y"

	[ -n "$name" ] || die "name is required"
	[ -n "$email" ] || die "email is required"

	batch_file="$(mktemp)"
	trap 'rm -f "$batch_file"' RETURN

	cat > "$batch_file" <<EOF
%ask-passphrase
Key-Type: eddsa
Key-Curve: ed25519
Key-Usage: sign
Name-Real: $name
Name-Email: $email
Name-Comment: $comment
Expire-Date: $expire
%commit
EOF

	echo
	echo "Creating GPG signing key..."
	gpg --batch --generate-key "$batch_file"

	echo "$email"
}

pick_or_create_key() {
	local configured_email

	configured_email="${RBASH_SIGNING_KEY_EMAIL:-$KEY_EMAIL_DEFAULT}"

	if gpg_key_exists "$configured_email"; then
		echo "$configured_email"
		return 0
	fi

	create_key
}

main() {
	local key_email fpr

	need gpg
	[ -f "$TARGET" ] || die "$TARGET does not exist"

	key_email="$(pick_or_create_key)"
	fpr="$(gpg_key_fpr "$key_email")"

	[ -n "$fpr" ] || die "failed to resolve signing key fingerprint"

	echo "Signing key:"
	echo "  email:       $key_email"
	echo "  fingerprint: $fpr"
	echo

	echo "Signing $TARGET -> $SIG"
	gpg \
		--batch \
		--yes \
		--armor \
		--detach-sign \
		--local-user "$fpr" \
		--output "$SIG" \
		"$TARGET"

	echo "Exporting public key -> $PUBKEY"
	gpg \
		--batch \
		--yes \
		--armor \
		--export "$fpr" > "$PUBKEY"

	echo
	echo "Done."
	echo
	echo "Add/pin this fingerprint in rbashrc:"
	echo
	echo "RBASH_SIGNING_FPR=\"$fpr\""
}

main "$@"