Recentemente o core do PHP passou por uma situação, no mínimo, inusitada: 2 commits foram feitos em nome de personalidades da comunidade. Isso é possível porque quando registramos uma alteração no git através de um commit, ele registra os dados que queremos que sejam registrados, incluindo o usuário e email que você disse ter (git config user.name "Cauan"
e git config user.email "[email protected]"
). Veja que você não precisa validar email nem nada.
Aplicações que hospedam projetos em git geralmente pedem pra gente validar o email usado nos commits, assim são capazes de inferir que aquele código enviado é de quem disse ter enviado. Mas é apenas uma associação “lógica”. O commit diz que foi feito por fulana, e a fulana é uma usuária válida aqui no Github/Gitlab, então vou exibir a foto e nome dessa fulana aqui na interface.
Se o git não garante que quem fez uma alteração é quem diz ser, como a gente pode garantir? Assinando nossas mudanças com uma chave criptográfica.
Felizmente o git permite que a gente especifique uma chave privada configurada no GPG e cuida de todo o processo de assinar nossas mudanças. Na outra ponta, nós compartilhamos a chave pública com o Github/Gitlab para que valide o commit assinado e então possam garantir que aquele código foi feito por quem diz ter feito.
O pessoal do PHP preparou um guia bem completo sobre como configurar o GPG e git para que o incidente não se repita. Vou colocar aqui o resumo do resumo para quem tiver alguma dificuldade com inglês, mas se tiver alguma dúvida, pode usar os comentários.
Atenção: todos os comando devem ser executados com seu usuário normal. Quando necessário, o sudo vai estar explicitado.
O símbolo $ não faz parte do comando, é só pra diferenciar o que é um comando e o que é uma saída de comando. Sempre que tiver o $, você pode copiar o que está na frente e executar no seu terminal.
Primeiro, instale o GPG:
Sistema | Comando(s) |
---|---|
macOS com Homebrew | brew install gpg |
Ubuntu, Debian, Mint, Kali | sudo apt install gnupg |
CentOS, Fedora, RHEL | sudo yum install gnupg |
Se você usa Zsh como shell, você precisa configurar um tty para que funcione corretamente os comandos interativos com o GPG:
$ mkdir "${HOME}"/.gnupg
$ chmod 700 "${HOME}"/.gnupg
$ >> "${HOME}"/.zshrc echo 'GPG_TTY="$(tty)" && export GPG_TTY || echo "Could not determine TTY: $?" >&2'
$ source "${HOME}"/.zshrc
Verificando que a instalação funcionou:
$ gpg --version | head -2
gpg (GnuPG) 2.2.21
libgcrypt 1.8.6
$ gpg-connect-agent /bye && echo 'GPG ok' || echo 'ERROR: GPG not running'
GPG ok
$ [ -r "${GPG_TTY}" ] && echo 'TTY ok' || echo 'ERROR: TTY not found'
TTY ok
Agora vamos gerar sua chave de assinatura GPG. É imprescindível escolher uma senha forte para proteger sua chave:
$ gpg --batch --generate-key <(echo '
Key-Type: RSA
Key-Length: 4096
Expire-Date: 0
Name-Real: Fulana de Tal
Name-Email: [email protected]
')
Precisamos descobrir a versão curta do ID da chave gerada:
$ gpg -K --keyid-format SHORT
sec rsa4096/02783663 2020-08-26 [SCEA]
79694216A0DECA5B53E94E96910A1F8402783663
uid [ultimate] Fulana de Tal <[email protected]>
Repare no resultado do comando anterior a primeira linha. O que vem após rsa4096/
é o ID que nós queremos, nesse exemplo: 02783663
.
Vamos deixar esse valor em uma variável de ambiente para facilitar o restante das configurações, basta executar:
$ export GPG_KEYID=02783663
Estamos terminando, precisamos dizer ao git para usar essa chave para assinar nossas alterações no repositório:
$ git config --global --replace user.signingkey "${GPG_KEYID}"
$ git config --global --replace commit.gpgsign true
$ git config --global --replace tag.gpgsign true
Por último, precisamos informar ao Github/Gitlab nossa chave, para que ele possa verificar o autor das mudanças:
$ gpg --armor --export "${GPG_KEYID}" | pbcopy
pbcopy
é um comando do macOS para jogar informação na área de transferência (equivalente a um Ctrl+C). Substitua essa parte pelo comando equivalente no seu ambiente se for outro, ou simplesmente retire o trecho | pbcopy
e a chave será exibe no terminal, daí basta selecionar e copiar.
Com a chave copiada, acesse suas configurações:
- No Github: https://github.com/settings/keys
- No Gitlab: https://gitlab.com/-/profile/gpg_keys
Feito isso, todos os seus novos commits deve ser assinados e se tudo ocorreu bem, aparecerão como verificados nos Git da vida:
Atualizado em 13/04/2021: eu segui esses passos do artigo original em um macOS sem o gpg previamente instalado e com o git relativamente atualizado. Caso seu ambiente já tenha gpg ou a versão do git seja muito antiga, verifique a seguinte resposta no StackOverflow. Agradecimento ao Elton Minetto pela dica nos comentários.
Atualizado em 01/05/2021: como alertou nos comentários o Adjamilton, depois da gente atualizar o conteúdo do arquivo .zshrc precisamos recarregar seus valores usando o comando
source "${HOME}"/.zshrc
para que as mudanças surtam efeito. O trecho já está atualizado.
4 respostas em “Git + GPG = Assinando suas contribuições”
Ótimo post, bem oportuno.
Testei no MacOS mas encontrei alguns problemas. Fiz uma pesquisa e encontrei esse post com a solução: https://stackoverflow.com/questions/39494631/gpg-failed-to-sign-the-data-fatal-failed-to-write-commit-object-git-2-10-0
O que eu precisei fazer foi:
brew upgrade gnupg # This has a make step which takes a while
brew link –overwrite gnupg
brew install pinentry-mac
echo “pinentry-program /usr/local/bin/pinentry-mac” >> ~/.gnupg/gpg-agent.conf
killall gpg-agent
Para testar se funcionou basta executar o comando:
echo “test” | gpg –clearsign
E se estiver tudo ok vai funcionar no Github.
Opa, valeu Minetto.
Vou adicionar esse link no texto pro caso de mais alguém parar nesse erro.
Cauan, depois do comando abaixo, é preciso dar um source no .zshrc:
$ >> “${HOME}”/.zshrc echo ‘GPG_TTY=”$(tty)” && export GPG_TTY || echo “Could not determine TTY: $?” >&2’
$ source ~/.zshrc
Tem razão Adjamilton, eu aqui tinha aberto uma nova aba no terminal (que é o jeito burro de fazer isso) e esqueci de comentar, vou incluir isso no texto.
Muito obrigado.