0

I was wondering if it is possible for openssl to check the server public key size. Currently, I am connecting to the server using:

openssl s_client -connect "ip address":"port" -key client.key -cert client.crt -CAfile myCA.crt -verify 10 -verify_return_error

This is on the client side.

The server has been set with a weak server key (1024). I was hoping that there is a one-line solution for rejecting the server because of its weak server key.

5
  • You merely have to look at the certificate presented by the server. Is there a reason you have to do this with OpenSSL? You can do it in a browser as well.
    – user163495
    Feb 8 at 14:15
  • Yes since I only have a shell access to the device
    – Sad.coder
    Feb 8 at 14:18
  • Also, sorry for checking I understand, what about rejecting as well
    – Sad.coder
    Feb 8 at 14:19
  • openssl has options like -ssl3, -tls1, -tls1_1, -tls1_2, -tls1_3, -no_ssl3, -no_tls1, -no_tls1_1, -no_tls1_2, -no_tls1_3, etc. which are used to allow/reject connections based on the versions of ssl/tls that the server supports. It would be nice if it had options like these to allow/reject connections based on attributes of the certificate as well, but looking at openssl.org/docs/man1.1.1/man1/s_client.html, that doesn't appear to be the case.
    – mti2935
    Feb 8 at 14:58
  • @mti2935 ahh sweet thank you, so I would have to implement feature, :'(
    – Sad.coder
    Feb 8 at 15:11

2 Answers 2

3

How to find the server's public key size

In order to check the size of the certificate's public key, you can use the openssl command-line tool. The commands were taken from this answer by Ari Maniatis on StackOverflow, so I would recommend upvoting his answer if it was helpful.

Essentially, there are two ways of doing it: With SNI, and without SNI. Some servers require SNI, while others don't support it.

With SNI, the command is as follows:

openssl s_client -showcerts -servername www.example.com -connect www.example.com:443 </dev/null

And without SNI, the command is as follows:

openssl s_client -showcerts -connect www.example.com:443 </dev/null

You can also use this one-liner to print the certificate information and look for the public key:

echo | openssl s_client -connect google.com:443 2>/dev/null | openssl x509 -text -noout

This will print the following output:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            02:52:16:e1:c4:99:8e:26:32:aa:5d:1d:a9:85:b4:3c
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
        Validity
            Not Before: Dec 10 00:00:00 2021 GMT
            Not After : Dec  9 23:59:59 2022 GMT
        Subject: C = US, ST = California, L = Los Angeles, O = "Verizon Digital Media Services, Inc.", CN = www.example.org
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
===>            RSA Public-Key: (2048 bit)
                Modulus:
                    00:a0:30:42:56:d7:0b:a1:11:b9:f3:0b:ec:cc:f2:
                    4c:b0:6f:13:02:6b:cf:07:f3:85:f0:42:8f:c5:54:
                    98:81:6e:7a:93:38:b6:fa:46:42:b3:5c:e6:c9:3b:
                    59:93:61:24:43:20:f5:7a:89:c9:77:ad:ff:87:c8:
                    08:db:86:f5:dc:61:75:96:5f:dc:f0:08:ca:3a:b9:
                    5e:0f:fa:37:7c:65:6a:ca:08:27:1e:9d:d8:0a:3f:
                    9e:10:db:45:25:9a:03:72:ba:f5:27:d9:b0:eb:36:
                    d4:93:39:8c:11:6c:5f:33:14:58:e5:c0:88:c5:1f:
                    7a:21:14:cc:d2:a7:5f:1c:73:1f:d9:03:20:6e:7a:
                    08:ef:17:4e:e3:be:28:c0:4f:e0:71:63:21:04:77:
                    8f:8f:4b:2b:e8:0b:a2:be:97:7e:50:6f:b8:3b:37:
                    63:7f:a4:0c:99:ff:96:a2:c3:7f:ca:7c:21:ba:fd:
                    90:d1:3f:05:a4:34:70:d6:84:8e:a5:00:dc:29:7c:
                    fd:96:cb:43:ae:39:8f:2d:c6:ad:d8:c2:1d:9b:e4:
                    5f:9c:51:9c:8b:fe:6d:49:62:5b:c7:cd:1e:18:96:
                    ce:c6:2a:07:b7:71:80:60:72:ac:57:12:00:90:43:
                    0f:23:be:a9:70:71:d6:e5:7b:85:a3:4d:05:88:21:
                    c7:23
                Exponent: 65537 (0x10001)
[...]

As you can see, example.com uses an 2048 bit RSA public key. You can also add | grep -B 1 "Public-Key" to just display the public key length and the key type. This is necessary, as EC Certificates have significantly shorter public key lengths, yet are considered just as secure.


How to reject weak public keys

Browsers will do that automatically. It seems Chrome and others automatically mark certificates with 1024 bit RSA keys as "insecure" and display a warning to the user.

9
  • Not directly an answer, but related: You can use the tool testssl.sh to test the SSL/TLS configuration of a server. It's way easier to use than naked openssl.
    – user163495
    Feb 8 at 14:32
  • So, one could grep the output to find and act on the key size?
    – schroeder
    Feb 8 at 14:38
  • Thank you, very much, this does help on the checking side of things but on the rejecting of the server key, I was hoping to use openssl, if not a script which has already been written, since I only have access via shell
    – Sad.coder
    Feb 8 at 14:41
  • @Sad.coder How are you going to access the server? Via HTTPS or SSH? Or something else entirely?
    – user163495
    Feb 8 at 14:50
  • 1
    @schroeder You're right. I added the grep command to my answer. You can't just grep for the key size alone, because it could be an ECC Certificate. Google, for example, uses a 256 bit ECC certificate.
    – user163495
    Feb 8 at 14:52
3

I want to thank @MechMK1 for providing the partial answer, and @schroeder for editing my questions and mti2935 for pointing me in the right direction, I was able to get OpenSSL to reject the server based on the server public key size. This was done through the following command:

openssl s_client -connect <ip_address>:<port> -key Client.key -cert Client.crt -CAfile myCA.crt -verify 10 -verify_return_error -cipher @SECLEVEL=2:ALL
6
  • Can you comment on what part(s) did the trick?
    – schroeder
    Feb 8 at 16:36
  • OP, I think you're on the right track with this, but I am skeptical that using the -cipher option with openssl s_client in this way is doing what you want as far as rejecting server certificates with RSA public keys <=1024 bits in length. The -cipher option allows/rejects connections based on the cipher (e.g. tls_aes_128_gcm_sha256, etc.) used. The cipher is only loosely related (at best) to the public key in the certificate. See security.stackexchange.com/questions/129987/… for more info.
    – mti2935
    Feb 8 at 17:03
  • To answer both schroeder and @mti2935 Yes mti2935 you are right on cipher suite being loosely connected but, the "-cipher @SECLEVEL=2:ALL" did do it for me schroeder, for mti2935 the SECLEVEL seems to be connected to what public keys size can be accepted as per this document openssl.org/docs/man1.1.1/man3/…. section DEFAULT CALLBACK BEHAVIOUR
    – Sad.coder
    Feb 8 at 20:01
  • The other arg which seems to work is "-auth_level 2"
    – Sad.coder
    Feb 8 at 20:05
  • That's really cool!
    – mti2935
    Feb 8 at 20:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.