How to Use OpenSSL: Generate Keys, Certificates, and Test TLS

Sooner or later, working with web servers, mail servers, or APIs means dealing with TLS certificates. You may need a private key for a new service, a certificate signing request to send to a certificate authority, a quick self-signed certificate for a test environment, or a way to confirm what a remote server is actually presenting. OpenSSL covers all of this from a single command-line tool.
OpenSSL is the de facto toolkit for the TLS and SSL protocols on Linux. It ships with almost every distribution and exposes dozens of subcommands for key generation, certificate handling, encoding conversions, and connection testing.
This guide explains how to use openssl to generate keys, create and inspect certificates, convert between formats, and test live TLS connections.
Syntax
OpenSSL works through subcommands, each with its own options:
openssl command [ command_options ] [ arguments ]For example, openssl genrsa generates an RSA key, while openssl x509 works with X.509 certificates. You can list every available subcommand with:
openssl helpCheck which version is installed before you start, since option defaults change between major releases:
openssl versionOpenSSL 3.5.5 27 Jan 2026OpenSSL 3.x is the current series on modern distributions. The examples below work on the 3.x line.
Generate a Private Key
Most certificate work starts with a private key. To create a 2048-bit RSA key, run:
openssl genrsa -out private.key 2048This writes an unencrypted key to private.key. A 2048-bit key is the practical minimum today; use 4096 bits when you want a wider safety margin and do not mind the small performance cost.
To protect the key with a passphrase, add a cipher option such as -aes256:
openssl genrsa -aes256 -out private.key 2048OpenSSL prompts you for the passphrase and encrypts the key on disk. The service that uses the key will then ask for that passphrase on startup.
Elliptic-curve keys are smaller and faster than RSA at equivalent security. To generate one on the widely supported prime256v1 curve:
openssl ecparam -name prime256v1 -genkey -noout -out ec-private.keychmod 600 private.key), never commit it to version control, and add key files to your .gitignore. Anyone who has the key can impersonate your service.Create a Certificate Signing Request
A certificate signing request (CSR) bundles your public key and identifying details so a certificate authority can issue a signed certificate. Generate a key and CSR together:
openssl req -new -newkey rsa:2048 -noenc -keyout domain.key -out domain.csrOpenSSL prompts for the subject fields. The Common Name (CN) should match the primary domain you are securing, for example example.com. The -noenc option leaves the key unencrypted so a service can read it without a passphrase prompt.
To skip the interactive prompts, pass the subject inline and add Subject Alternative Name (SAN) entries for each hostname the certificate should cover:
openssl req -new -newkey rsa:2048 -noenc \
-keyout domain.key -out domain.csr \
-subj "/C=US/ST=California/L=San Francisco/O=Example Inc/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com"Inspect the finished CSR to confirm the details before sending it off:
openssl req -in domain.csr -noout -textThe output lists the subject, public key, and any requested extensions.
Create a Self-Signed Certificate
For local development, internal tools, or testing, a self-signed certificate avoids the need for a CA. Generate a key and certificate valid for one year in a single command:
openssl req -x509 -newkey rsa:2048 -noenc \
-keyout selfsigned.key -out selfsigned.crt \
-days 365 \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"The -x509 option tells req to output a certificate instead of a request, and -days 365 sets the validity period. Browsers will warn that the certificate is not trusted, which is expected for self-signed certificates. For a fuller walkthrough, see our guide on creating a self-signed SSL certificate
.
When you need a browser-trusted certificate for a public site, use a CA such as Let’s Encrypt instead.
Inspect a Certificate
To read the contents of a certificate in human-readable form:
openssl x509 -in selfsigned.crt -noout -textThis prints the issuer, subject, validity dates, public key, and extensions. When you only need specific fields, target them directly. To see just the validity window:
openssl x509 -in selfsigned.crt -noout -datesnotBefore=Jan 1 08:00:00 2026 GMT
notAfter=Jan 1 08:00:00 2027 GMTTo print the subject and issuer:
openssl x509 -in selfsigned.crt -noout -subject -issuerFor a self-signed certificate, the subject and issuer are the same.
Verify Key, Certificate, and CSR Match
When deploying a certificate, the private key, certificate, and CSR must all share the same public key. A mismatch is a common cause of services that refuse to start. Compare their modulus hashes:
openssl rsa -in domain.key -noout -modulus | openssl md5
openssl x509 -in domain.crt -noout -modulus | openssl md5
openssl req -in domain.csr -noout -modulus | openssl md5All three commands must print the same hash. If one differs, the files do not belong together.
Convert Certificate Formats
Different platforms expect different encodings. OpenSSL converts between them.
Convert a PEM certificate to DER (binary), often required by Java or Windows tools:
openssl x509 -in cert.pem -outform der -out cert.derConvert DER back to PEM:
openssl x509 -in cert.der -inform der -outform pem -out cert.pemBundle a certificate and private key into a PKCS#12 file (.pfx or .p12), the format many Windows services and load balancers expect:
openssl pkcs12 -export -out bundle.pfx -inkey domain.key -in domain.crtOpenSSL asks for an export password that protects the bundle.
Test a TLS Connection
The s_client subcommand opens a TLS connection to a server and reports what it negotiated. This is the fastest way to debug a certificate that does not seem to work:
openssl s_client -connect example.com:443The output shows the certificate chain, the negotiated protocol and cipher, and the verification result. Press Ctrl+C or type Q to close the session.
When a server hosts several names on one IP, send the hostname with Server Name Indication so you get the right certificate:
openssl s_client -connect example.com:443 -servername example.comTo check when a live certificate expires without scrolling through the full chain, pipe the output into x509:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -datesThe echo closes the connection immediately so the command returns instead of waiting for input. This is handy for verifying renewals after a certificate is reissued. If a hostname is not resolving as expected during testing, the dig command
helps confirm the DNS records first.
Generate Random Data and Hashes
OpenSSL also doubles as a general crypto utility. Generate a random, URL-safe token:
openssl rand -base64 32Hash a file with SHA-256:
openssl dgst -sha256 file.isoThese small helpers are useful for generating secrets or verifying downloads when no dedicated tool is at hand.
Quick Reference
For a printable quick reference, see the OpenSSL cheatsheet .
| Task | Command |
|---|---|
| Show version | openssl version |
| Generate RSA key | openssl genrsa -out private.key 2048 |
| Generate EC key | openssl ecparam -name prime256v1 -genkey -noout -out ec.key |
| Create CSR | openssl req -new -newkey rsa:2048 -noenc -keyout d.key -out d.csr |
| Self-signed cert | openssl req -x509 -newkey rsa:2048 -noenc -keyout d.key -out d.crt -days 365 |
| Inspect cert | openssl x509 -in cert.crt -noout -text |
| Check expiry dates | openssl x509 -in cert.crt -noout -dates |
| PEM to DER | openssl x509 -in cert.pem -outform der -out cert.der |
| Export PKCS#12 | openssl pkcs12 -export -out b.pfx -inkey d.key -in d.crt |
| Test TLS | openssl s_client -connect host:443 -servername host |
Troubleshooting
unable to load Private Key
The key file is encrypted and OpenSSL expected an unencrypted one, or the file is corrupt. Add the passphrase when prompted, or regenerate the key with -noenc if the service cannot supply a passphrase.
verify error:num=18:self signed certificates_client is reporting that the chain ends in a self-signed certificate. This is normal for self-signed certificates and for testing. For a public site, install the full chain issued by your CA.
verify error:num=20:unable to get local issuer certificate
The server did not send the intermediate certificate. Concatenate your certificate and the CA intermediate into one file and serve that combined file.
Key and certificate modulus do not match
The certificate was not issued for this key. Re-check that you generated the CSR from the same key the CA signed, then compare modulus hashes as shown above.
FAQ
What is the difference between a CSR and a certificate?
A CSR contains your public key and identity details and is sent to a certificate authority. The CA returns a signed certificate. The CSR is the request; the certificate is the issued result.
Should I use RSA or elliptic-curve keys?
Elliptic-curve keys (such as prime256v1) are smaller and faster at equivalent security and are well supported. RSA 2048 remains a safe, widely compatible default. Either is fine for most servers.
How do I remove a passphrase from a key?
Run openssl rsa -in encrypted.key -out plain.key. OpenSSL prompts for the current passphrase and writes an unencrypted copy. Protect that file carefully, since it is no longer passphrase-protected.
Why does my self-signed certificate trigger browser warnings?
Browsers only trust certificates signed by a recognized authority. Self-signed certificates are not in that trust store, so the warning is expected. Use Let’s Encrypt for public sites.
Conclusion
OpenSSL handles the full lifecycle of TLS material: keys, requests, certificates, format conversions, and live connection testing. When you move from generating certificates to serving them, use a trusted CA and keep renewal on a schedule so certificates do not expire unnoticed.
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page