Cauan Cabral's.

Git + GPG = Assinando suas contribuições

Cauan Cabral
Cauan Cabral
Posted underDesenvolvimento WebProgramaçãoTutoriais

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 "cauan@dominio.com"). 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:

SistemaComando(s)
macOS com Homebrewbrew install gpg
Ubuntu, Debian, Mint, Kalisudo apt install gnupg
CentOS, Fedora, RHELsudo 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: fulana@dominio.com.br
')

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 <fulana@dominio.com.br>

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:

Feito isso, todos os seus novos commits deve ser assinados e se tudo ocorreu bem, aparecerão como verificados nos Git da vida:

Imagem com uma lista de commits contendo o selo "verified" do Github

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.

Taggedgitgpgsegurança


pgModeler – gerando o seu binário

Cauan Cabral
Cauan Cabral

Tem algumas aplicações que são icônicas pra gente – por diversas razões – no meu caso, alguns destes são winamp, mIRC, Macromedia Flash MX, Amarok, Kompare, MySQL Workbench e Gitlab. Outro que conheci e me deixou admirado quando descobri foi o pgModeler, primeiro pela qualidade da aplicação em si que é o mais próximo do […]

Dica Rápida: usando tipos “complexos” com Migrations no Phinx

Cauan Cabral
Cauan Cabral

Essa é uma dica bem curta e realmente rápida pra registrar algo que precisei pesquisar algumas vezes nos últimos anos e sempre me esqueço. Cena: você define uma tabela no seu projeto e gostaria de usar uma coluna com o tipo tsvector (como citei em posts recentes) ou então uuid. Você quer usar as funções […]