98

I have a public key generated with ssh-keygen and I'm just wondering how I get information on the keylength with openssl?

Evan Carroll
  • 2,325
  • 4
  • 22
  • 29

2 Answers2

121
ssh-keygen -lf /etc/ssh/rsa_key.pub 
2048 d1:cb:15:df:5d:44:...

2048 is the keylength

enigma
  • 1,798
  • 1
  • 11
  • 14
  • 1
    Interesting, can I do it with openssl too, since it is just an rsa public key? – Evan Carroll Sep 11 '13 at 17:16
  • For a script that checks all public keys in a file at once see [Given keys in ~/.ssh/authorized_keys format, can you determine key strength easily?](http://unix.stackexchange.com/questions/2116/given-keys-in-ssh-authorized-keys-format-can-you-determine-key-strength-easi) – Mark Stosberg Aug 11 '15 at 13:10
106

With openssl, if your private key is in the file id_rsa, then

openssl rsa -text -noout -in id_rsa

will print the private key contents, and the first line of output contains the modulus size in bits. If the key is protected by a passphrase you will have to enter that passphrase, of course.

If you only have the public key, then OpenSSL won't help directly. @Enigma shows the proper command line (with ssh-keygen -lf id_rsa.pub). You can still do that with OpenSSL the following way:

Open the public key file with a text editor. You will find something like this:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDo2xko99piegEDgZCrobfFTvXUTFDbWT
ch4IGk5mk0CelB5RKiCvDeK4yhDLcj8QNumaReuwNKGjAQwdENsIT1UjOdVvZOX2d41/p6J
gOCD1ujjwuHWBzzQvDA5rXdQgsdsrJIfNuYr/+kIIANkGPPIheb2Ar2ccIWh9giwNHDjkXT
JXTVQ5Whc0mGBU/EGdlCD6poG4EzCc0N9zk/DNSMIIZUInySaHhn2f7kmfoh5LRw7RF3c2O
5tCWIptu8u8ydIxz9q5zHxxKS+c7q4nkl9V/tVjZx8sneNZB+O79X1teq7LawiYJyLulUMi
OEoiL1YH1SE1U93bUcOWvpAQ5 thebear@isgreat.com

Select the first characters of the middle blob (after ssh-rsa); this is Base64 and OpenSSL can decode that:

echo "AAAAB3NzaC1yc2EAAAADAQABAAABAQDDo2xko99piegEDgZC" | openssl base64 -d | hd

OpenSSL is picky, it will require that you input no more than 76 characters per line, and the number of characters must be a multiple of 4. The line above will print out this:

00000000  00 00 00 07 73 73 68 2d  72 73 61 00 00 00 03 01  |....ssh-rsa.....|
00000010  00 01 00 00 01 01 00 c3  a3 6c 64 a3 df 69 89 e8  |.........ld..i..|
00000020  04 0e 06 42                                       |...B|

This reads as such:

00 00 00 07             The length in bytes of the next field
73 73 68 2d 72 73 61    The key type (ASCII encoding of "ssh-rsa")
00 00 00 03             The length in bytes of the public exponent
01 00 01                The public exponent (usually 65537, as here)
00 00 01 01             The length in bytes of the modulus (here, 257)
00 c3 a3...             The modulus

So the key has type RSA, and its modulus has length 257 bytes, except that the first byte has value "00", so the real length is 256 bytes (that first byte was added so that the value is considered positive, because the internal encoding rules call for signed integers, the first bit defining the sign). 256 bytes is 2048 bits.

nyuszika7h
  • 107
  • 6
Tom Leek
  • 168,808
  • 28
  • 337
  • 475
  • Wow, that's complex. But, well done. I'd have thought there was a way to read in the key and output all of that stuff. – Evan Carroll Sep 11 '13 at 18:10
  • Well, with the _private_ key, there is a simple way, since the format is _exactly_ what OpenSSL does natively. With the public key, though, the format is SSH-specific, not something that OpenSSL knows of. I use OpenSSL only for Base64, the rest is "manual". – Tom Leek Sep 11 '13 at 18:22
  • OpenSSL does public keys differently? – Evan Carroll Sep 11 '13 at 18:25
  • @EvanCarroll Different applications use different text representations for public keys. This has no security implications, but you need to use the appropriate program to open each key. Some programs can convert between different formats. – CodesInChaos Sep 11 '13 at 18:31
  • 3
    For OpenSSL, public keys exist only in certificates or certificate requests, with an ASN.1-based type called `SubjectPublicKeyInfo`, different from what SSH does. At the crypto level, a RSA public key is a couple of big integers; how to _encode_ a public key into bytes is out of scope of RSA "stricto sensu" and is up to the protocol which uses it. SSH, X.509, OpenPGP... all have their own encoding conventions. OpenSSL follows the "X.509" religion. – Tom Leek Sep 11 '13 at 18:33
  • 5
    [This answer](http://stackoverflow.com/questions/1193529/how-to-store-retreieve-rsa-public-private-key/13104466#13104466) on Stackoverflow digs into the gory format and binary details. TLDR: the binary blobs used by SSH are not DER (ASN.1), so OpenSSL won't read them directly. If you *really* wanted to waste 10 minutes you can use `openssl asn1parse -genconf` an adapt [one of these examples](https://www.openssl.org/docs/crypto/ASN1_generate_nconf.html#) to build a DER format which you can parse with OpenSSL... – mr.spuratic Sep 11 '13 at 18:43
  • Why does SSH do it differently, is SSH's method standardized? Why not just patch openssh to write X.509 public keys? – Evan Carroll Sep 12 '13 at 00:11
  • Probably because there was no need for the complexity of ASN.1 at that time. See [RFC 4716 §3](http://tools.ietf.org/html/rfc4716#section-3) and [RFC 4235 §6.6](http://tools.ietf.org/html/rfc4253#section-6.6) for the standard. It's not abundantly clear, but each type is prefixed with a uint32 big-endian (network order) size, as described in the answer above. There is [a patch for complete X.509 support](http://roumenpetrov.info/openssh/). – mr.spuratic Sep 12 '13 at 11:12
  • 2
    What’s `hd` and how do I get it (on OS X)? – freyaariel Feb 15 '14 at 03:32
  • 4
    `hd` is a specialized keys of `hexdump`, a usual Linux tool. On OS X, try: `od -t x1` – Tom Leek Feb 15 '14 at 14:02
  • I have no `hd`, you can use `hexdump -C` on linux/BSD – mykhal Aug 24 '15 at 14:37
  • `openssl base64 -d -A` (cap a) handles longer than 76 chars (but still a multiple of 4, which OpenSSH public-blob always is). OpenSSH beginning with 6.5 in 2014-01 can use an alternative privatekey format which OpenSSL can't read, and beginning with 7.8 in 2018-08 it does so by default. See https://stackoverflow.com/questions/19365940/convert-openssh-rsa-key-to-javax.crypto.cipher https://stackoverflow.com/questions/39105031/java-security-spec-invalidkeyspecexception and https://stackoverflow.com/questions/46870569/ssh-keygen-and-openssl-gives-two-different-public-keys/ – dave_thompson_085 May 03 '20 at 01:10