• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer

Mister PKI

SSL Certificates * SSL Tools * Certificate Decoder

  • PKI Training
  • OpenSSL
  • Keytool
  • PKI Tools
    • Apereo CAS
    • SAML
    • OpenID Connect
  • Get expert help

OpenSSL ciphers: List, Filter, and Test TLS Cipher Suites

August 13, 2026 by Mister PKI Leave a Comment

Overview

TLS configuration often works perfectly until an administrator tightens the cipher configuration.

Perhaps an old cipher is removed from a reverse proxy, web server, load balancer, or application server. Modern browsers continue working, but an older monitoring agent, Java application, API client, or network appliance suddenly fails to connect.

The server logs may contain an error such as:

no shared cipher

or:

handshake failure

The openssl ciphers command is one of the best tools for investigating that problem.

It can show:

  • which cipher suites OpenSSL recognizes;
  • which cipher suites are actually supported under the current security policy;
  • which TLS 1.2 cipher suites match a proposed configuration;
  • which TLS 1.3 cipher suites are enabled;
  • the order in which cipher suites are preferred;
  • each cipher suite’s key exchange, authentication, encryption, and MAC;
  • the official IANA cipher-suite name;
  • the hexadecimal cipher-suite identifier.

This tutorial uses a practical system-administration scenario:

After hardening the TLS configuration on an internal application server, a legacy monitoring client can no longer connect. Modern clients work normally. We need to determine whether the failure is caused by a cipher-suite mismatch and decide whether the client or server configuration should change.

We will use openssl ciphers and openssl s_client to identify the problem without weakening TLS blindly.

What does openssl ciphers do?

The basic command is:

openssl ciphers

The OpenSSL project describes openssl ciphers as the SSL cipher display and cipher-list command. It converts OpenSSL cipher strings into an ordered cipher preference list. See the official OpenSSL 3.5 ciphers documentation.

The most useful form for administrators is usually:

openssl ciphers -v

This produces detailed information for each matching cipher suite.

Another particularly useful option is:

openssl ciphers -s

The -s option limits the output to cipher suites consistent with the current security level and configured protocol range, making the result closer to what an actual OpenSSL application can use.

OpenSSL version compatibility

This guide covers:

  • OpenSSL 3.0;
  • OpenSSL 3.1;
  • OpenSSL 3.2;
  • OpenSSL 3.3;
  • OpenSSL 3.4;
  • OpenSSL 3.5 LTS;
  • OpenSSL 4.0.

Check your installed version:

openssl version

For build and configuration information:

openssl version -a

The core workflow remains consistent across OpenSSL 3.0 through OpenSSL 4.0:

openssl ciphers
openssl ciphers -v
openssl ciphers -s
openssl ciphers -V
openssl ciphers 'HIGH:!aNULL'

However, several version differences matter.

OpenSSL 3.0 and 3.1

When working with TLS 1.2-and-earlier cipher lists, use traditional OpenSSL cipher names for the broadest compatibility.

For example:

ECDHE-RSA-AES256-GCM-SHA384

rather than:

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

OpenSSL 3.2 and later

Support for using standard IANA cipher-suite names directly in cipher lists was added in OpenSSL 3.2.

That means newer releases can understand names such as:

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

in places where OpenSSL traditionally used:

ECDHE-RSA-AES256-GCM-SHA384

For scripts intended to work on OpenSSL 3.0 through 4.0, traditional OpenSSL names remain the safer choice for TLS 1.2 and earlier.

OpenSSL 3.4 and later

Support for TLS 1.3 integrity-only cipher suites was added in OpenSSL 3.4.

This is primarily relevant to specialized environments rather than normal HTTPS administration.

OpenSSL 3.5 LTS

OpenSSL 3.5 is the primary documentation target for this MisterPKI series.

The examples in this article use the OpenSSL 3.5 command syntax while maintaining OpenSSL 3.0 compatibility where practical.

OpenSSL 4.0

openssl ciphers remains available in OpenSSL 4.0 with the same general cipher-list workflow.

For modern deployments, continue using provider-based OpenSSL configuration rather than older ENGINE-based integrations.

Real-world scenario: TLS works for browsers but fails for one application

Assume an internal HTTPS service is available at:

app.example.internal

After a TLS hardening change, browsers continue connecting normally.

However, an older monitoring agent begins reporting:

SSL handshake failed

The first instinct might be to re-enable a broad set of older ciphers.

Don’t do that yet.

Instead, determine:

  1. which OpenSSL version is on the diagnostic host;
  2. which cipher suites that OpenSSL supports;
  3. which protocols the server supports;
  4. which cipher the server negotiates normally;
  5. whether a specific TLS 1.2 cipher can connect;
  6. whether TLS 1.3 is involved;
  7. whether OpenSSL’s security level is rejecting the connection.

This separates a real compatibility problem from a certificate, protocol, or configuration issue.

Step 1: Check your OpenSSL version

Run:

openssl version -a

The OpenSSL version affects:

  • cipher availability;
  • security-level behavior;
  • provider availability;
  • supported protocols;
  • accepted cipher names.

When comparing two servers or clients, record the OpenSSL version on both.

Do not assume:

OpenSSL 3

means two hosts have identical behavior.

A machine running OpenSSL 3.0 may differ significantly from one running OpenSSL 3.5 or OpenSSL 4.0.

Step 2: List the default OpenSSL cipher suites

Run:

openssl ciphers

The output is a colon-separated ordered list:

TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:...

The order matters because it represents the cipher preference list.

For easier reading, convert the colons to line breaks:

openssl ciphers | tr ':' '\n'

You can count them:

openssl ciphers | tr ':' '\n' | wc -l

The exact list depends on your OpenSSL version, build, providers, configuration, and security level.

Step 3: Display detailed cipher information

Run:

openssl ciphers -v

A TLS 1.2 entry might resemble:

ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD

This tells you several things.

FieldMeaning
Cipher nameOpenSSL cipher-suite name
TLSv1.2Protocol associated with the suite
KxKey exchange
AuAuthentication
EncBulk encryption
MacMessage authentication or AEAD

For example:

Kx=ECDH

indicates elliptic-curve Diffie-Hellman key exchange.

Au=RSA

indicates RSA authentication.

Enc=AESGCM(256)

indicates AES-256 in Galois/Counter Mode.

Mac=AEAD

indicates an authenticated-encryption cipher rather than a separate traditional MAC.

Step 4: Show only cipher suites that are actually supported

There is an important difference between:

openssl ciphers -v

and:

openssl ciphers -s -v

Without -s, OpenSSL lists all cipher suites matching the cipher expression.

With:

-s

OpenSSL considers factors such as:

  • current security level;
  • minimum protocol version;
  • maximum protocol version.

This makes:

openssl ciphers -s -v

more representative of what the OpenSSL installation can actually use.

The OpenSSL documentation notes that even this may not exactly match what a server can negotiate because server certificates, DH parameters, signature algorithms, and other configuration can further restrict usable cipher suites.

For troubleshooting, I generally recommend starting with:

openssl ciphers -s -v

Step 5: List TLS 1.2 cipher suites

Use:

openssl ciphers \
  -s \
  -tls1_2 \
  -v

This shows cipher suites that could be used if TLS 1.2 were negotiated.

Remember that the protocol selector is most meaningful when combined with:

-s

Simply using a cipher string such as:

TLSv1.2

does not force the connection protocol.

It selects cipher suites associated with TLS 1.2.

To actually force TLS 1.2 during a connection test, use openssl s_client:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  -tls1_2

For more TLS troubleshooting examples, see OpenSSL s_client Commands and Examples.

Step 6: List TLS 1.3 cipher suites

Run:

openssl ciphers \
  -s \
  -tls1_3 \
  -v

Typical TLS 1.3 cipher suites include:

TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256

OpenSSL’s default TLS 1.3 ciphersuite configuration includes those three suites.

This introduces one of the most important OpenSSL cipher concepts.

TLS 1.3 cipher suites are configured separately

For TLS 1.2 and earlier, you configure cipher suites through a cipher list.

For example:

openssl ciphers 'ECDHE:!aNULL:!eNULL'

TLS 1.3 uses a separate ciphersuite setting.

OpenSSL exposes this through:

-ciphersuites

For example:

openssl ciphers \
  -ciphersuites \
  'TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256'

This is important when configuring software such as:

  • Nginx;
  • Apache;
  • HAProxy;
  • Java applications;
  • OpenSSL-based servers;
  • reverse proxies;
  • network appliances.

A TLS 1.2 cipher setting does not necessarily control TLS 1.3.

For example, removing a TLS 1.2 cipher with:

!AES128

does not automatically mean:

TLS_AES_128_GCM_SHA256

has been removed from TLS 1.3.

Treat the TLS 1.3 ciphersuite configuration separately.

Step 7: Check the cipher negotiated by a real server

Now test the actual service:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal

Look for output such as:

Protocol  : TLSv1.3
Cipher    : TLS_AES_256_GCM_SHA384

Depending on OpenSSL version and output format, the presentation may vary.

A concise alternative is:

echo | openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  2>/dev/null |
grep -E 'Protocol|Cipher'

This answers a different question from:

openssl ciphers

openssl ciphers tells you what the local OpenSSL installation can potentially use.

openssl s_client tells you what was actually negotiated with a remote server.

For a deeper handshake workflow, see Debug TLS Connections with OpenSSL s_client.

Step 8: Force TLS 1.2

Suppose the modern connection negotiates TLS 1.3 successfully.

The failing legacy application only supports TLS 1.2.

Test the server explicitly:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  -tls1_2

If the connection succeeds, the server supports TLS 1.2.

If it fails, investigate whether TLS 1.2 has been intentionally disabled.

A protocol-version failure is not necessarily a cipher-suite failure.

Step 9: Force a specific TLS 1.2 cipher suite

Assume the older application requires:

ECDHE-RSA-AES256-GCM-SHA384

Test it:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  -tls1_2 \
  -cipher 'ECDHE-RSA-AES256-GCM-SHA384'

If the handshake succeeds, the server accepts that cipher.

If it fails while another TLS 1.2 cipher succeeds, you may have identified the compatibility issue.

Test another cipher:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  -tls1_2 \
  -cipher 'ECDHE-RSA-AES128-GCM-SHA256'

This is far better than changing the server configuration blindly.

Step 10: Force a specific TLS 1.3 cipher suite

TLS 1.3 uses:

-ciphersuites

rather than:

-cipher

For example:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  -tls1_3 \
  -ciphersuites 'TLS_AES_256_GCM_SHA384'

Test another:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  -tls1_3 \
  -ciphersuites 'TLS_AES_128_GCM_SHA256'

This difference is worth remembering:

TLS 1.2 and below → -cipher
TLS 1.3           → -ciphersuites

Step 11: Display the hexadecimal cipher-suite ID

Use:

openssl ciphers -V

This works like -v but also displays the official cipher-suite value in hexadecimal.

Example output may contain:

0xC0,0x30 - ECDHE-RSA-AES256-GCM-SHA384 ...

This is useful when comparing OpenSSL output with:

  • packet captures;
  • Wireshark;
  • vendor documentation;
  • TLS debug logs;
  • IANA cipher-suite assignments;
  • Java debug output.

For the authoritative cipher-suite registry, see the IANA TLS Cipher Suites registry.

Step 12: Display standard IANA cipher names

Use:

openssl ciphers \
  -stdname \
  -v

This shows the standard cipher name alongside the OpenSSL representation.

For example, OpenSSL may map:

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

to:

ECDHE-RSA-AES256-GCM-SHA384

This is useful because vendor documentation often uses IANA names while OpenSSL configuration historically uses OpenSSL names.

Step 13: Convert an IANA cipher name to an OpenSSL name

Suppose vendor documentation specifies:

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

Convert it:

openssl ciphers \
  -convert \
  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

The result identifies the equivalent OpenSSL name.

This is particularly helpful when translating:

  • Java cipher-suite names;
  • IANA documentation;
  • vulnerability scanner reports;
  • appliance configuration;
  • compliance documentation;

into OpenSSL configuration.

Step 14: Understand OpenSSL cipher strings

One of the most powerful features of openssl ciphers is the cipher-string language.

Instead of listing every permitted cipher individually, you can select groups.

For example:

openssl ciphers 'HIGH'

This selects high-strength cipher suites.

Other commonly encountered selectors include:

DEFAULT
ALL
HIGH
AES
AES128
AES256
AESGCM
CHACHA20
ECDHE
DHE
RSA
SHA256
SHA384

You can combine these expressions to construct a cipher policy.

Step 15: Exclude cipher suites with !

The exclamation mark permanently excludes matching cipher suites.

For example:

openssl ciphers \
  'HIGH:!aNULL:!eNULL'

Here:

!aNULL

excludes cipher suites without authentication.

And:

!eNULL

excludes cipher suites without encryption.

The OpenSSL documentation specifically warns that anonymous cipher suites are vulnerable to man-in-the-middle attacks and that NULL encryption suites provide no encryption.

Those should not be enabled in normal TLS configurations.

Another example:

openssl ciphers \
  'HIGH:!aNULL:!eNULL:!MD5'

Once a cipher has been removed with:

!

it cannot be reintroduced later in the same cipher expression.

Step 16: Understand the difference between ! and –

OpenSSL also supports:

-

to remove a cipher temporarily.

For example:

HIGH:-AES128

removes AES-128 suites from the current list.

Unlike:

!AES128

a cipher removed with - can potentially be added back later.

For strict security exclusions, ! is generally clearer.

Use:

!

when you mean:

Never allow this category.

Step 17: Reorder ciphers with +

The plus sign at the beginning of a cipher token moves matching ciphers to the end of the existing list.

For example:

HIGH:+AES128

does not add new AES-128 ciphers.

It moves matching AES-128 entries already in the list toward the end.

This is a preference operation.

Step 18: Use + as a logical AND

The plus sign also has another meaning when used between algorithm selectors.

For example:

openssl ciphers \
  'AESGCM+ECDHE'

means:

Select cipher suites that use both AES-GCM and ECDHE.

This is effectively a logical AND.

That is different from:

+AESGCM

which changes preference order.

The position of the + matters.

Step 19: Sort by encryption strength

Use:

@STRENGTH

to sort the existing list by encryption key length.

Example:

openssl ciphers \
  'HIGH:@STRENGTH'

This changes the ordering of the selected cipher suites.

Do not assume that ordering strictly by symmetric key length produces the best modern TLS policy. Modern protocol design involves more than simply comparing AES key sizes.

Use @STRENGTH when you specifically need this ordering behavior.

Step 20: Understand OpenSSL security levels

OpenSSL supports security levels from:

0

through:

5

A cipher string can change the security level using:

@SECLEVEL=n

For example:

openssl ciphers \
  -s \
  -v \
  'ALL:@SECLEVEL=2'

The security level affects more than the cipher list.

Depending on the level, OpenSSL may reject:

  • weak encryption;
  • insufficient key sizes;
  • weak signature algorithms;
  • weak DH parameters;
  • other cryptographic parameters below the required security strength.

The official OpenSSL documentation defines security levels through the SSL security-level API.

Why does lowering SECLEVEL make an old connection work?

Suppose this fails:

openssl s_client \
  -connect legacy.example.internal:443 \
  -servername legacy.example.internal

But a test using a lower security level succeeds.

That indicates the remote endpoint probably relies on cryptographic parameters the current OpenSSL policy considers too weak.

The wrong response is:

Great, let’s permanently lower the security level.

Instead, identify the actual problem.

Possible causes include:

  • an old server certificate;
  • a weak RSA key;
  • SHA-1 signatures;
  • small DH parameters;
  • legacy cipher suites;
  • outdated TLS protocols.

Lowering the security level can be useful as a diagnostic test, but upgrading the remote system is usually the correct long-term solution.

Step 21: Compare security-level cipher lists

Compare:

openssl ciphers \
  -s \
  -v \
  'ALL:@SECLEVEL=1'

with:

openssl ciphers \
  -s \
  -v \
  'ALL:@SECLEVEL=2'

Save the results:

openssl ciphers \
  -s \
  -v \
  'ALL:@SECLEVEL=1' \
  > seclevel1.txt
openssl ciphers \
  -s \
  -v \
  'ALL:@SECLEVEL=2' \
  > seclevel2.txt

Compare:

diff -u \
  seclevel1.txt \
  seclevel2.txt

This can help explain why an application stopped negotiating after a security-policy change.

Step 22: Understand DEFAULT

Run:

openssl ciphers 'DEFAULT'

DEFAULT refers to OpenSSL’s compiled-in default cipher list.

OpenSSL describes the default list as providing strong security while maintaining reasonable interoperability.

You can build on it:

openssl ciphers \
  'DEFAULT:!aNULL:!eNULL'

However, do not assume the exact output of:

DEFAULT

will remain identical across:

  • OpenSSL releases;
  • operating-system distributions;
  • vendor builds.

If application behavior depends on an exact cipher policy, test the resulting list on the target systems.

Step 23: Understand HIGH

Run:

openssl ciphers 'HIGH'

HIGH is a class of high-strength cipher suites.

You will often see configuration examples such as:

HIGH:!aNULL:!eNULL

This can be useful, but it is still a broad selector.

A security policy should be based on:

  • supported TLS versions;
  • application requirements;
  • organizational security standards;
  • current cryptographic recommendations;
  • client compatibility.

Do not assume that every cipher matching a broad keyword is automatically desirable for every environment.

Step 24: Find AES-GCM cipher suites

Run:

openssl ciphers \
  -v \
  'AESGCM'

To narrow it to ECDHE:

openssl ciphers \
  -v \
  'AESGCM+ECDHE'

To require RSA authentication:

openssl ciphers \
  -v \
  'AESGCM+ECDHE+aRSA'

This is useful when determining whether a particular certificate type and cipher combination is available.

Step 25: Find ChaCha20 cipher suites

Run:

openssl ciphers \
  -v \
  'CHACHA20'

ChaCha20-Poly1305 is an AEAD cipher commonly available in modern TLS implementations.

Remember that TLS 1.3’s:

TLS_CHACHA20_POLY1305_SHA256

belongs to the separately configured TLS 1.3 ciphersuite list.

Step 26: Find ECDHE cipher suites

Run:

openssl ciphers \
  -v \
  'ECDHE'

ECDHE provides ephemeral elliptic-curve Diffie-Hellman key exchange.

You can combine it with RSA authentication:

openssl ciphers \
  -v \
  'ECDHE+aRSA'

Or ECDSA authentication:

openssl ciphers \
  -v \
  'ECDHE+aECDSA'

The server’s certificate type matters.

For example, an RSA certificate cannot satisfy a cipher suite requiring ECDSA authentication.

This is one reason why:

openssl ciphers -s

still cannot perfectly predict every cipher a particular server will use without considering its certificate configuration.

Step 27: Why a cipher can appear in the list but still fail

Assume:

openssl ciphers -v

shows:

ECDHE-ECDSA-AES256-GCM-SHA384

That does not guarantee your server can negotiate it.

The server may have only an RSA certificate.

The suite requires:

ECDSA authentication

and therefore may not be usable.

Other limiting factors include:

  • certificate key type;
  • signature algorithms;
  • DH parameters;
  • supported groups;
  • protocol configuration;
  • security level;
  • provider configuration;
  • server preference;
  • client capabilities.

Treat openssl ciphers as one part of TLS troubleshooting.

Use openssl s_client to test the real endpoint.

Step 28: Diagnose “no shared cipher”

Suppose this command fails:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  -tls1_2

with an error related to:

no shared cipher

Begin by listing your local TLS 1.2 ciphers:

openssl ciphers \
  -s \
  -tls1_2 \
  -v

Then test a likely modern suite explicitly:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  -tls1_2 \
  -cipher 'ECDHE-RSA-AES256-GCM-SHA384'

Try another:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal \
  -tls1_2 \
  -cipher 'ECDHE-RSA-AES128-GCM-SHA256'

If neither works, investigate:

  • whether TLS 1.2 is enabled;
  • whether the server uses an RSA or ECDSA certificate;
  • whether client and server share supported groups;
  • whether security policies are blocking the handshake;
  • whether a proxy or load balancer terminates TLS before the application.

For more examples, see Debug TLS Connections with OpenSSL s_client.

Step 29: Test a proposed server cipher policy before deploying it

Assume you are considering this TLS 1.2 policy:

ECDHE+AESGCM:!aNULL:!eNULL

Before applying it to Nginx, Apache, HAProxy, or another service, inspect what it actually means:

openssl ciphers \
  -s \
  -v \
  'ECDHE+AESGCM:!aNULL:!eNULL'

If the output is empty, your expression does not match any supported cipher suites under the current configuration.

Count the result:

openssl ciphers \
  -s \
  'ECDHE+AESGCM:!aNULL:!eNULL' |
tr ':' '\n' |
wc -l

Review every result before deploying the policy.

This is exactly where openssl ciphers is most valuable: it allows you to validate the cipher expression before restarting a production service.

Step 30: Compare two cipher configurations

Suppose you have an old policy:

DEFAULT

and a proposed policy:

ECDHE+AESGCM:!aNULL:!eNULL

Save both:

openssl ciphers \
  'DEFAULT' |
tr ':' '\n' \
> default-ciphers.txt
openssl ciphers \
  'ECDHE+AESGCM:!aNULL:!eNULL' |
tr ':' '\n' \
> proposed-ciphers.txt

Compare:

diff -u \
  default-ciphers.txt \
  proposed-ciphers.txt

This immediately shows which TLS 1.2-and-earlier cipher suites would disappear.

Repeat the comparison on the actual production operating system because cipher availability may differ from your workstation.

Step 31: Compare OpenSSL installations on two hosts

When one server supports a TLS integration and another does not, run:

openssl version -a

Then:

openssl ciphers \
  -s \
  -v \
  > openssl-ciphers.txt

Also capture providers:

openssl list -providers \
  > openssl-providers.txt

And disabled features:

openssl list -disabled \
  > openssl-disabled.txt

Compare the results.

For a complete OpenSSL environment inventory workflow, see How to List OpenSSL Commands and Get Command Help.

TLS protocol names inside cipher strings can be misleading

A cipher selector such as:

TLSv1.2

means:

Select cipher suites introduced for TLS 1.2.

It does not mean:

Force TLS 1.2.

For example:

openssl ciphers 'TLSv1.2'

filters cipher suites.

To force a protocol during a real connection, use:

openssl s_client \
  -tls1_2 \
  ...

This distinction prevents a lot of TLS troubleshooting confusion.

Cipher suites versus certificate signature algorithms

A certificate’s signature algorithm is not the same thing as the TLS cipher suite.

For example, a certificate may be signed using:

sha256WithRSAEncryption

while a TLS connection negotiates:

TLS_AES_256_GCM_SHA384

These describe different cryptographic operations.

To inspect the certificate signature algorithm:

openssl x509 \
  -in certificate.pem \
  -noout \
  -text |
grep 'Signature Algorithm'

To inspect the negotiated TLS cipher:

openssl s_client \
  -connect app.example.internal:443 \
  -servername app.example.internal

Do not diagnose certificate-signature problems solely from the TLS cipher name.

Cipher suites versus supported groups

TLS cipher configuration is also different from supported elliptic-curve or finite-field groups.

Especially with TLS 1.3, the cipher-suite name does not specify the key-exchange group.

For example:

TLS_AES_256_GCM_SHA384

does not tell you whether the connection used:

X25519
P-256
P-384

or another supported key-exchange group.

That information is negotiated separately.

Use detailed openssl s_client output when you need to inspect the complete handshake rather than just the cipher.

OpenSSL providers and cipher availability

OpenSSL 3 uses the provider architecture.

List loaded providers:

openssl list -providers

For details:

openssl list \
  -providers \
  -verbose

Provider configuration can affect which cryptographic implementations are available.

If an algorithm is missing unexpectedly, compare:

openssl list -providers

between a working and non-working system.

The openssl ciphers command also supports provider options such as:

-provider
-provider-path
-propquery

and newer OpenSSL releases document provider parameters as well.

Most administrators using standard modern TLS cipher suites will not need to specify provider options manually.

FIPS environments

The cipher selector:

FIPS

can be used to identify cipher suites permitted for FIPS-oriented configurations.

For example:

openssl ciphers \
  -s \
  -v \
  'FIPS'

However, seeing a cipher in this list is not by itself proof that the entire application environment is operating in a validated FIPS configuration.

FIPS compliance involves:

  • the cryptographic module;
  • module configuration;
  • approved algorithms;
  • application behavior;
  • operating mode;
  • platform and validation requirements.

Do not treat:

openssl ciphers FIPS

as a complete FIPS-compliance test.

Avoid blindly enabling legacy cipher suites

When troubleshooting an old system, you may encounter recommendations to enable:

  • NULL encryption;
  • anonymous authentication;
  • RC4;
  • DES;
  • 3DES;
  • old CBC suites;
  • obsolete protocols;
  • low OpenSSL security levels.

Do not enable weak cryptography globally just to make one outdated client connect.

Instead:

  1. identify exactly what the client requires;
  2. confirm whether an upgrade is available;
  3. isolate the legacy system if necessary;
  4. minimize the compatibility exception;
  5. document the exception;
  6. establish a removal date.

OpenSSL explicitly excludes NULL encryption from normal cipher groups and discourages anonymous authentication because of the security risks.

A practical TLS hardening workflow

Before changing a server’s cipher configuration:

1. Record the current OpenSSL version

openssl version -a

2. Capture current supported TLS 1.2 ciphers

openssl ciphers \
  -s \
  -tls1_2 \
  -v \
  > tls12-before.txt

3. Capture TLS 1.3 cipher suites

openssl ciphers \
  -s \
  -tls1_3 \
  -v \
  > tls13-before.txt

4. Test the proposed TLS 1.2 expression

openssl ciphers \
  -s \
  -v \
  'ECDHE+AESGCM:!aNULL:!eNULL'

5. Test representative clients

Use:

openssl s_client

and real application testing.

6. Apply the server configuration

Follow the configuration mechanism appropriate for:

  • Nginx;
  • Apache;
  • HAProxy;
  • Java;
  • application middleware;
  • network appliance;
  • cloud load balancer.

7. Test again

Check:

TLS 1.2
TLS 1.3
certificate chain
hostname validation
cipher negotiation
application compatibility

8. Compare before and after

Review which cipher suites were actually removed.

This reduces the chance that a security improvement causes an unexpected outage.

Useful openssl ciphers commands

List default ciphers:

openssl ciphers

One per line:

openssl ciphers | tr ':' '\n'

Verbose:

openssl ciphers -v

Only currently supported ciphers:

openssl ciphers -s -v

Show cipher IDs:

openssl ciphers -V

Show standard names:

openssl ciphers -stdname -v

TLS 1.2:

openssl ciphers -s -tls1_2 -v

TLS 1.3:

openssl ciphers -s -tls1_3 -v

AES-GCM:

openssl ciphers -v 'AESGCM'

ECDHE and AES-GCM:

openssl ciphers -v 'ECDHE+AESGCM'

Exclude anonymous and NULL encryption:

openssl ciphers \
  'HIGH:!aNULL:!eNULL'

Security level 2:

openssl ciphers \
  -s \
  -v \
  'ALL:@SECLEVEL=2'

Convert an IANA name:

openssl ciphers \
  -convert \
  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

Important openssl ciphers options

OptionPurpose
-helpDisplays usage information
-sLists ciphers consistent with current security and protocol settings
-vDisplays detailed cipher information
-VIncludes hexadecimal cipher-suite values
-stdnameDisplays standard cipher-suite names
-convert nameConverts a standard cipher name to its OpenSSL name
-tls1_2Filters supported suites for TLS 1.2 when used with -s
-tls1_3Filters supported suites for TLS 1.3 when used with -s
-ciphersuitesSets TLS 1.3 cipher suites for the query
-pskIncludes PSK suites with -s
-srpIncludes SRP suites with -s; SRP support is deprecated
-providerLoads a provider
-provider-pathSpecifies provider module location
-propqueryApplies an OpenSSL property query

For the complete syntax, see the official OpenSSL 3.5 ciphers documentation.

Common openssl ciphers troubleshooting questions

Why does openssl ciphers show a cipher that my server cannot negotiate?

The command may show a cipher recognized by the local OpenSSL installation even though the server cannot use it.

Additional restrictions include:

  • certificate type;
  • signature algorithms;
  • DH parameters;
  • supported groups;
  • protocol versions;
  • application configuration;
  • security policies.

Try:

openssl ciphers -s -v

and then verify the real endpoint with openssl s_client.

Why does -cipher not affect TLS 1.3?

Because TLS 1.3 cipher suites are configured separately.

Use:

-cipher

for TLS 1.2 and earlier.

Use:

-ciphersuites

for TLS 1.3.

Why does a server report no shared cipher?

The client and server may have no mutually acceptable cipher suite after considering:

  • supported protocols;
  • cipher configuration;
  • certificate authentication type;
  • security levels;
  • supported algorithms.

Test TLS 1.2 explicitly and then test individual cipher suites with openssl s_client.

Does TLS_AES_256_GCM_SHA384 use RSA authentication?

The TLS 1.3 cipher-suite name does not specify certificate authentication or key exchange the way many TLS 1.2 suite names do.

Authentication and key exchange are negotiated separately in TLS 1.3.

What is the difference between AES256-SHA and TLS_AES_256_GCM_SHA384?

They represent very different generations of TLS cipher suites.

AES256-SHA is an older TLS-style cipher-suite name representing multiple negotiated components.

TLS_AES_256_GCM_SHA384 is a TLS 1.3 cipher suite whose name describes the symmetric encryption and hash associated with the TLS 1.3 key schedule.

Do not assume they are equivalent because both contain AES256.

What does !aNULL mean?

It permanently removes cipher suites that do not provide authentication.

These anonymous cipher suites are not appropriate for normal HTTPS connections.

What does !eNULL mean?

It removes cipher suites that provide no encryption.

NULL-encryption cipher suites should not be enabled for normal TLS services.

What is @SECLEVEL=2?

It tells OpenSSL to apply security level 2 to the cipher expression.

Security levels affect cryptographic parameters beyond only cipher suites.

Should I use HIGH as my production TLS configuration?

HIGH is useful as a cipher selector, but production TLS policy should consider:

  • protocol versions;
  • supported clients;
  • organizational requirements;
  • certificate types;
  • current security guidance.

Treat it as a building block rather than a complete security policy.

How do I see which cipher a website is using?

Run:

openssl s_client \
  -connect example.com:443 \
  -servername example.com

Review the negotiated protocol and cipher.

How do I test one TLS 1.2 cipher?

Run:

openssl s_client \
  -connect example.com:443 \
  -servername example.com \
  -tls1_2 \
  -cipher 'ECDHE-RSA-AES256-GCM-SHA384'

How do I test one TLS 1.3 cipher?

Run:

openssl s_client \
  -connect example.com:443 \
  -servername example.com \
  -tls1_3 \
  -ciphersuites 'TLS_AES_256_GCM_SHA384'

OpenSSL ciphers versus openssl list

These commands answer different questions.

Use:

openssl ciphers

for TLS cipher-suite selection and cipher strings.

Use:

openssl list -cipher-algorithms

to list symmetric cryptographic cipher implementations exposed through OpenSSL’s provider architecture.

For example, openssl list -cipher-algorithms may show cryptographic implementations such as AES, while openssl ciphers shows complete TLS cipher suites.

For more command-discovery examples, see How to List OpenSSL Commands and Get Command Help.

Security and privacy considerations

The openssl ciphers command itself generally reveals only local cryptographic capabilities.

However, TLS troubleshooting output from:

openssl s_client

may expose:

  • internal hostnames;
  • certificate subjects;
  • organization names;
  • email addresses;
  • internal CA names;
  • IP addresses;
  • certificate serial numbers;
  • network architecture.

Before sharing terminal output publicly, replace real infrastructure with generic placeholders.

Examples in this article use names such as:

app.example.internal
legacy.example.internal

Do not copy real internal hostnames or personally identifying information into public documentation.

Related OpenSSL guides

  • Browse the complete OpenSSL Commands Guide.
  • Test real TLS endpoints with OpenSSL s_client Commands and Examples.
  • Follow a practical workflow to Debug TLS Connections with OpenSSL s_client.
  • Learn how to List OpenSSL Commands and Get Command Help.
  • Validate certificate chains with OpenSSL verify.
  • Inspect certificate details with OpenSSL X.509 examples.
  • Review the broader collection of SSL and PKI tools.

External references

  • OpenSSL 3.5 ciphers documentation
  • OpenSSL 3.0 ciphers documentation
  • OpenSSL 4.0 ciphers documentation
  • OpenSSL s_client documentation
  • OpenSSL TLS security levels
  • IANA TLS Cipher Suites Registry

Conclusion

The openssl ciphers command is most useful when you treat it as a TLS configuration and troubleshooting tool, not simply a way to print a huge list of cipher names.

The practical workflow is:

Check the OpenSSL version
        ↓
List supported cipher suites
        ↓
Inspect the proposed cipher string
        ↓
Separate TLS 1.2 from TLS 1.3
        ↓
Test the real server with s_client
        ↓
Force individual ciphers when necessary
        ↓
Identify the actual incompatibility
        ↓
Fix or upgrade the client instead of weakening TLS blindly

For TLS 1.2 and earlier, remember:

cipher list → -cipher

For TLS 1.3:

cipher suites → -ciphersuites

And when a connection fails after TLS hardening, do not immediately restore every legacy cipher.

Use openssl ciphers to determine what the local system supports, use openssl s_client to determine what the remote server actually negotiates, and narrow the compatibility problem to a specific protocol or cipher suite before changing production configuration.

linux,  openssl

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Popular Posts

PKCS12

openssl s_client

Keytool

Keytool list

ECDSA vs RSA

OpenSSL

PKCS7

Certificate Decoder

PKI for DevOps Engineers – Free Training Series

PKI for DevOps Training Hub

Lesson 1 – How TLS and PKI Work

Lesson 2 – Understanding X.509 Certificates

Lesson 3 – Certificate Chains Explained

Lesson 4 – Debug TLS with OpenSSL

Lesson 5 – Verify Certificate Chains

Lesson 6 – Creating CSRs with OpenSSL

Lesson 7 – Working with PKCS12 Certificates

Lesson 8 – Java Keystores and keytool

Lesson 9 – Certificate Expiration Monitoring

Lesson 10 – Automating Certificate Renewal

Lesson 11 – Common TLS Errors

Lesson 12 – PKI Architecture for DevOps

Recent Posts

  • Apache mod_auth_cas: Protect Web Applications with Apereo CAS and Docker
  • Apache mod_auth_mellon: Configure SAML SSO & Docker
  • Configure OpenID Connect (OIDC) in Apereo CAS 7.3 and 8
  • Certificate Ownership Is an Operating Model Problem, Not a Tooling Problem
  • OpenSSL dgst: Create Checksums and Verify Digital Signatures

Footer

  • Twitter
  • YouTube
Mister PKI

Practical security engineering for the systems that establish trust.

Learn OpenSSL Keytool Free training
Work together PKI consulting CAS consulting Sponsored contributions
Site About Support Mister PKI Cookie policy Search
© 2026 Mister PKI Secure systems. Clear guidance.