From 34c79384d55c746aa64a795402218c2f08120947 Mon Sep 17 00:00:00 2001 From: gabrix73 Date: Wed, 3 Jun 2026 02:13:45 +0200 Subject: fix: use pinentry/zenity for YubiKey PIN prompt in non-interactive contexts Added yubisigner-with-pinentry wrapper that handles PIN entry via: - zenity (GUI popup, primary method) - pinentry-qt (Qt GUI fallback) - pinentry-curses (TUI fallback) - /dev/tty direct read (last resort) This fixes PIN prompt failing when vim-yubisigner is called from NeoMutt, where fmt.Scanln() in yubisigner-cli cannot capture stdin properly. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- scripts/vim-yubisigner | 4 +-- scripts/yubisigner-with-pinentry | 64 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100755 scripts/yubisigner-with-pinentry (limited to 'scripts') diff --git a/scripts/vim-yubisigner b/scripts/vim-yubisigner index 45d1c3d..ab8b14f 100755 --- a/scripts/vim-yubisigner +++ b/scripts/vim-yubisigner @@ -23,8 +23,8 @@ echo "Releasing YubiKey from gpg-agent..." gpgconf --kill gpg-agent 2>/dev/null || true sleep 1 -# Sign with yubisigner-cli (PIN will be prompted) -if ! "$HOME/bin/yubisigner-cli/yubisigner-cli" \ +# Sign with yubisigner-cli (PIN will be prompted via pinentry/zenity) +if ! "$HOME/bin/yubisigner-with-pinentry" \ --input "$FILE" \ --author "Gab Virebent" \ --email "gabriel1@virebent.art" \ diff --git a/scripts/yubisigner-with-pinentry b/scripts/yubisigner-with-pinentry new file mode 100755 index 0000000..bebd9af --- /dev/null +++ b/scripts/yubisigner-with-pinentry @@ -0,0 +1,64 @@ +#!/bin/bash +# Wrapper for yubisigner-cli that uses pinentry/zenity for PIN prompt +# This allows PIN entry to work from non-interactive contexts like NeoMutt + +set -euo pipefail + +# Release YubiKey from gpg-agent first +gpgconf --kill gpg-agent 2>/dev/null || true +sleep 0.5 + +# Try different PIN entry methods in order of preference +get_pin() { + local pin="" + + # Method 1: Try zenity (GUI, works best from NeoMutt) + if command -v zenity >/dev/null 2>&1; then + pin=$(zenity --password --title="YubiKey PIN" --text="Enter YubiKey PIN:" 2>/dev/null || true) + if [ -n "$pin" ]; then + echo "$pin" + return 0 + fi + fi + + # Method 2: Try pinentry-qt (GUI) + if command -v pinentry-qt >/dev/null 2>&1; then + pin=$(echo -e "SETDESC Enter YubiKey PIN\nSETPROMPT PIN:\nGETPIN\n" | pinentry-qt 2>/dev/null | grep "^D " | cut -d' ' -f2- || true) + if [ -n "$pin" ]; then + echo "$pin" + return 0 + fi + fi + + # Method 3: Try pinentry-curses (TUI, works in terminal) + if command -v pinentry-curses >/dev/null 2>&1 && [ -t 0 ]; then + pin=$(echo -e "SETDESC Enter YubiKey PIN\nSETPROMPT PIN:\nGETPIN\n" | pinentry-curses 2>/dev/null | grep "^D " | cut -d' ' -f2- || true) + if [ -n "$pin" ]; then + echo "$pin" + return 0 + fi + fi + + # Method 4: Fallback to /dev/tty direct read + if [ -e /dev/tty ]; then + echo "Enter YubiKey PIN: " >/dev/tty + read -s pin /dev/tty + if [ -n "$pin" ]; then + echo "$pin" + return 0 + fi + fi + + return 1 +} + +# Get PIN +PIN=$(get_pin) +if [ -z "$PIN" ]; then + echo "ERROR: Failed to get PIN" >&2 + exit 1 +fi + +# Call yubisigner-cli with PIN +exec "$HOME/bin/yubisigner-cli/yubisigner-cli" --pin "$PIN" "$@" -- cgit v1.2.3