Eu venho usando uma YubiKey como chave de autenticação em 2 fatores e para assinar meus commits do Git. Até alguns dias atrás eu usava uma YubiKey 4. Como meu computador atual não tem nenhuma porta USB-A, faz mais de um ano que eu ando com adaptadores de USB-A para USB-C na mochila, e usar a chave tem sido um incômodo. Por isso decidi que era hora de migrar para a minha YubiKey 5C “nova” e ficar livre de ter que carregar esses adaptadores.
Na verdade, eu já tinha a chave há um tempo: comprei junto com uma YubiKey 4 de reposição, que precisei por causa do problema do TPM da Infineon identificado por eles. Mas só agora decidi que era hora de migrar para a chave nova.
O outro motivo para fazer isso agora é que minhas chaves GPG antigas expiraram e eu precisei reemiti-las, então posso aproveitar para usar a chave para assinar meus commits do Git.
A loucura do GPG
Se você já lidou com chaves GPG no passado (ou lida atualmente), sabe que pode ser bem difícil colocá-las para funcionar de forma correta e segura se você nunca fez isso antes. Manter as chaves mestras offline, trocar chaves públicas de um lado para o outro, reemitir chaves depois que expiram, possivelmente assiná-las com chaves anteriores para verificá-las, revogar chaves… Não é fácil seguir as boas práticas nem na teoria. Na prática, as coisas ficam extremamente complicadas.
A maioria dos tutoriais online manda usar a linha de comando para gerar as chaves, navegando por menus com um padrão de design nada comum, e é uma dor de cabeça geral para fazer tudo funcionar. A maioria deles diz para usar uma máquina offline, como um Raspberry PI, e/ou gerar as chaves mestras e subchaves offline e manter a chave mestra fora do seu computador.
🤯
Eu lido com isso todo começo de janeiro há quase 4 anos. Eu morro de medo do momento em que aparece o erro a seguir, avisando que minhas chaves de assinatura expiraram.
error: gpg failed to sign the data
fatal: failed to write commit objectEste ano decidi que era hora de tentar deixar esse processo muito mais fácil, usando a geração de certificados embutida na própria chave e evitando todo o trabalho de gerar chaves GPG e afins.
Geração de chaves direto na YubiKey
Ainda vamos ter que usar a interface de linha de comando, mas é um pouco mais óbvio, já que tem menos etapas.
Primeiro precisamos configurar nosso cartão/dispositivo.
Configuração do cartão/dispositivo
Execute gpg --card-status no terminal e você deve ver algo assim:
Reader ………..: Yubico Yubikey 4 OTP U2F CCID
Application ID …: <Serial number>
Version ……….: 2.1
Manufacturer …..: Yubico
Serial number ….: <Device serial number>
Name of cardholder: unspecified
Language prefs …: en
Sex …………..: unspecified
URL of public key : \[not set\]
Login data …….: <e-mail or nothing>
Signature PIN ….: not forced
Key attributes …: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 9Se você viu algo parecido e nenhum erro apareceu, pode continuar.
Execute gpg --card-edit
Você vai cair em uma interface de linha de comando, mostrando as mesmas informações do início e, embaixo, um prompt de comando gpg/card>.
Digite admin e aperte return/enter.
Agora você pode digitar help para descobrir como alterar as informações do dono e os PINs do cartão.
Uma coisa que você PRECISA fazer é trocar os PINs padrão do cartão. São dois. O primeiro é o PIN que você usa para acessar as chaves no cartão. O segundo é o PIN de “Admin” ou PUK (Personal Unblocking Code, o código pessoal de desbloqueio).
Para isso, digite passwd e você verá um menu:
gpg/card> passwd
gpg: OpenPGP card no. <Serial number> detected
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quitDigite 1 e siga as instruções para atualizar o seu PIN. O PIN padrão é 123456.
Depois de terminar, escolha 3 para trocar o PIN de Admin. O padrão é 12345678.
Com os dois PINs trocados, volte ao menu principal para terminar de atualizar as informações da chave.
Os comandos que você pode usar são:
name– para alterar o nome do titular do cartãologin– para alterar o endereço de e-mail ou o login do titular do cartão
Depois disso, podemos passar para a geração das chaves propriamente dita.
Geração das chaves
Agora é hora de gerar as chaves de verdade.
Para isso, digite generate.
Vão te perguntar Make off-card backup of encryption key? (Y/n), mas, como diz a documentação da YubiKey, isso é só um backup de fachada e não cria um backup completo das chaves secretas, então tanto faz responder Yes ou No. Eu respondo No(n).
Se já houver chaves armazenadas no cartão, vão perguntar se você quer substituí-las:
gpg: Note: keys are already stored on the card!
Replace existing keys? (y/N)Verifique se você não vai substituir algo importante do qual não tem backup e continue com Y. Se houver algo importante, é melhor cancelar todo o processo com Ctrl+C.
Vão pedir o PIN do cartão que você definiu antes.
Depois você terá que escolher por quanto tempo as chaves serão válidas:
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)Se você quer que as chaves sejam válidas por apenas 1 ano, digite 1y.
Vão pedir para você confirmar a data de expiração. Confira se está tudo certo e confirme.
Depois vão pedir as informações do dono da chave:
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.
Real name: <Your name>
Email address: <Your e-mail>
Comment: <Comment is optional>
You selected this USER-ID:
"<Your name> <comment> <your e-mail>
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
Type `O` to confirm if everything seems correct.Depois vão pedir o seu PIN de Admin ou PUK. Ele é necessário porque será feita uma operação de escrita no cartão.
Então, se tudo estiver certo, a YubiKey vai começar a piscar e continuar assim por um tempo (para mim leva uns cinco minutos).
Quando terminar, você verá a seguinte mensagem:
gpg: key <Short ID> marked as ultimately trusted
gpg: revocation certificate stored as '/Users/bisko/.gnupg/openpgp-revocs.d/<LONG ID>.rev' public and secret key created and signed.Anote o <Short ID>, pois vamos usá-lo mais adiante.
Neste ponto você pode sair do prompt do GPG com quit ou Ctrl+C.
Agora é hora de salvar a chave pública, para que possamos reutilizar a chave em outro computador.
Para isso, execute o seguinte comando:
gpg --armor --export <Short ID> > <Short ID>.ascIsso vai exportar a chave pública para um arquivo chamado <Short ID>.asc. Ele será usado no futuro se você quiser usar a YubiKey em outro computador ou se perder a sua configuração do GPG.
Para restaurar a chave pública no seu chaveiro, você precisa fazer:
gpg --import < <Short ID>.asc
gpg: key <Short ID>: public key "Your Name <your@email>" imported
gpg: Total number processed: 1
gpg: imported: 1Uma observação muito importante. Se for uma instalação nova do GPG ou outro computador, o GPG não vai reconhecer as chaves do cartão sozinho. Você precisa executar gpg --card-status para que ele leia o cartão e identifique as chaves nele.
Configurando o Git para assinar
Para configurar o Git para assinar seus commits, você precisa adicionar o seguinte ao seu ~/.gitconfig.
Na seção [user], você precisa adicionar (ou atualizar) a seguinte linha:
signingkey = 0x<Short ID>
Depois, se você quiser assinar todos os seus commits, adicione o seguinte no final do arquivo:
[gpg]
program = /usr/local/bin/gpg
[commit]
gpgsign = trueIsso fará o Git assinar todos os seus commits.
Para configurar o GitHub, você precisa adicionar sua chave pública ao seu perfil. Para isso, vá em GitHub -> Settings -> SSH and GPG keys -> New GPG key.
Você verá uma caixa de texto, onde precisa colar todo o conteúdo do arquivo <Short ID>.asc que geramos acima.
Se quiser copiar o conteúdo do arquivo (no macOS), você pode fazer:
cat <Short ID>.asc | pbcopy
Isso copia o conteúdo do arquivo inteiro para a área de transferência.
Cole na caixa de texto do GitHub e clique no botão Add GPG key.
Depois disso, você pode tentar fazer um commit e um push para o GitHub e deve ver o lindo selo Verified.
Depuração
Às vezes as coisas não funcionam de primeira. Para reunir mais informações, você pode tentar o seguinte:
Assinando com o GPG
Primeiro, tente assinar algo com a chave:
gpg -s <file>
Se isso falhar, tente descobrir por quê. Eu não sou especialista para ajudar nessa parte.
Confira a saída do Git com GIT_TRACE=1 git commit -am “test”
Isso mostra exatamente o que o Git faz enquanto tenta realizar o commit e assiná-lo. Vai te dar uma pista de por que a assinatura pode estar falhando.
Dali você também pode ver que o Git executa o seguinte comando:
/usr/local/bin/gpg --status-fd=2 -bsau <Key ID>Você pode tentar executá-lo manualmente para ver se ele dá um erro mais útil.