É possível assinar um arquivo usando uma chave ssh?

36

Eu uso o SSH (OpenSSH 5.5p1 no Linux, para ser mais preciso). Eu tenho uma chave, na qual eu tenho uma senha. Eu uso isso para o logon habitual nas coisas de computadores.

Também posso usá-lo para assinar arquivos?

Pelo que entendi, uma chave SSH é uma chave RSA (ou DSA) e, durante o processo de login do SSH, é usada para assinar mensagens enviadas ao servidor. Portanto, em princípio e na prática, pode ser usado para assinar coisas - de fato, esse é seu único objetivo.

Mas, tanto quanto posso ver, não há como usar a chave para assinar um arquivo arbitrário (como faria com o PGP, por exemplo). Existe alguma maneira de fazer isso?

Tom Anderson
fonte
O OpenSSH não usa Ed25519 como o protocolo dat ? Parece apenas uma questão de ferramentas.
Pablo

Respostas:

24

Pode não haver uma maneira de fazer isso apenas com as ferramentas OpenSSH.

Mas isso pode ser feito facilmente com as ferramentas OpenSSL. De fato, existem pelo menos duas maneiras de fazer isso. Nos exemplos abaixo, ~/.ssh/id_rsaé sua chave privada.

Uma maneira é usar o dgst :

openssl dgst -sign ~/.ssh/id_rsa some-file

O outro está usando pkeyutl :

openssl pkeyutl -sign -inkey ~/.ssh/id_rsa -in some-file

Ambos escrevem uma assinatura binária na saída padrão. O dgst assume uma -hexopção imprimirá uma representação textual, com alguns detalhes sobre a forma da assinatura. O pkeyutl aceita uma -hexdumpopção que é um pouco menos útil. Ambos aceitarão as chaves RSA e DSA. Não tenho idéia de qual é o formato da saída. Os dois comandos produzem formatos diferentes. Tenho a impressão de que o pkeyutl é considerado mais moderno que o dgst .

Para verificar essas assinaturas:

openssl dgst -verify $PUBLIC_KEY_FILE -signature signature-file some-file

e:

openssl pkeyutl -verify -inkey $PUBLIC_KEY_FILE -sigfile signature-file -in some-file

O problema aqui é $PUBLIC_KEY_FILE. O OpenSSL não pode ler o formato da chave pública do OpenSSH; portanto, você não pode simplesmente usar id_rsa.pub. Você tem algumas opções, nenhuma ideal.

Se você possui uma versão do OpenSSH da versão 5.6 ou posterior, aparentemente você pode fazer o seguinte:

ssh-keygen -e -f ~/.ssh/id_rsa.pub -m pem

O qual gravará a chave pública na saída padrão no formato PEM, que o OpenSSL pode ler.

Se você possui a chave privada e é uma chave RSA, pode extrair a chave pública dela (suponho que o arquivo de chave privada codificado por PEM inclua uma cópia da chave pública, pois não é possível derivar a chave pública da própria chave privada) e use isso:

openssl rsa -in ~/.ssh/id_rsa -pubout

Não sei se existe um equivalente DSA. Observe que essa abordagem requer alguma cooperação do proprietário da chave privada, que precisará extrair a chave pública e enviá-la ao pretenso verificador.

Por fim, você pode usar um programa Python escrito por um sujeito chamado Lars para converter a chave pública do formato OpenSSH para OpenSSL.

Tom Anderson
fonte
1
Gostaria apenas de observar que “não é possível derivar a chave pública da própria chave privada” não é verdade. Na prática (isto é, em todos os sistemas de criptografia realmente usados), a chave pública é facilmente derivada da chave privada na maioria das vezes.
Kirelagin
@kirelagin: Eu não sabia disso. Você poderia me dizer ou me vincular a mais informações sobre como isso pode ser feito?
21420 Tom
1
Não tenho certeza se há alguma leitura específica sobre esse tópico ... Vamos pensar sobre isso. Pegue qualquer sistema criptográfico baseado em log (ElGamal). Nesse caso, a chave privada é (tamanho do grupo, gerador, potência) e a chave pública é (tamanho do grupo, gerador, potência ^). Portanto, o log é difícil, mas o poder não, basta calculá-lo.
kirelagin
No caso da RSA, essa inversão é realmente difícil, mas aqui a situação é um pouco diferente. A chave pública é (n, d) e a chave privada é (n, d ^ (- 1) mod phi (n)). Inverter d também seria difícil se você não armazenasse phi (n), mas aqui está o truque: quase todo mundo usa e = 65537 (quando você gera uma chave, há uma opção para alterar esse padrão, mas nunca vi qualquer pessoa que o utilize porque não faz sentido prático), portanto, derivar uma chave pública de uma privada é trivial.
precisa saber é o seguinte
Com as curvas elípticas, na verdade é o mesmo que com o log e a energia discretos, a inversão é fácil. Dito isto, não tenho certeza sobre outros sistemas de criptografia, mas esses três são os que são usados ​​na prática.
kirelagin
10

A resposta de @ Tom ajudou-me a começar, mas não funcionou imediatamente.

Esses comandos funcionarão com:

  • OpenSSL 1.0.1 14 de março de 2012
  • OpenSSH_5.9p1

Usando pkeyutl

# openssl pkeyutl -sign -inkey ~/.ssh/id_sample -in $1 > $1.sig
# ssh-keygen -e -f ~/.ssh/id_sample.pub -m PKCS8 > pub
# openssl pkeyutl -verify -pubin -inkey pub -in $1 -sigfile $1.sig
Signature Verified Successfully

Usando dgst

# openssl dgst -sign ~/.ssh/id_sample $1 > $1.sig
# ssh-keygen -e -f ~/.ssh/id_sample.pub -m PKCS8 > pub
# openssl dgst -verify pub -signature $1.sig $1
Verified OK

A versão pkeyutl pode assinar apenas arquivos pequenos. Enquanto o dgst pode assinar arquivos arbitrariamente grandes, porque é necessário digerir antes de assinar o resultado.

stephen.z
fonte
Para mim, também, a resposta Stephen.z funcionou imediatamente. Primeiro, continuei brincando com a resposta de Tom por um tempo e finalmente encontrei a resposta de Stephen.z para funcionar perfeitamente para mim. Obrigado Stephen.z!
Grzegorz Wierzowiecki 01/04
PS Aqui eu compartilhei meus trechos: gist.github.com/gwpl/2c7636f0b200cbfbe82cc9d4f6338585
Grzegorz Wierzowiecki
Você tentou usar o pkeyutl para assinar apenas o hash do arquivo?
Gaia
-3

Para verificar essas assinaturas - solução mais fácil:

A maneira mais fácil de garantir que um documento assinado seja o mesmo, é gerar novamente o arquivo de assinatura digital e usar diff para verificar se os dois arquivos de assinatura são iguais.

Ehrhardt Le Grange
fonte
3
Você está pensando em hashes , não em assinaturas . Semelhante, mas não o mesmo: o hash apenas verifica se o arquivo não foi alterado; uma assinatura também verifica de onde veio.
Piskvor