Como assinar arquivos com ferramentas de linha de comando do Ubuntu e minhas próprias chaves?

14

Quero assinar alguns arquivos de código Python que escrevi, porque são módulos de plug-in para um dos meus projetos. Para distribuí-lo, quero que o usuário tenha certeza de que um plug-in é verificado e seguro (porque foi escrito por mim ou por alguém em quem confio) e não foi modificado.

O software é apenas um projeto de hobby de código aberto, portanto, não quero gastar nenhum dinheiro comprando um certificado oficial. Em vez disso, suponho que o programa principal seja sempre válido e possa ser confiável sem verificação adicional. Se alguém faz o download de qualquer outro local que não o meu repositório GitHub, a culpa é deles.

Pelo que li, a assinatura geralmente é feita através da criação de um par de chaves assimétricas, calculando um forte valor de hash criptográfico (por exemplo, SHA-512) a partir do arquivo de código, criptografando o hash usando minha chave privada e armazenando a assinatura em um arquivo separado para ser enviado com o arquivo de código original.
O programa principal precisará descriptografar a assinatura usando a chave pública salva em texto sem formatação no código fonte do programa principal, calcular a mesma função hash do arquivo de código e compará-la com a descriptografada. Se eles corresponderem, o plug-in pode ser confiável.

Então agora minha pergunta:

Como crio facilmente um forte par de chaves assimétricas com as ferramentas Ubuntu e como calculo facilmente um valor de hash criptográfico de um arquivo?
Automatizar o processo de assinatura em um script (sempre usando a mesma chave) seria ótimo.

Byte Commander
fonte

Respostas:

19

Grande parte dessa resposta é extraída da documentação do Arch Wiki e do GnuPG . Quaisquer recomendações nesta resposta são puramente a minha opinião e devem ser tomadas com uma tonelada de sal.

Criando uma chave PGP

GUI

  1. Abra o aplicativo Senhas e Chaves (também conhecido como seahorse) e clique em +(ou vá em Arquivo -> Novo ou pressione CtrlN) para ver:

    caixa de diálogo novo item para Seahorse

  2. Selecione a chave PGP e insira seus detalhes. Estou representando o Byte Commander:

    caixa de diálogo detalhes principais

    Os bits RSA e 2048 são bons para a maioria dos propósitos. Se você quiser usá-lo apenas para assinar, escolha a opção RSA (somente sinal) no menu suspenso, mas não precisará disso - isso pode ser feito com subchaves . Você pode deixar um comentário. Manter uma data de validade em sua chave também é útil. Clique em Create.

  3. Digite uma senha adequadamente longa (e quero dizer longa , meu exemplo é curto, IMO) e clique em Ok:

    caixa de diálogo de entrada de senha

    O cavalo marinho parece não ter nenhum feedback, ao contrário do CLI. Espere um pouco, fazendo o que quiser, enquanto ele reúne entropia e cria uma chave. Pode demorar um pouco. Depois disso, você verá a chave na seção Chaves PGP :

    lista de chaves pgp

CLI

Para gerar uma chave a partir da linha de comando, basta executar gpg --gen-key. Ele solicitará os mesmos detalhes que a GUI fez:

$ gpg --gen-key 
gpg (GnuPG) 1.4.16; Copyright (C) 2013 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
Requested keysize is 2048 bits
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) 1y
Key expires at Tuesday 27 September 2016 03:45:19 PM IST
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and E-mail Address in this form:
    "Heinrich Heine (Der Dichter) <[email protected]>"

Real name: Byte Commander
E-mail address: [email protected]
Comment: 
You selected this USER-ID:
    "Byte Commander <[email protected]>"

Change (N)ame, (C)omment, (E)-mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.

passphrase not correctly repeated; try again.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, use the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 186 more bytes)
.....+++++
+++++
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, use the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 80 more bytes)
....+++++

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 83 more bytes)
...+++++
gpg: key 8AE670A6 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: next trustdb check due at 2016-09-26
pub   2048R/8AE670A6 2015-09-28 [expires: 2016-09-27]
      Key fingerprint = 82D9 0644 B265 8E75 1E01  538B B479 3CF4 8AE6 70A6
uid                  Byte Commander <[email protected]>
sub   2048R/0E2F4FD8 2015-09-28 [expires: 2016-09-27]

Observe como o GnuPG nos diz que precisa de mais entropia. Desejo cavalo-marinho também. Mas, novamente, parece que o GnuPG está agindo como Oliver Twist. : P

Publicando sua chave

Agora, precisamos divulgar nossa chave pública, para que as pessoas possam verificar as coisas usando-a.

GUI

Volte para a lista de chaves PGP no seahorseaplicativo (veja a última captura de tela). Selecione as chaves que você deseja exportar e, no menu Remoto , escolha Sincronizar e publicar chaves :

insira a descrição da imagem aqui

O Syncbotão será desativado se você não tiver selecionado um servidor para publicar. Faça isso clicando no Key Serversbotão:

insira a descrição da imagem aqui

Eu escolhi o servidor do Ubuntu.

Agora, você pode clicar no Syncbotão e publicá-lo no servidor de chaves do Ubuntu (desculpe pelo spam, Ubuntu!).

CLI

Com a CLI, você precisa do ID da chave que deseja publicar. É a última linha da saída ao criar a chave ( 8AE670A6). Se você não se lembra o que é, apenas corra gpg --list-keys. Publicar:

$ gpg  --keyserver pgp.mit.edu --send-keys 8AE670A6
gpg: sending key 8AE670A6 to hkp server pgp.mit.edu

Desculpe, MIT .

Assinatura

Ainda não conheço um método GUI conveniente de assinar um documento.

Depois de criar o arquivo que deseja assinar, vá para o terminal. Tente gpg --list-keys:

$ gpg --list-keys       
/home/muru/.gnupg/pubring.gpg
---------------------------
pub   2048R/F7878B0C 2015-09-28 [expires: 2016-09-26]
uid                  Byte Commander <[email protected]>
sub   2048R/345B9A4F 2015-09-28 [expires: 2016-09-26]

Você pode assinar o arquivo usando dois métodos:

Assinando com criptografia

$ gpg --sign --output examples.sig examples.desktop 

You need a passphrase to unlock the secret key for
user: "Byte Commander <[email protected]>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

gpg: Invalid passphrase; please try again ...

You need a passphrase to unlock the secret key for
user: "Byte Commander <[email protected]>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

Se você estiver em uma sessão da área de trabalho, é provável que seja recebido com uma solicitação gráfica de senha. Por exemplo, no GNOME:

insira a descrição da imagem aqui

Se o destinatário tiver sua chave pública, ele poderá verificá-la ou obter o conteúdo descriptografado:

$ gpg --verify examples.sig
gpg: Signature made Monday 28 September 2015 03:25:00 PM IST using RSA key ID F7878B0C
gpg: Good signature from "Byte Commander <[email protected]>"
$ gpg --decrypt examples.sig
[Desktop Entry]
Version=1.0
Type=Link
Name=Examples
Name[aa]=Ceelallo
...
URL=file:///usr/share/example-content/
Icon=folder
X-Ubuntu-Gettext-Domain=example-content

gpg: Signature made Monday 28 September 2015 03:25:00 PM IST using RSA key ID F7878B0C
gpg: Good signature from "Byte Commander <[email protected]>"

Assinando com texto não criptografado

Você pode não querer criptografar o conteúdo, por exemplo, ao enviar um email. Nesse caso, use a --clearsignopção:

$ gpg --clearsign examples.desktop 

You need a passphrase to unlock the secret key for
user: "Byte Commander <[email protected]>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

$ cat examples.desktop.asc 
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

[Desktop Entry]
Version=1.0
Type=Link
Name=Examples
Name[aa]=Ceelallo
...
URL=file:///usr/share/example-content/
Icon=folder
X-Ubuntu-Gettext-Domain=example-content

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAEBAgAGBQJWCRAaAAoJEGUZkqX3h4sMBWsH/1yw+G0v5Ck+T3PBS90SkvC8
5C0FJeGVr0AgYQohhsE3zEGQ7nn53N7JsvNlF6VccvN99DZIp18JbrJ+qs5hWjtg
KU/ACleR5dvVrJgfjppkuC8Q3cAudvqciKlLjA7Xycr3P49oCNCy8k/ue2TrgCvS
mMb5IS/kqpO7wrOMBAR0c/2CjQsA91S1/YK7DbuUqeNgEzW1grsI7XZPhiDGpAib
D20HWrbdLhklAEJuo1EvuOIggW6MF6ksxDoVapsUzQalD0TWEq6OnvzIS5qhITrc
XaDPQJpiHyCyINnL5aZCUwr2uon7osJ+2a8Ahp1REpzIZTdND9jA5NWSel5+yAs=
=ZrtB
-----END PGP SIGNATURE-----

Assinatura, com um arquivo separado para assinatura (assinatura desanexada)

Por fim, para alguns arquivos, você não pode ter a assinatura no documento. Por exemplo, os arquivos de empacotamento ou os metadados de um repositório têm conteúdo de natureza específica que não permite facilmente assinaturas incorporadas. Nesse caso, você usa a --detached-sigopção:

$ gpg --output examples.desktop.sig --detach-sign examples.desktop

You need a passphrase to unlock the secret key for
user: "Byte Commander <[email protected]>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

$ gpg --verify examples.desktop.sig examples.desktop
gpg: Signature made Monday 28 September 2015 03:35:55 PM IST using RSA key ID F7878B0C
gpg: Good signature from "Byte Commander <[email protected]>"

Nota

Na criptografia + assinatura e nas assinaturas desanexadas, a saída de gpgé binária. Você pode obter dados codificados em base64 do GnuPG usando a --armoropção (blindado ASCII).

Automação

Para assinar scripts, você pode:

  • use uma senha vazia para a chave
  • dependendo da sua versão do GnuPG, envie a senha através de stdin. Veja este post sobre Unix e Linux para algumas opções.
muru
fonte
Resposta muito agradável e detalhada. Mas sobre as chaves de exemplo que você criou ... Não sei se estou muito feliz com o fato de que um conjunto de chaves não utilizadas para o meu pseudônimo está por aí. Se eu quiser criar chaves reais com esse nome posteriormente e usá-las, as pessoas que as procurarem podem ficar confusas. Eu acho que suas chaves de exemplo e minhas chaves reais poderão coexistir por causa de endereços de email diferentes e, portanto, obter um ID diferente, mas ainda assim ... É possível que você possa excluir essas chaves novamente?
Byte Commander
@ByteCommander, o termo é revogado . Vou procurar revogá-los. Para esse assunto, devo adicionar uma seção sobre a revogação de chaves.
muru
@ByteCommander desculpe, excluí a chave que publiquei (e não havia emitido um certificado de revogação (erro clássico do n00b), por isso não posso revogá-la. No entanto, ela tem um prazo de um ano, então, bem, qualquer confusão será resolvido em um ano.
Muru
Ok, bem - isso acontece. Não tenho certeza se devo ficar aborrecido ou apenas rir desse erro estúpido ... Acho que, para o meu projeto em questão, prefiro usar o módulo Python, rsaque permite facilmente assinar dados sem ter que lidar com todo o material do GPG. Isso pode se tornar muito útil quando eu começar a publicar e empacotar software de verdade, mas provavelmente é demais para o meu objetivo no momento. Então até lá provavelmente será expirado! :)
Byte Commander
@ByteCommander ambos, suponho. Embora eu sugira que você use seu nome verdadeiro ao criar sua chave e deixe o apelido no campo de comentário.
muru
4
  1. Crie uma chave assimétrica com gpg

    gpg --gen-key
    
  2. Use gpg para assinar seu arquivo (sua chave privada é usada)

    gpg --output foo.sig --detach-sig foo.py
    
  3. Teste o arquivo de assinatura (sua chave pública é usada)

    gpg --verify foo.sig foo.py
    

    Saída de exemplo

    % gpg --verify foo.sig foo.py 
    gpg: Signature made Mo 28 Sep 2015 12:46:04 CEST using RSA key ID 89B30DEC
    gpg: Good signature from "Your Name <[email protected]>"
    
    % echo "bad" >> foo.py
    
    % gpg --verify foo.sig foo.py
    gpg: Signature made Mo 28 Sep 2015 12:46:04 CEST using RSA key ID 89B30DEC
    gpg: BAD signature from "Your Name <[email protected]>"
    
AB
fonte