# Generate a private key

To generate a 2048-bit RSA private key, run `openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.key`. For an elliptic curve key, which is smaller and faster at equivalent strength, run `openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out private.key`. Prefer `genpkey` over the older `genrsa`: it handles every algorithm through one interface and writes PKCS#8 output, which Java, Go and most modern libraries require.

Source: https://certguru.io/openssl/generate-private-key/
Last updated: 2026-08-19
Commands verified against OpenSSL 3.5.7.

---

## RSA

*2048-bit RSA, PKCS#8 output*

```bash
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.key
```

| Placeholder | What to put there |
| --- | --- |
| `-algorithm RSA` | The key type. Also accepts `EC`, `ED25519`, `X25519`. |
| `-pkeyopt rsa_keygen_bits:2048` | Key size. 2048 is the CA/Browser Forum minimum. |
| `private.key` | Output file. Starts `-----BEGIN PRIVATE KEY-----`. |

## Elliptic curve

Smaller keys, smaller certificates, faster handshakes, and equivalent security. P-256 is universally
supported:

*P-256 EC key*

```bash
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out private.key
```

*P-384, for a larger margin*

```bash
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out private.key
```

> **Curve naming**
>
> `P-256`, `prime256v1` and `secp256r1` are three names for the same curve. OpenSSL accepts all
>   three. `openssl ecparam -list_curves` prints everything your build supports.

## Ed25519

Modern, fast and fixed-size, but **not accepted by public CAs** for TLS server certificates. Useful
for internal PKI and for signing:

```bash
openssl genpkey -algorithm ED25519 -out private.key
```

## Choosing

| Algorithm | Key size | Use when |
| --- | --- | --- |
| RSA 2048 | 2048 bits | You want the option that works everywhere without thought |
| RSA 4096 | 4096 bits | A policy requires it. Otherwise it mostly buys signing cost |
| EC P-256 | 256 bits | Default choice for new TLS work — smaller and faster |
| EC P-384 | 384 bits | A larger margin is required by policy |
| Ed25519 | 256 bits | Internal PKI or signing. Not for public TLS certificates |

## Adding a passphrase

*Encrypt the key at rest*

```bash
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -aes-256-cbc -out private.key
```

> **A passphrase blocks unattended startup**
>
> nginx, Apache and every other TLS server will stop and wait for the passphrase at boot. That turns
>   an unattended restart into an outage. For service keys, use `chmod 600` and no passphrase; save
>   passphrases for keys a human handles, such as a CA key.

## Lock the file down

```bash
chmod 600 private.key
```

Do this immediately, not later. A key created with a default umask may be world-readable for the
window between creation and whenever you remember.

## Check what you generated

```bash
openssl pkey -in private.key -noout -text | head -n 3
```

Expected output:

```
Private-Key: (2048 bit, 2 primes)
modulus:
    00:c4:1f:...
```

## The older subcommands

Still functional, still widely seen in documentation:

```bash
openssl genrsa -out private.key 2048
```

> **genrsa writes PKCS#1, not PKCS#8**
>
> On every OpenSSL version, `genrsa` produces a `BEGIN RSA PRIVATE KEY` file. Java and Go will not
>   load it, so you end up
>   [converting it to PKCS#8](/convert/pkcs1-to-pkcs8/) anyway. Starting with `genpkey` skips the
>   step.

## Next steps

- [Generate a CSR](/openssl/generate-csr/) to get this key certified
- [Generate a self-signed certificate](/openssl/generate-self-signed-certificate/) for local use
- [Extract the public key](/openssl/extract-public-key/)


## Frequently asked questions

### Should I use genpkey or genrsa?

`genpkey`. It covers every algorithm through one interface and writes PKCS#8, the format modern libraries expect. `genrsa` still works and still writes PKCS#1 by default, which then needs converting for Java or Go.

### RSA 2048 or 4096?

2048 for almost everything. It is the CA/Browser Forum minimum and is not considered at risk. 4096 roughly quadruples signing cost for a security margin nobody currently needs, which matters on a busy server. Choose EC P-256 instead if you want a real improvement.

### Is an EC key safe to use with a public CA?

Yes. P-256 and P-384 are supported by every public CA and every browser and TLS library in current use. The certificate will be smaller and handshakes cheaper.

### Should I put a passphrase on the key?

Not for a web server, which cannot answer a prompt at boot. Protect it with file permissions instead. A passphrase makes sense for a CA key or any key that is handled by a person rather than a service.


## References

- [openssl-genpkey(1)](https://docs.openssl.org/3.5/man1/openssl-genpkey/) — the current key generation command and its -pkeyopt options
- [RFC 5958: asymmetric key packages](https://www.rfc-editor.org/rfc/rfc5958) — PKCS#8, the self-describing private key container

## Related pages

- https://certguru.io/openssl/generate-csr/
- https://certguru.io/openssl/extract-public-key/
- https://certguru.io/openssl/remove-passphrase-from-key/
- https://certguru.io/formats/pkcs8/
- https://certguru.io/concepts/csr/

--
CertGuru — https://certguru.io
