Is it possible to sign a file using an ssh key?

36

14

I use SSH (OpenSSH 5.5p1 on Linux, to be precise). I have a key, on which i have a passphrase. I use this for the usual logging in to computers stuff.

Can i also use it to sign files?

As i understand it, an SSH key is an RSA (or DSA) key, and during the SSH login process, it is used to sign messages sent to the server. So in principle and in practice, it can be used to sign things - indeed, that is its sole purpose.

But as far as i can see, there is no way to use the key to sign an arbitrary file (as you would with PGP, say). Is there some way to do this?

Tom Anderson

Posted 2011-07-08T14:08:32.343

Reputation: 1 341

Doesn't OpenSSH use Ed25519 as the dat protocol? Seems just a matter of tools.

– Pablo A – 2018-03-15T03:22:57.717

Answers

24

There may not be a way to do this with the OpenSSH tools alone.

But it can be done quite easily with the OpenSSL tools. In fact, there are at least two ways to do it. In the examples below, ~/.ssh/id_rsa is your private key.

One way is using dgst:

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

The other is using pkeyutl:

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

Both of these write a binary signature to standard output. dgst takes a -hex option will print a textual representation, with some details about the form of the signature. pkeyutl takes a -hexdump option which is a bit less useful. Both will accept both RSA and DSA keys. I have no idea what the format of the output is. The two commands produce different formats. I get the impression that pkeyutl is considered more modern than dgst.

To verify those signatures:

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

and:

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

The problem here is $PUBLIC_KEY_FILE. OpenSSL can't read OpenSSH's public key format, so you can't just use id_rsa.pub. You have a few options, none ideal.

If you have a version of OpenSSH of 5.6 or later, you can apparently do this:

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

Which will write the public key to standard output in PEM format, which OpenSSL can read.

If you have the private key, and it's an RSA key, then you can extract the public key from it (I assume the PEM-encoded private key file includes a copy of the public key, since it is not possible to derive the public key from the private key itself), and use that:

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

I don't know if there's a DSA equivalent. Note that this approach requires some cooperation from the owner of the private key, who will have to extract the public key and send it to the would-be verifier.

Lastly, you can use a Python program written by a chap called Lars to convert the public key from OpenSSH to OpenSSL format.

Tom Anderson

Posted 2011-07-08T14:08:32.343

Reputation: 1 341

I found this write up very helpful as well http://blog.oddbit.com/2011/05/09/signing-data-with-ssh-agent/.

– David Xia – 2015-10-21T02:53:52.310

1I'd just like to note that “it is not possible to derive the public key from the private key itself” is not true. In practice (that is, in all the cryptosystems that are actually used) public key is easily derived from the private key most of the time. – kirelagin – 2014-04-07T19:35:50.227

@kirelagin: I didn't know that. Could you tell me, or link me to, more information about how that can be done? – Tom Anderson – 2014-04-08T11:20:03.127

1I'm not sure if there is some particular reading on this topic… Let's just think about it. Take any discrete log based cryptosystem (ElGamal). In this case, private key is (group size, generator, power) and public key is (group size, generator, generator^power). So, log is difficult, but power is not, you just calculate it. – kirelagin – 2014-04-08T16:28:26.083

In case of RSA this inversion is actually difficult, but here the situation is slightly different. Public key is (n, d) and private key is (n, d^(-1) mod phi(n)). Inverting d would also be difficult if you didn't store phi(n), but here is the trick: almost everyone uses e = 65537 (when you generate a key there is an option to change this default, but I've never seen anyone using it because it doesn't make any practical sense), so deriving a public key from a private one is trivial. – kirelagin – 2014-04-08T16:31:16.517

With Elliptic curves it's actually the same as with discrete log and power, inverting is easy. That said, I'm not sure about other cryptosystems, but those three are the ones that are used in practice. – kirelagin – 2014-04-08T16:36:12.763

10

@Tom's answer helped get me started, but didn't work out-of-the box.

These commands will work with:

  • OpenSSL 1.0.1 14 Mar 2012
  • OpenSSH_5.9p1

Using 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

Using 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

The pkeyutl version can only sign small sized files. While dgst can sign arbitrarily large files, because it takes a digest before signing the result.

stephen.z

Posted 2011-07-08T14:08:32.343

Reputation: 323

To me also Stephen.z answer worked out-of-the-box . First I kept playing with Tom's answer for a while and finally found Stephen.z answer to work perfectly to me. Thanks Stephen.z ! – Grzegorz Wierzowiecki – 2016-04-01T21:09:08.017

P.S. Here I've shared my snippets: https://gist.github.com/gwpl/2c7636f0b200cbfbe82cc9d4f6338585

– Grzegorz Wierzowiecki – 2016-04-01T22:02:43.947

Did you try to use pkeyutl to sign only the hash of the file? – Gaia – 2018-11-17T23:15:13.253

-3

To verify those signatures - easier solution:

Easier way to make sure a signed document is the same, is to re-generate the digital signature file and then use diff to check if the two signature files are the same.

Ehrhardt Le Grange

Posted 2011-07-08T14:08:32.343

Reputation: 1

3You are thinking of hashes, not signatures. Similar, but not the same: the hash only verifies that the file didn't change; a signature also verifies whence it came. – Piskvor left the building – 2011-10-20T14:00:10.603