When using SSL Ciphers relying on a diffie hellman key exchange, the size of the private key employed is of crucial importance for the security of that key exchange.

When I connect to a server using the "openssl s_client" tool, how can I query the DH parameters used?

migrated from security.stackexchange.com Apr 24 '15 at 8:13

This question came from our site for information security professionals.


I don't know of an easy to use command-line switch, but in the openssl s_client command line, you can add the -msg option to get an hexadecimal dump of the handshake message. Then look for the ServerKeyExchange message; it should look like this:

<<< TLS 1.2 Handshake [length 030f], ServerKeyExchange
    0c 00 03 0b 01 00 ff ff ff ff ff ff ff ff c9 0f
    da a2 21 68 c2 34 c4 c6 62 8b 80 dc 1c d1 29 02
    4e 08 8a 67 cc 74 02 0b be a6 3b 13 9b 22 51 4a

and it reads that way:

  • 0c 00 03 0b: message of type "ServerKeyExchange" (that's the "0c") of length 0x00030B bytes.
  • First element is the DH modulus as a big integer, with a two-byte length header. Here, the length is encoded as 01 00, meaning an integer encoded over 0x0100 bytes. That's 256 bytes, so the modulus has length between 2041 and 2048 bits.
  • The modulus bytes follow, in unsigned big-endian order. The top bytes of that modulus are, in this case, ff ff ff ff.... The modulus then has length exactly 2048 bits.

If you use an ECDHE cipher suite (elliptic curve), then the ServerKeyExchange format is different, of course.

See the standard for the definition of the ServerKeyExchange message. For DHE cipher suites, it contains the modulus p, generator g and server DH public key y, in that order, each expressed as a big integer in the format described above (16-bit header that contains the length in bytes, then the integer value in unsigned big-endian encoding).

Recent OpenSSL versions tend to select a DH modulus size that matches (from a security point of view) the strength of the server's key pair (used to sign the ServerKeyExchange message). In the example above, the server has a 2048-bit RSA key, so OpenSSL elected to use a 2048-bit DH modulus (in this case, the well-known modulus described in RFC 3526, section 3).

Some other servers stick to 1024-bit DH groups in order to ensure compatibility with some existing clients that do not support larger DH groups (biggest offender being the SSL implementation in Java, fixed in Java 8 build 56 in 2012). A known flaw in the TLS protocol, for the DHE cipher suites, is that the client has no way to specify what modulus size it may support (this is fixed for ECDHE, because the client can specify the exact list of curves that it accepts).

  • 1
    OpenSSL doesn't autoselect DHE, but an app callback can. OpenSSL 1.0.2 (Jan. 2015) can optionally autoselect ECDHE, and also in 1.0.2 s_client always displays "Temp server key" DH&size or ECDH&curve when applicable, just before "handshake has read x and written y", so you no longer need to decode it. It's recent Apache mod_ssl that autoselects DHE: httpd.apache.org/docs/trunk/mod/mod_ssl.html#sslcertificatefile (which notes the issue about Java clients). – dave_thompson_085 Apr 24 '15 at 9:18
  • I use openssl 1.0.1e and I don't get any ServerKeyExchange with 0c 00 03 0b. can you provide the exact command to get the output? I have none of the Handshakes starting with 0c – rubo77 Jun 9 '15 at 14:12
  • If the cipher suite selected by the server is not a "DHE" or "ECHDE" cipher suite, then there will be no ServerKeyExchange message. – Thomas Pornin Jun 9 '15 at 14:56
  • I get <<< TLS 1.2 Handshake [length 01cd], ServerKeyExchange 0c 00 01 c9 03 00 17 41 04 08 5f 82 88 1e e5 b6 followed by 443 octets which correspond to a length of 0x1c9 starting at the fifth octet. However "0300" seems to mean 768 octets while I feel sure my DH param is "only" 2048 bits. – Law29 Nov 21 '16 at 11:59
  • 1
    @Law29 This more looks like an ECDHE ServerKeyExchange. If using an elliptic curve, then the "03" means "this is a named curve, the next two bytes encode the curve identifier". Then "00 17" is the curve identifier, which is NIST P-256 (the most used curve for ECDHE). Then "41" is the public point length, which is exactly the right value for a P-256 point in uncompressed format; such a point would begin with a byte of value 0x04, and that's precisely what you have. To sum up: it seems your TLS 1.2 handshake really uses ECDHE, not DHE. – Thomas Pornin Nov 21 '16 at 13:59

If you have the certificate in PEM format, you can try this command, it should give you a proper output from Openssl command.

openssl dhparam -inform PEM -in ./imapd.pem -check -text

(Sample output)
    PKCS#3 DH Parameters: (512 bit)
        generator: 2 (0x2)
DH parameters appear to be ok.

Hope this is what you are looking for.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.