Como usar a linha de comando gpg para verificar se a senha está correta

88

Estou tentando automatizar backups com duplicity, mas quando testo o resultado, recebo

gpg: falha na descriptografia da chave pública: senha incorreta

Quero verificar se a senha que estou usando é realmente a senha associada à chave secreta gpg correspondente, mas não consigo ver nas opções de linha de comando do gpg "Não criptografar ou descriptografar nada. Basta confirmar Estou usando a senha longa certa. "

Isso sugere que talvez eu esteja (mais uma vez) entendendo mal o Gnu Privacy Guard. (Tem predileção por me provocar até eu chorar.)

Faz sentido pedir ao gpg para verificar uma senha longa? Se sim, como?

Estranheza
fonte

Respostas:

114

Não existe um método embutido para fazer isso, mas é simples o suficiente para criar um teste que não modifica nada e permite que você apenas verifique sua senha.

Você não especificou, então assumirei que você está usando uma versão do GnuPG anterior à v2 e está no Linux com Bash como seu interpretador de linha de comando.

Eu darei o comando aqui e abaixo explicarei o que cada parte faz - (nota: o seguinte é para a série GnuPG versão 1, veja abaixo para a série GnuPG v2)

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

O que isso faz primeiro é enviar algum texto para assinar no GnuPG echo "1234" |- porque não queremos realmente assinar nada, isso é apenas um teste, então assinaremos algum texto inútil.

Em seguida, dizemos ao gpg para não usar o agente principal com --no-use-agent; isso é importante mais tarde porque, dependendo do seu agente principal, ele pode não retornar "0" em caso de sucesso, e isso é tudo o que queremos fazer - verificar o sucesso de sua senha.

Em seguida, dizemos ao gpg para colocar os dados assinados diretamente no /dev/nullarquivo, o que significa que os descartamos e não gravamos o resultado no terminal - NOTA: se você não estiver usando alguma variante do Linux / Unix, este arquivo pode não existir. No Windows, você pode apenas permitir que ele grave os dados assinados na tela, apenas omitindo a -o /dev/nullparte.

Em seguida, especificamos a chave com a qual queremos fazer nosso teste usando --local-user 012345. Você pode usar o KeyID para especificidade máxima ou usar um nome de usuário, o que melhor se adequar às suas necessidades.

Em seguida, especificamos -as, o que ativa o modo de saída ascii e define o modo de contexto para assinatura. Em -seguida, apenas diz ao GnuPG para obter os dados a serem assinados do padrão-in, que é a primeira parte do comando que demos echo "1234" |.

E por último, temos && echo "A message that indicates success"- o "&&" significa, se o comando anterior foi bem-sucedido, imprima esta mensagem. Isso é apenas adicionado para maior clareza, porque o sucesso do comando acima seria indicado por nenhuma saída.

Espero que esteja claro o suficiente para você entender o que está acontecendo e como você pode usar isso para fazer os testes que deseja fazer. Se alguma parte não estiver clara ou você não entender, terei o maior prazer em esclarecer. Boa sorte!

[EDITAR] - Se você estiver usando GnuPG v2, o comando acima precisará ser ligeiramente modificado, assim:

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

O motivo é que o GnuPG v2 espera que a senha seja recuperada por meio de um agente, portanto, não podemos desabilitar o uso do agente com --no-use-agente ter o efeito desejado; em vez disso, precisamos dizer ao GnuPG v2 que queremos executar um processo em "lote" e recuperar a frase-senha de STDIN (entrada padrão) usando a opção --passphrase-fd 1.

Kylehuff
fonte
11
Isso não funciona com o gpg2, pois sempre requer um agente. Além disso, o agente ncurses de alguma forma fica confuso com a entrada canalizada. Então, eu apenas usei gpg --local-user <KEYID> -as. Isso apenas permite que o agente solicite a frase secreta e diga se ela estava correta (então não faz nada).
BubuIIC de
1
Você está correto, BubullC, na maior parte; com uma pequena modificação nas opções passadas, você pode ter um resultado semelhante usando gpg2. Modifiquei minha resposta para oferecer suporte às diferenças entre gpg e gpg2.
kylehuff
4
Tente isto para GnuPG 2.1:gpg -o /dev/null --local-user <KEYID> -as <(echo 1234) && echo "The correct passphrase was entered for this key"
starfry
6
Para mim no MacOS 10.12.6, nenhuma das variações solicita uma frase-senha e retorna uma mensagem de sucesso independentemente.
Stan James
1
--passphrase-fd 1? ler do stdout? Isso funciona para mim: gpg2 -aso - <(echo 1234); echo $?. Use echo RELOADAGENT | gpg-connect-agentpara esquecer frases secretas.
x-yuri
20

Esta é uma linha de comando mais curta para verificar se a senha longa está OK:

gpg --export-secret-keys -a <KEYID> > /dev/null && echo OK
Hóspede
fonte
3

Para mim, a maneira simplista de verificar a senha longa é usar uma gpg --passwdabreviação. Ele tenta alterar a frase-senha e o passo é confirmar a frase-senha antiga, e então você pode clicar em 'cancelar' no prompt da nova frase-senha e isso mantém a frase-senha intacta.

gpg --passwd <your-user-id>
Lei Zhao
fonte
2

Aviso, não use eco gpg -o /dev/nullcomo sugerido pela resposta principal aqui. Isso fará com que / dev / null tenha permissão inválida e corrompa o /dev/nullarquivo. Você pode verificar a permissão do arquivo / dev / null ao executar este comando para provar isso.

Você pode usar isto:

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

Eu também criei um script bash para isso (este está trabalhando com o Centos 8). Este script pedirá uma frase-senha; se for inválida, continuará solicitando a entrada de uma frase-senha válida. Além disso, se você inserir KEY_ID incorreto ou não existente como um argumento, ele também pode validar isso:

#!/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

Exemplo de saída se nenhuma senha for armazenada em cache no 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:

Exemplo de saída se uma senha inválida for inserida (continuará perguntando):

[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:

Exemplo de saída se a senha longa for inserida:

[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

Quando uma frase-senha válida é armazenada em cache, na próxima vez que você executar este script, ele não pedirá que você insira a frase-senha. Portanto, este script fornece a solução para sua pergunta; "Apenas confirme que estou usando a senha longa certa"

MaXi32
fonte