# CertGuru > OpenSSL commands for generating, converting, inspecting and fixing TLS certificates. Every command is run against OpenSSL 3.5 and has to work before it is published. Every command block marked for verification is executed against OpenSSL 3.5.7 on each build; a command that stops working fails the build rather than shipping. Each page below is also available as plain markdown by replacing the trailing slash with `.md`. ## OpenSSL Commands - [Generate a private key](https://certguru.io/openssl/generate-private-key/): Use openssl genpkey for RSA, EC and Ed25519 keys. It writes PKCS#8 by default, which is what modern libraries expect, unlike the older genrsa. - [Generate a certificate signing request](https://certguru.io/openssl/generate-csr/): Create a private key and CSR in one command, or a CSR from a key you already have. Includes what each subject field means and which ones the CA checks. - [Generate a CSR with Subject Alternative Names](https://certguru.io/openssl/generate-csr-with-san/): Create a CSR covering multiple hostnames with openssl req -addext, or a config file on older OpenSSL, and verify the SANs are present before you submit it. - [Generate a self-signed certificate](https://certguru.io/openssl/generate-self-signed-certificate/): Create a key and self-signed certificate in one command, with the subject alternative names browsers require. Includes why a local CA is usually the better option. - [View and decode a CSR](https://certguru.io/openssl/view-csr/): Read the subject, SANs and key details out of a certificate signing request, and verify its self-signature before you submit it to a CA. - [View and decode a certificate](https://certguru.io/openssl/view-certificate/): Read a certificate's subject, issuer, validity, SANs and extensions with openssl x509 -text, plus the short flags for pulling out one field at a time. - [Check when a certificate expires](https://certguru.io/openssl/check-certificate-expiry/): Read the expiry date of a file or a live server, and test whether it expires within a given window — the form you actually want in a monitoring script. - [Does this private key match this certificate?](https://certguru.io/openssl/check-key-matches-certificate/): Compare the public key derived from each, which works for RSA and EC alike — unlike the older modulus comparison, which silently does nothing useful for EC keys. - [Fetch a certificate from a live server](https://certguru.io/openssl/get-certificate-from-server/): Use openssl s_client to see what a server is actually serving, save the chain to a file, and diagnose the SNI mistakes that make the output misleading. - [Check supported TLS versions and ciphers](https://certguru.io/openssl/check-tls-versions-and-ciphers/): Probe a server one protocol version at a time with s_client, read what was negotiated, and avoid the OpenSSL 3 default that makes old versions look disabled when they are not. - [Verify a certificate chain](https://certguru.io/openssl/verify-certificate-chain/): Use openssl verify to confirm a certificate chains to a trusted root, and read the error codes it returns when it does not. - [Create a private root certificate authority](https://certguru.io/openssl/create-root-ca/): Build a root CA you can trust once and use to sign every internal certificate, instead of trusting self-signed certificates one at a time. - [Sign a CSR with your own CA](https://certguru.io/openssl/sign-csr-with-ca/): Issue a certificate from a CSR with openssl x509 -req, and handle the extension-copying problem that silently strips subject alternative names. - [Create an intermediate certificate authority](https://certguru.io/openssl/create-intermediate-ca/): Issue a signing CA beneath your root so the root key can stay offline, with the pathlen constraint that stops the intermediate creating further CAs. - [Remove or change a private key passphrase](https://certguru.io/openssl/remove-passphrase-from-key/): Strip the passphrase so a web server can start unattended, add one for a key a human handles, and understand the trade-off between the two. - [Extract the private key from a PFX / P12](https://certguru.io/openssl/extract-key-from-pkcs12/): Pull just the private key out of a PKCS#12 archive, strip the bag attributes, and handle archives that OpenSSL 3 refuses to open. - [Extract certificates from a PFX / P12](https://certguru.io/openssl/extract-cert-from-pkcs12/): Pull the server certificate and the CA chain out of a PKCS#12 archive as separate PEM files, without touching the private key. - [Extract a public key](https://certguru.io/openssl/extract-public-key/): Derive the public key from a private key, a certificate or a CSR — and use the result to prove which files belong together. - [Issue a client certificate for mutual TLS](https://certguru.io/openssl/create-mtls-client-certificate/): Generate a key and CSR for a client, then sign it with your private CA using clientAuth extended key usage — the flag that everything hinges on. ## Certificate Format Conversion - [Convert PEM to PFX / PKCS#12](https://certguru.io/convert/pem-to-pfx/): Bundle a PEM certificate, its private key and the intermediate chain into a single .pfx file with openssl pkcs12 -export, including the legacy flags Windows and older Java need. - [Convert PEM to DER](https://certguru.io/convert/pem-to-der/): Convert a certificate, CSR or private key from Base64 PEM text to raw binary DER, using the right OpenSSL subcommand for each object type. - [Convert DER to PEM](https://certguru.io/convert/der-to-pem/): Turn a binary DER certificate, CSR or key into Base64 PEM text, including how to work out which subcommand a mystery .cer or .der file needs. - [Convert PFX / PKCS#12 to PEM](https://certguru.io/convert/pfx-to-pem/): Extract the certificate, private key and chain out of a .pfx or .p12 archive into separate PEM files, including the OpenSSL 3 legacy flag older archives need. - [Convert a .crt or .cer file to PEM](https://certguru.io/convert/crt-to-pem/): A .crt file is often already PEM and needs only renaming. Here is how to tell, and what to run when it is really DER-encoded. - [Convert P7B / PKCS#7 to PEM](https://certguru.io/convert/p7b-to-pem/): Unpack a .p7b or .p7c certificate bundle into individual PEM certificates, and work out which of them is the leaf and which are intermediates. - [Convert PEM to P7B / PKCS#7](https://certguru.io/convert/pem-to-p7b/): Bundle one or more PEM certificates into a single .p7b file with openssl crl2pkcs7, for Windows and Java tools that expect a chain in PKCS#7 form. - [Convert a PKCS#1 key to PKCS#8](https://certguru.io/convert/pkcs1-to-pkcs8/): Turn a BEGIN RSA PRIVATE KEY file into the BEGIN PRIVATE KEY form that Java, Go and most modern libraries require, with openssl pkcs8 -topk8. - [Convert a PKCS#8 key to PKCS#1](https://certguru.io/convert/pkcs8-to-pkcs1/): Turn a BEGIN PRIVATE KEY file back into the traditional BEGIN RSA PRIVATE KEY form, including the -traditional flag OpenSSL 3 requires. - [Convert PEM to a Java keystore](https://certguru.io/convert/pem-to-jks/): Get a PEM certificate and private key into a Java keystore by going through PKCS#12 with openssl, then importing with keytool. There is no direct route. - [Convert a Java keystore to PEM](https://certguru.io/convert/jks-to-pem/): Extract the certificate and private key from a .jks keystore by converting it to PKCS#12 with keytool, then unpacking it with openssl. - [Convert PFX / PKCS#12 to a Java keystore](https://certguru.io/convert/pfx-to-jks/): Import a .pfx or .p12 archive into a Java keystore in a single keytool command, and check the alias and chain came across intact. ## Certificate File Formats - [PEM](https://certguru.io/formats/pem/): PEM is Base64-encoded DER wrapped in BEGIN and END lines. It can hold certificates, keys, CSRs or several at once, which is why the extension tells you so little. - [DER](https://certguru.io/formats/der/): DER is the raw binary encoding of an X.509 object. It holds exactly one thing, has no delimiters, and is what PEM Base64-encodes. - [.crt, .cer and .cert files](https://certguru.io/formats/crt-cer/): None of these extensions tells you the encoding. All three mean "a certificate", and any of them may be PEM text or binary DER. Here is how to check. - [.key private key files](https://certguru.io/formats/key/): A .key file holds a private key, but the extension does not say which of the four PEM key formats it uses. The header line does. - [PKCS#12 — .pfx and .p12](https://certguru.io/formats/pkcs12-pfx-p12/): A password-protected binary archive holding a certificate, its private key and the chain in one file. Also the format most likely to break between OpenSSL versions. - [CSR — certificate signing request](https://certguru.io/formats/csr/): A CSR carries your public key and the identity you are claiming, signed with your private key to prove you hold it. The CA is free to ignore most of what it says. - [PKCS#7 — .p7b and .p7c](https://certguru.io/formats/pkcs7-p7b/): A certificate-only bundle format. It can carry a whole chain in one file but never a private key, and it records no order between the certificates it holds. - [PKCS#8 private key format](https://certguru.io/formats/pkcs8/): The modern private key format. It records which algorithm the key belongs to, so one parser handles RSA, EC and Ed25519 — which is why Java and Go accept nothing else. - [JKS — Java KeyStore](https://certguru.io/formats/jks-keystore/): Java's proprietary keystore format, deprecated in favour of PKCS#12 since Java 9. Read only by keytool, never directly by OpenSSL. ## Certificate Errors - [unable to get local issuer certificate](https://certguru.io/errors/unable-to-get-local-issuer-certificate/): This OpenSSL verify error means the certificate chain is incomplete or the root CA is not trusted locally. Here is how to tell which of the two it is, and fix each. - [curl (60) SSL certificate problem](https://certguru.io/errors/curl-60-ssl-certificate-problem/): Exit code 60 is curl refusing to trust a certificate, and the text after the colon says which check failed. Match your message to its cause and fix. - [PEM routines::no start line](https://certguru.io/errors/pem-routines-no-start-line/): OpenSSL looked for a BEGIN line and did not find one. Either the file is DER and needs -inform der, or it is not the object type the command expects. - [wrong version number](https://certguru.io/errors/wrong-version-number/): Almost always a TLS client talking to a plaintext port. Here is how to confirm that in one command, plus the three rarer causes worth checking. - [OpenSSL 3 cannot read my PFX](https://certguru.io/errors/unsupported-mac-pkcs12-legacy/): OpenSSL 3 moved RC2 and 3DES into a legacy provider, so archives written by older tools fail — usually with a message that looks like a wrong password. - [bad decrypt](https://certguru.io/errors/bad-decrypt/): The ciphertext was read but the key derived from your passphrase did not fit it. Usually a wrong password, or an OpenSSL version whose default digest changed. - [self signed certificate in certificate chain](https://certguru.io/errors/self-signed-certificate-in-chain/): Verify error 19 means the chain terminates in a root your machine does not trust — usually a corporate TLS-inspecting proxy, or your own private CA. - [key values mismatch](https://certguru.io/errors/key-values-mismatch/): nginx or Apache is telling you the private key and certificate are from different key pairs. There is no repair — only finding the right key or reissuing. - [certificate has expired](https://certguru.io/errors/certificate-has-expired/): Verify error 10. Check whether it is the leaf or an intermediate that expired, and rule out a wrong system clock before renewing anything. - [NET::ERR_CERT_AUTHORITY_INVALID](https://certguru.io/errors/err-cert-authority-invalid/): Chrome cannot build a path from the certificate to a root it trusts. Either the certificate is self-signed, the chain is incomplete, or a proxy is re-signing traffic. - [NET::ERR_CERT_COMMON_NAME_INVALID](https://certguru.io/errors/err-cert-common-name-invalid/): Chrome rejects the certificate because the hostname is not in its Subject Alternative Name list. The Common Name is ignored entirely, whatever it says. - [Python — CERTIFICATE_VERIFY_FAILED](https://certguru.io/errors/certificate-verify-failed-python/): Python does not use the system trust store on macOS and often not in containers. Point it at the right CA bundle instead of disabling verification. - [PKIX path building failed](https://certguru.io/errors/pkix-path-building-failed/): Java keeps its own trust store, so a CA the rest of the machine trusts still fails inside the JVM. Here is how to find the missing CA and import it properly. - [Input not an X.509 certificate](https://certguru.io/errors/keytool-not-an-x509-certificate/): keytool refuses the file because it is not a bare certificate. Identify what you actually have — key, CSR, PKCS#12 or HTML — then convert or use the right command. - [Go — x509 certificate signed by unknown authority](https://certguru.io/errors/x509-signed-by-unknown-authority-go/): Go uses the system trust store, so this almost always means a scratch container with no CA bundle, or a corporate root that is not installed. - [UNABLE_TO_VERIFY_LEAF_SIGNATURE](https://certguru.io/errors/unable-to-verify-leaf-signature/): Node reports this when a server sends its certificate without the intermediates. Node never fetches a missing intermediate, so the chain has to be repaired. ## Install Certificates by Platform - [Certbot renewal](https://certguru.io/platforms/certbot/): Renewal is already automated by a timer you did not install. What to check when it silently stops working, and why a renewed certificate still serves the old one. - [Install a TLS certificate on nginx](https://certguru.io/platforms/nginx/): nginx has no chain directive — the intermediates go in the same file as the certificate. That one detail causes most nginx TLS problems. - [Install a TLS certificate on Apache httpd](https://certguru.io/platforms/apache/): Apache 2.4.8 changed how the chain is supplied. SSLCertificateChainFile is deprecated — the intermediates go in SSLCertificateFile now. - [Install a TLS certificate on IIS](https://certguru.io/platforms/iis/): IIS wants a PKCS#12 archive, not PEM files. Build the PFX with OpenSSL, and use -legacy if the import dialog rejects a correct password. - [Kubernetes TLS secrets](https://certguru.io/platforms/kubernetes-tls-secret/): Create a kubernetes.io/tls secret from a certificate and key, including why the certificate file must contain the full chain for Ingress to serve it correctly. - [Install a TLS certificate on Apache Tomcat](https://certguru.io/platforms/tomcat/): Tomcat 8.5+ reads PEM files directly, so the old keystore dance is optional. Here is both routes, and the keystore/key password trap. - [Install a TLS certificate on HAProxy](https://certguru.io/platforms/haproxy/): HAProxy wants one PEM file containing the certificate, the chain and the private key — the only common server that expects the key in the same file. ## Certificate Concepts - [Certificate signing requests](https://certguru.io/concepts/csr/): A CSR proves you hold a private key and states the identity you want certified. The CA decides what the certificate actually says. - [The certificate chain of trust](https://certguru.io/concepts/certificate-chain/): Why your certificate alone is not enough, what the server must send, and why browsers succeed where curl fails on the same misconfigured host. - [Self-signed vs CA-signed certificates](https://certguru.io/concepts/self-signed-vs-ca-signed/): Both provide identical encryption. The difference is entirely about who vouches for the identity, and that difference decides how much work you are signing up for. - [Free TLS certificates and ACME](https://certguru.io/concepts/free-tls-certificate/): Every publicly trusted certificate you can get for nothing comes out of ACME. What the protocol does, which CAs offer it, and the cases where free is the wrong answer. - [Subject Alternative Names](https://certguru.io/concepts/san/): The extension browsers actually match hostnames against. The Common Name has been ignored since Chrome 58, which is why CN-only certificates fail everywhere. - [Wildcard certificates](https://certguru.io/concepts/wildcard-certificate/): A wildcard replaces exactly one label, never two, and never the bare domain. What that means in practice, how to get one, and when a multi-SAN certificate is the better choice. - [Root and intermediate certificate authorities](https://certguru.io/concepts/root-vs-intermediate-ca/): Roots are trust anchors kept offline; intermediates do the actual signing. That split is why a compromised CA does not require an operating system update. - [Mutual TLS](https://certguru.io/concepts/mtls/): In mTLS the client presents a certificate too, so both ends authenticate. Here is what changes on each side and what usually breaks. - [Key usage and extended key usage](https://certguru.io/concepts/key-usage-vs-eku/): Two extensions that both restrict what a certificate can do, at different levels. Getting either wrong produces "unsupported certificate purpose". - [Revocation — OCSP and CRLs](https://certguru.io/concepts/ocsp-vs-crl/): Both answer "has this certificate been revoked?". Neither works reliably in browsers, which is why certificate lifetimes keep shrinking instead. - [Certificate fingerprints](https://certguru.io/concepts/fingerprint/): A hash of the certificate's DER bytes. Unchanged by PEM/DER conversion, changed by any reissue — which is what makes pinning brittle. ## Tools - [CSR decoder](https://certguru.io/tools/decode-csr/): Decode a certificate signing request in the browser. Nothing is uploaded. - [Certificate decoder](https://certguru.io/tools/decode-certificate/): Full X.509 breakdown of a PEM or DER certificate, in the browser. - [Key / certificate matcher](https://certguru.io/tools/check-key-cert-match/): Check whether a private key belongs to a certificate. - [PEM / DER converter](https://certguru.io/tools/convert-pem-der/): Convert between PEM and DER without leaving the page. - [Chain checker](https://certguru.io/tools/check-certificate-chain/): Validate the order and completeness of a certificate chain. ## MCP server This site is also available over the Model Context Protocol at https://certguru.io/mcp (Streamable HTTP, POST only, no authentication). Six tools: search_reference, get_reference_page and list_reference over the pages below, plus decode_certificate, decode_csr and check_key_cert_match, which parse certificate material server-side so it need not enter a model's context. Details: https://certguru.io/mcp-server/ ## Optional - [Cheat sheet](https://certguru.io/cheatsheet/): Every command on one page. - [Glossary](https://certguru.io/glossary/): Definitions of the terms used throughout. - [Verification methodology](https://certguru.io/methodology/): How commands on this site are tested. - [MCP server](https://certguru.io/mcp-server/): Using this reference and its decoders from an AI agent.