Jak używać wiersza poleceń gpg, aby sprawdzić, czy hasło jest poprawne

88

Próbuję zautomatyzować tworzenie kopii zapasowych za pomocą duplicity, ale kiedy testuję wynik, otrzymuję

gpg: odszyfrowanie klucza publicznego nie powiodło się: złe hasło

Chcę sprawdzić, czy hasło, którego używam, jest w rzeczywistości hasłem skojarzonym z odpowiednim tajnym kluczem gpg, ale i tak nie widzę w opcjach wiersza poleceń gpg, aby powiedzieć „Nie szyfruj ani nie odszyfruj niczego. Po prostu potwierdź Używam właściwego hasła ”.

To sugeruje, że być może (jeszcze raz) nie rozumiem Gnu Privacy Guard. (Ma skłonność do wyszydzania mnie do płaczu.)

Czy ma sens poproszenie gpg o zweryfikowanie hasła? Jeśli tak to jak?

Dziwne
źródło

Odpowiedzi:

114

Nie ma wbudowanej metody, aby to zrobić, ale wystarczy utworzyć test, który niczego nie modyfikuje i pozwala po prostu sprawdzić hasło.

Nie określiłeś, więc zakładam, że używasz wersji GnuPG mniejszej niż v2 i używasz Linuksa z Bash jako interpreter wiersza poleceń.

Podam polecenie tutaj, a poniżej wyjaśnię, co robi każda część - (uwaga: poniższe dotyczy wersji 1 serii GnuPG, poniżej wersja 2 serii GnuPG)

echo "1234" | gpg --no-use-agent -o /dev/null --local-user <KEYID> -as - && echo "The correct passphrase was entered for this key"

Po pierwsze, potokuj jakiś tekst do podpisania do GnuPG echo "1234" |- ponieważ tak naprawdę nie chcemy niczego podpisywać, to tylko test, więc podpiszemy jakiś bezużyteczny tekst.

Następnie mówimy gpg, aby nie używał agenta kluczowego z --no-use-agent; jest to ważne później, ponieważ w zależności od Twojego głównego agenta, po pomyślnym zakończeniu może nie zwracać „0”, a to wszystko, co chcemy zrobić - zweryfikować powodzenie hasła.

Następnie mówimy gpg, aby umieścił podpisane dane bezpośrednio w /dev/nullpliku, co oznacza, że ​​odrzucamy je i nie zapisujemy wyniku na terminalu - UWAGA: jeśli nie używasz jakiegoś wariantu Linux / Unix, ten plik może nie istnieć. W systemie Windows może być konieczne zezwolenie na zapisanie podpisanych danych na ekranie, po prostu pomijając rozszerzenie-o /dev/null część.

Następnie określamy klucz, z którym chcemy wykonać nasz test, używając --local-user 012345. Możesz użyć KeyID w celu uzyskania maksymalnej precyzji lub użyć nazwy użytkownika, w zależności od tego, która najlepiej odpowiada Twoim potrzebom.

Następnie określamy -as, co włącza tryb wyjścia ascii i ustawia tryb kontekstu dla podpisywania. Następnie -po prostu mówi GnuPG, aby pobierał dane do podpisania ze standardowego wejścia, co jest pierwszą częścią polecenia, które wydaliśmy echo "1234" |.

I na koniec mamy && echo "A message that indicates success" - „&&” oznacza, że ​​jeśli poprzednie polecenie się powiodło, wydrukuj tę wiadomość. Zostało to dodane tylko dla przejrzystości, ponieważ w przeciwnym razie powodzenie powyższego polecenia byłoby sygnalizowane brakiem danych wyjściowych.

Mam nadzieję, że jest to wystarczająco jasne, abyś zrozumiał, co się dzieje i jak możesz go wykorzystać, wykonując testy, które chcesz przeprowadzić. Jeśli jakakolwiek część jest niejasna lub nie rozumiesz, z przyjemnością wyjaśnię. Powodzenia!

[EDYTUJ] - Jeśli używasz GnuPG v2, powyższe polecenie będzie wymagało niewielkiej modyfikacji, na przykład:

echo "1234" | gpg2 --batch --passphrase-fd 1 -o /dev/null --local-user <KEYID> -as - && echo "The correct passphrase was entered for this key"

Powodem jest to, że GnuPG v2 oczekuje, że hasło zostanie pobrane przez agenta, więc nie możemy wyłączyć używania agenta z --no-use-agentpożądanym skutkiem; zamiast tego musimy powiedzieć GnuPG v2, że chcemy uruchomić proces „wsadowy” i pobrać hasło ze STDIN (standard in) przy użyciu opcji --passphrase-fd 1.

kylehuff
źródło
11
To nie działa z gpg2, ponieważ zawsze wymagało agenta. Również agent ncurses jest w jakiś sposób zdezorientowany przez dane wejściowe z potoku. Więc po prostu użyłem gpg --local-user <KEYID> -as. To po prostu pozwala agentowi poprosić o hasło i powie Ci, czy było poprawne (wtedy nic nie robi).
BubuIIC
1
W większości masz rację BubullC; z niewielką modyfikacją przekazanych opcji możesz uzyskać podobny wynik używając gpg2. Zmodyfikowałem odpowiedź, aby obsługiwała różnice między gpg i gpg2.
kylehuff
4
Wypróbuj to dla GnuPG 2.1:gpg -o /dev/null --local-user <KEYID> -as <(echo 1234) && echo "The correct passphrase was entered for this key"
starfry
6
U mnie w systemie MacOS 10.12.6 żadna z odmian nie monituje o podanie hasła i mimo to zwraca komunikat o powodzeniu.
Stan James
1
--passphrase-fd 1? czytać ze standardowego wyjścia? Działa to dla mnie gpg2 -aso - <(echo 1234); echo $?. Służy echo RELOADAGENT | gpg-connect-agentdo zapominania haseł.
x-yuri
20

To jest krótsza linia poleceń, aby sprawdzić, czy hasło jest prawidłowe:

gpg --export-secret-keys -a <KEYID> > /dev/null && echo OK
Gość
źródło
3

Dla mnie prostym sposobem sprawdzenia hasła jest użycie gpg --passwdskrótu. Próbuje zmienić hasło, a krok polega na potwierdzeniu starego hasła, a następnie możesz kliknąć „anuluj” w monicie o nowe hasło, dzięki czemu hasło pozostanie nienaruszone.

gpg --passwd <your-user-id>
Lei Zhao
źródło
2

Ostrzeżenie nie używaj echa, gpg -o /dev/nulljak sugeruje tutaj najlepsza odpowiedź. Spowoduje to, że / dev / null będzie miał nieprawidłowe uprawnienia i uszkodzi /dev/nullplik. Możesz sprawdzić uprawnienia do pliku / dev / null podczas uruchamiania tego polecenia, aby to udowodnić.

Możesz użyć tego:

echo "1234" | gpg -q --batch --status-fd 1 --sign --local-user $KEY_ID --passphrase-fd 0 > /dev/null

Stworzyłem również skrypt bash do tego (ten działa z Centos 8). Ten skrypt zapyta o hasło, jeśli jest nieprawidłowe, będzie nadal prosić o wprowadzenie prawidłowego hasła. Również jeśli podasz błędny lub nieistniejący KEY_ID jako argument, może to również potwierdzić:

#!/bin/bash
# usage ./gpgcron KEYID   | ./gpgcron 2B705B8B6FA943B1
script_path=$(dirname $(realpath -s $0))
script_name=$(basename -- "$0")
GPG_CACHE_BIN="/usr/libexec/gpg-preset-passphrase"
KEY_ID=$1
KEY_GRIP=$(gpg --with-keygrip --list-secret-keys $KEY_ID | grep -Pom1 '^ *Keygrip += +\K.*')
RETVAL=$?
if [[ $RETVAL -ne 0 || -z $KEY_ID ]]; then
    echo "Please provide correct KEY_ID. Example ./$script_name KEY_ID"
    exit 1
fi

export GPG_TTY=$(tty)

function set_gpg_cachepass {
    read -s -p "[$script_name | input]: Enter passphrase to cache into gpg-agent: " PASSPHRASE; echo
    $GPG_CACHE_BIN -c $KEY_GRIP <<< $PASSPHRASE
    RETVAL=$?
    echo "[$script_name | info ]: gpg-preset-passphrase return code: [$RETVAL]"
    if [ $RETVAL = 0 ]; then
        echo "[$script_name | info ]: A passphrase has been set and cached in gpg-agent"
        echo "[$script_name | info ]: Paraphrase set return code: [$RETVAL]"
        gpg_validatepass
    else
        echo "[$script_name | info ]: Unsuccessful error occured: [$RETVAL]"
        set_gpg_cachepass
    fi
}

function gpg_validatepass {
    echo "[$script_name | info ]: Validating passphrase cached in gpg-agent ..."
    echo "1234" | gpg -q --batch --status-fd 1 --sign --local-user $KEY_ID --passphrase-fd 0 > /dev/null
    RETVAL=$?
    if [ $RETVAL = 0 ]; then
        echo "[$script_name | info ]: OK, valid passphrase has been cached in gpg-agent"
    else
        echo "[$script_name | info ]: Warning, invalid passphrase or no passphrase is cached in gpg-agent"
        set_gpg_cachepass
    fi
}

RES=$(echo "KEYINFO --no-ask $KEY_GRIP Err Pmt Des" | gpg-connect-agent | awk '{ print $7 }')
if [ "$RES" == "1" ]; then
    echo "[$script_name | info ]: OK, passphrase is already cached in gpg agent for KEY_ID of [$KEY_ID]"
    gpg_validatepass
else
    echo "[$script_name | info ]: Warning, no passphrase is cached in gpg agent for KEY_ID of [$KEY_ID]"
    set_gpg_cachepass
fi

Przykładowe dane wyjściowe, jeśli żadne hasło nie jest buforowane w gpg-agent:

[root@earth gpg]# ./gpgcron 2B705B8B6FA943B2
[gpgcron | info ]: Warning, no passphrase is cached in gpg agent for KEY_ID of [2B705B8B6FA943B2]
[gpgcron | input]: Enter passphrase to cache into gpg-agent:

Przykładowe dane wyjściowe, jeśli wprowadzono nieprawidłowe hasło (będzie nadal pytać):

[root@earth gpg]# ./gpgcron 2B705B8B6FA943B2
[gpgcron | info ]: OK, passphrase is already cached in gpg agent for KEY_ID of [2B705B8B6FA943B2]
[gpgcron | info ]: Validating passphrase cached in gpg-agent ...
gpg: signing failed: Bad passphrase
gpg: signing failed: Bad passphrase
[gpgcron | info ]: Warning, invalid passphrase or no passphrase is cached in gpg-agent
[gpgcron | input]: Enter passphrase to cache into gpg-agent:

Przykładowe dane wyjściowe, jeśli wprowadzono prawidłowe hasło:

[gpgcron | input]: Enter passphrase to cache into gpg-agent:
[gpgcron | info ]: gpg-preset-passphrase return code: [0]
[gpgcron | info ]: A passphrase has been set and cached in gpg-agent
[gpgcron | info ]: Paraphrase set return code: [0]
[gpgcron | info ]: Validating passphrase cached in gpg-agent ...
[gpgcron | info ]: OK, valid passphrase has been cached in gpg-agent

Gdy prawidłowe hasło jest zapisywane w pamięci podręcznej, przy następnym uruchomieniu tego skryptu nie zostanie wyświetlony monit o wprowadzenie hasła. Więc ten skrypt daje odpowiedź na twoje pytanie; „Potwierdź, że używam prawidłowego hasła”

MaXi32
źródło