# Self-signed vs CA-signed certificates

A self-signed certificate is its own issuer — nobody vouches for it, so every client must be configured to trust it individually. A CA-signed certificate is issued by an authority the client already trusts, so it is accepted with no configuration at all. The encryption is identical in both cases; the difference is purely about identity. Self-signed certificates are fine for local development and a poor fit for anything with users, because the usual workaround for the trust warning is to disable verification, which removes the protection TLS exists to provide.

Source: https://certguru.io/concepts/self-signed-vs-ca-signed/
Last updated: 2026-08-19
Commands verified against OpenSSL 3.5.7.

---

## The only difference

*Self-signed — subject and issuer are the same*

```bash
openssl x509 -in self-signed.crt -noout -subject -issuer
```

Expected output:

```
subject=CN = localhost
issuer=CN = localhost
```

*CA-signed — the issuer is somebody else*

```bash
openssl x509 -in ca-signed.crt -noout -subject -issuer
```

Expected output:

```
subject=CN = example.com
issuer=C = US, O = Example CA, CN = Example Intermediate CA
```

That is the whole distinction. Everything else follows from it.

## What is and is not different

| | Self-signed | CA-signed |
| --- | --- | --- |
| Encryption strength | Identical | Identical |
| TLS protocol version | Identical | Identical |
| Cipher suites | Identical | Identical |
| Trusted by default | No | Yes |
| Identity verified by a third party | No | Yes |
| Revocable | No | Yes, via CRL or OCSP |
| Cost | None | None, [with a free CA](/concepts/free-tls-certificate/) |
| Client configuration needed | Per certificate, per machine | None |

> **The encryption really is the same**
>
> A self-signed certificate does not produce weaker encryption. The bytes on the wire are protected
>   identically. What you lose is the ability to know *who you are talking to*, which is what makes
>   the encryption worth having.

## Why the identity part matters

Encryption without authentication protects you from a passive eavesdropper and not from an active
one. An attacker who can intercept the connection presents their own self-signed certificate, and
the client has no basis to tell it apart from yours — both are equally unvouched-for.

That is also why the usual workaround is so damaging. When a self-signed certificate produces a
warning, the fix people reach for is `curl -k`, `verify=False` or
`NODE_TLS_REJECT_UNAUTHORIZED=0` — and those disable verification for *every* connection that code
makes, not just the one that prompted it.

## When self-signed is the right choice

- **Local development.** `localhost` with a certificate you generated is fine.
- **Throwaway test environments** that no real data passes through.
- **A root CA certificate.** Every root is self-signed by definition — that is what makes it a root.

## When it is not

- Anything with real users, who will be taught to click through security warnings.
- Anything a mobile app connects to, where certificate handling is stricter and the workarounds are
  worse.
- Anything that needs revocation. A self-signed certificate cannot be revoked; if the key leaks your
  only options are to wait for expiry or manually remove it from every trust store it reached.

## The middle path: a private CA

For internal services, a private CA gives you the operational properties of a real CA without paying
anyone. Trust the root once per machine, then issue as many certificates as you like:

| | Self-signed | Private CA | Public CA |
| --- | --- | --- | --- |
| Trust-store operations | One per certificate | One per machine, ever | None |
| Works for external users | No | No | Yes |
| Revocation | No | Yes | Yes |
| Setup effort | Lowest | Moderate, once | Low with ACME |

See [create a root CA](/openssl/create-root-ca/) and
[sign a CSR with it](/openssl/sign-csr-with-ca/).

## Generating a self-signed certificate correctly

If you do want one, the SAN extension is not optional — without it browsers reject the certificate
even after you have trusted it:

```bash
openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout private.key -out certificate.crt -days 365 \
  -subj "/CN=localhost" \
  -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
```

Full detail at
[generate a self-signed certificate](/openssl/generate-self-signed-certificate/).


## Frequently asked questions

### Is a self-signed certificate less secure?

The encryption is exactly the same — same algorithms, same key sizes, same TLS. What is missing is identity assurance. Nothing independent attests that the certificate belongs to who it claims to, so a client cannot distinguish the real server from an interceptor presenting a different self-signed certificate.

### Can I use a self-signed certificate in production?

Only where you control every client and can install the certificate in each one — internal service-to-service traffic, for example. For anything with users, the browser warning trains people to click through security warnings, and the usual developer workaround is to disable verification entirely.

### How do I tell if a certificate is self-signed?

Compare subject and issuer. If they are identical, it is self-signed. `openssl x509 -in certificate.crt -noout -subject -issuer` answers it in one command.

### What about Let's Encrypt?

Let's Encrypt is a real, publicly trusted CA and its certificates are CA-signed. They are free and automatable, which removes most of the reasons people historically reached for self-signed certificates on public services. See how to get a free TLS certificate.


## References

- [CA/Browser Forum Baseline Requirements](https://cabforum.org/working-groups/server/baseline-requirements/documents/) — what a publicly trusted CA is permitted to issue
- [Mozilla CA certificate policy](https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/policy/) — the rules behind what reaches a browser trust store

## Related pages

- https://certguru.io/openssl/generate-self-signed-certificate/
- https://certguru.io/openssl/create-root-ca/
- https://certguru.io/concepts/certificate-chain/
- https://certguru.io/errors/err-cert-authority-invalid/
- https://certguru.io/concepts/root-vs-intermediate-ca/
- https://certguru.io/concepts/free-tls-certificate/

--
CertGuru — https://certguru.io
