Est-il possible de signer un fichier en utilisant une clé ssh?

36

J'utilise SSH (OpenSSH 5.5p1 sous Linux, pour être précis). J'ai une clé sur laquelle j'ai une phrase secrète. J'utilise ceci pour la connexion habituelle aux ordinateurs.

Puis-je aussi l'utiliser pour signer des fichiers?

Si je comprends bien, une clé SSH est une clé RSA (ou DSA) et, lors du processus de connexion SSH, elle est utilisée pour signer les messages envoyés au serveur. Donc, en principe et dans la pratique, il peut être utilisé pour signer des choses - en fait, c'est son seul but.

Mais pour autant que je sache, il n’ya aucun moyen d’utiliser la clé pour signer un fichier arbitraire (comme avec PGP, par exemple). Y a-t-il un moyen de faire ça?

Tom Anderson
la source
OpenSSH n'utilise-t-il pas Ed25519 comme protocole de données ? Semble juste une question d'outils.
Pablo Un

Réponses:

24

Il n’est peut-être pas possible de faire cela avec les outils OpenSSH seuls.

Mais cela peut être fait assez facilement avec les outils OpenSSL. En fait, il y a au moins deux façons de le faire. Dans les exemples ci-dessous, ~/.ssh/id_rsaest votre clé privée.

Une façon utilise dgst :

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

L'autre utilise pkeyutl :

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

Tous deux écrivent une signature binaire sur la sortie standard. dgst prend une -hexoption pour imprimer une représentation textuelle, avec quelques détails sur la forme de la signature. pkeyutl prend une -hexdumpoption un peu moins utile. Les deux accepteront les clés RSA et DSA. Je n'ai aucune idée du format de la sortie. Les deux commandes produisent des formats différents. J'ai l'impression que pkeyutl est considéré comme plus moderne que dgst .

Pour vérifier ces signatures:

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

et:

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

Le problème ici est $PUBLIC_KEY_FILE. OpenSSL ne peut pas lire le format de clé publique d'OpenSSH, vous ne pouvez donc pas simplement l'utiliser id_rsa.pub. Vous avez quelques options, aucune idéale.

Si vous avez une version de OpenSSH 5.6 ou ultérieure, vous pouvez apparemment le faire:

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

Qui écrira la clé publique sur la sortie standard au format PEM, qu’OpenSSL peut lire.

Si vous possédez la clé privée et qu'il s'agit d'une clé RSA, vous pouvez en extraire la clé publique (je suppose que le fichier de clé privée codé en PEM inclut une copie de la clé publique, car il n'est pas possible de dériver la clé publique. de la clé privée elle-même), et utilisez-le:

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

Je ne sais pas s'il existe un équivalent DSA. Notez que cette approche nécessite une certaine coopération de la part du propriétaire de la clé privée, qui devra extraire la clé publique et l'envoyer au vérificateur potentiel.

Enfin, vous pouvez utiliser un programme Python écrit par un responsable appelé Lars pour convertir la clé publique du format OpenSSH au format OpenSSL.

Tom Anderson
la source
1
Je voudrais juste noter que "il n'est pas possible de dériver la clé publique de la clé privée elle-même" n'est pas vrai. En pratique (c'est-à-dire dans tous les cryptosystèmes réellement utilisés), la clé publique est facilement dérivée de la clé privée la plupart du temps.
Kirelagin
@kirelagin: Je ne le savais pas. Pourriez-vous me dire ou me connecter à plus d'informations sur la façon dont cela peut être fait?
Tom Anderson
1
Je ne suis pas sûr qu'il y ait une lecture particulière sur ce sujet… Pensons-y. Prenez n’importe quel cryptosystème à base de journaux discrets (ElGamal). Dans ce cas, la clé privée est (taille du groupe, générateur, puissance) et la clé publique est (taille du groupe, générateur, générateur ^ puissance). Donc, le log est difficile, mais le pouvoir ne l’est pas, vous le calculez.
Kirelagin
En cas de RSA, cette inversion est en réalité difficile, mais la situation est légèrement différente. La clé publique est (n, d) et la clé privée est (n, d ^ (- 1) mod phi (n)). L'inversion de d serait également difficile si vous ne stockiez pas phi (n), mais voici le truc: presque tout le monde utilise e = 65537 (lorsque vous générez une clé, il est possible de modifier ce paramètre par défaut, mais je ne l'ai jamais vu quiconque l’utilise parce que cela n’a aucun sens pratique), il est donc trivial de dériver une clé publique d’une clé privée.
Kirelagin
Avec les courbes elliptiques, c'est en fait la même chose que pour le log et l'alimentation discrets, l'inversion est facile. Cela dit, je ne suis pas sûr des autres systèmes cryptographiques, mais ces trois systèmes sont ceux qui sont utilisés dans la pratique.
Kirelagin
10

@ La réponse de Tom m'a aidé à démarrer, mais n'a pas fonctionné en dehors de la boîte.

Ces commandes fonctionneront avec:

  • OpenSSL 1.0.1 14 mars 2012
  • OpenSSH_5.9p1

Utiliser 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

Utiliser 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

La version pkeyutl ne peut signer que des fichiers de petite taille. Alors que dgst peut signer des fichiers volumineux, car il faut un résumé avant de signer le résultat.

stephen.z
la source
Pour moi, la réponse de Stephen.z a également fonctionné. D'abord, j'ai continué à jouer avec la réponse de Tom pendant un moment et j'ai finalement trouvé la réponse de Stephen.z qui me convenait parfaitement. Merci Stephen.z!
Grzegorz Wierzowiecki
PS Ici , j'ai partagé mes extraits: gist.github.com/gwpl/2c7636f0b200cbfbe82cc9d4f6338585
Grzegorz Wierzowiecki
Avez-vous essayé d'utiliser pkeyutl pour signer uniquement le hachage du fichier?
Gaia
-3

Pour vérifier ces signatures - solution plus facile:

Un moyen plus simple de s’assurer qu’un document signé est identique, consiste à générer à nouveau le fichier de signature numérique, puis à utiliser diff pour vérifier si les deux fichiers de signature sont identiques.

Ehrhardt Le Grange
la source
3
Vous pensez à des hashes , pas à des signatures . Similaire, mais pas pareil: le hachage vérifie uniquement que le fichier n'a pas changé; une signature vérifie également d'où il vient.
Piskvor