OpenSSL: Display DH Parameters

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?


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).


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)
        prime:
            xx:xx:xx:xx
            xx:xx:xx:xx
            xx:xx:xx:xx
        generator: 2 (0x2)
DH parameters appear to be ok.
-----BEGIN DH PARAMETERS-----
XXXX
XXXX
-----END DH PARAMETERS-----

Hope this is what you are looking for.