<!-- https://pkizerotohero.com/guides/create-csr-java-keytool/ | Markdown mirror of the HTML page | PKI Zero to Hero, by Duyutech BV -->

> Create a key pair and CSR with Java keytool, with SANs that reach the CA, then import the signed reply and its chain into the same PKCS #12 keystore.

Source: https://pkizerotohero.com/guides/create-csr-java-keytool/ · Last reviewed: 2026-10-20

How-to guide · Create keys and CSRs

# How to create a CSR with Java keytool

**In one sentence:**

You will have a key pair in a PKCS #12 keystore, a CSR whose SAN list really reaches the CA, and the signed certificate chain installed under the same alias.

Task

[Create keys and CSRs](https://pkizerotohero.com/guides/#task-create)

Platforms

- Java

Who it is for

- [Developer](https://pkizerotohero.com/start/#developer)
- [IT ops](https://pkizerotohero.com/start/#itops)

Level

Practitioner · 6 steps

## Before you start

- **A JDK** with `keytool` on the path (`keytool -help` should work). The commands below were run with OpenJDK 21.
- **Every name the certificate must cover**, and any IP addresses clients use to connect.
- **A place for the keystore** on the server that will use it, readable only by the service account.

A [keystore](https://pkizerotohero.com/handbook/glossary/#keystore) holds your private key and, later, its certificate chain under one alias. The private key never leaves it: you send the CA only the CSR.

## Steps

### 1. Create the key pair in a new keystore

```bash
keytool -genkeypair -alias shop -keyalg EC -groupname secp256r1 \
  -dname "CN=shop.example.com, O=Example Shop, C=BE" \
  -ext "SAN=dns:shop.example.com,dns:www.shop.example.com" \
  -storetype PKCS12 -keystore shop.p12
```

```text
Generating 256 bit EC (secp256r1) key pair and self-signed certificate (SHA384withECDSA) with a validity of 90 days
	for: CN=shop.example.com, O=Example Shop, C=BE
```

- `-keyalg EC -groupname secp256r1` creates a P-256 key. For RSA, use `-keyalg RSA -keysize 3072`.
- keytool asks for a keystore password. In a PKCS #12 keystore, the key uses the same password.
- `-storetype PKCS12` is the default since JDK 9; it matters on JDK 8, whose default is the older JKS format.
- The self-signed certificate is only a placeholder. The CA’s reply replaces it in step 6.

### 2. Create the CSR, and repeat the names

```bash
keytool -certreq -alias shop -keystore shop.p12 -file shop.csr \
  -ext "SAN=dns:shop.example.com,dns:www.shop.example.com"
```

Common mistake

The SAN does not carry over by itself

`-certreq` does not copy the SAN from the key pair you made in step 1. Without `-ext` here, our CSR requested only a Subject Key Identifier and no names at all. The [keytool documentation](https://docs.oracle.com/en/java/javase/21/docs/specs/man/keytool.html) describes `-ext` in `-certreq` as the way “to show what extensions are requested in the certificate request”. Always pass it again.

For clients that connect by IP address, add `ip:192.0.2.10` to the list.

### 3. Check the CSR

```bash
keytool -printcertreq -file shop.csr
```

```text
PKCS #10 Certificate Request (Version 1.0)
Subject: CN=shop.example.com, O=Example Shop, C=BE
Format: X.509
Public Key: 256-bit EC (secp256r1) key
Signature algorithm: SHA384withECDSA

Extension Request:

#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
  DNSName: shop.example.com
  DNSName: www.shop.example.com
]
```

Every name must appear under `SubjectAlternativeName`. You can also paste the CSR into the decoder under “Check it worked”.

### 4. Send the CSR to the CA

Submit `shop.csr` through your CA’s form or your internal PKI process. Ask for the reply as a **chain**: your certificate followed by the intermediates, as a PEM bundle or a `.p7b` file. If you receive separate files, join them, your certificate first:

```bash
cat shop.crt issuing-ca.crt > shop-chain.pem
```

### 5. Make sure keytool can trust the chain

keytool imports a reply only if it can build a chain to a root it trusts, either in your keystore or in the JDK’s trust store, a keystore file named cacerts in JAVA\_HOME/lib/security.

- **Public CA:** its root is already in `cacerts`. Add `-trustcacerts` in step 6.
- **Private CA:** import its root into your keystore as a trusted entry first. Compare the fingerprint keytool shows with the one your PKI team publishes, and answer `yes` only if they match:

```bash
keytool -importcert -alias keystone-root -file root.crt -keystore shop.p12
```

```text
Owner: CN=Keystone Demo Root CA, O=Keystone Demo, C=BE
...
	 SHA256: FE:F0:F5:E6:B9:C0:7B:2E:53:F6:D3:8B:0B:33:CD:0E:EA:81:C0:0D:B8:8D:50:38:88:0E:4E:D6:80:BE:5D:63
...
Trust this certificate? [no]:  yes
Certificate was added to keystore
```

### 6. Import the reply into the same alias

Use the **same alias** as the key pair, so keytool replaces the placeholder:

```bash
keytool -importcert -alias shop -file shop-chain.pem -keystore shop.p12
```

```text
Certificate reply was installed in keystore
```

For a public CA, add `-trustcacerts`. keytool also checks that the public key in the reply matches your private key, and refuses it otherwise.

## Check it worked

```bash
keytool -list -v -alias shop -keystore shop.p12
```

```text
Alias name: shop
Entry type: PrivateKeyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=shop.example.com, O=Example Shop, C=BE
Issuer: CN=Keystone Demo Issuing CA 1, O=Keystone Demo, C=BE
...
Certificate[2]:
Owner: CN=Keystone Demo Issuing CA 1, O=Keystone Demo, C=BE
Issuer: CN=Keystone Demo Root CA, O=Keystone Demo, C=BE
...
Certificate[3]:
Owner: CN=Keystone Demo Root CA, O=Keystone Demo, C=BE
Issuer: CN=Keystone Demo Root CA, O=Keystone Demo, C=BE
```

Look for `PrivateKeyEntry`, a chain length of 2 or more, and your names under `SubjectAlternativeName`. A chain length of 1 with your own name as the issuer means the self-signed placeholder is still there. Paste the CSR here to double-check what you asked for:

*Interactive tool: CSR decoder (runs in the browser at [/tools/csr/](https://pkizerotohero.com/tools/csr/))*

Then point your server at the keystore: [How to install a certificate in Tomcat and other Java servers](https://pkizerotohero.com/guides/install-certificate-tomcat/).

## If something goes wrong

- **The issued certificate lacks your names:** `-ext SAN=…` was missing from `-certreq` (step 2). Create a new CSR from the same key and ask for a reissue.
- **`keytool error: java.lang.Exception: Failed to establish chain from reply`:** you imported only your certificate, and keytool cannot find its issuer. Import the chain file instead (step 4), and the private root if there is one (step 5).
- **`… is not trusted. Install reply anyway? [no]:`:** the chain ends at a root keytool does not know. Answer `no`, check the root’s fingerprint with your PKI team, import it (step 5) and try again.
- **`keytool error: java.lang.Exception: Public keys in reply and keystore don't match`:** the reply belongs to another key: the wrong alias, the wrong keystore, or a CSR from an earlier attempt. See [How to check that a private key matches a certificate](https://pkizerotohero.com/guides/check-key-matches-certificate/).
- **A warning that “The JKS keystore uses a proprietary format”:** you created a JKS keystore. Move it to PKCS #12 with [How to convert a Java keystore (JKS) to PKCS #12](https://pkizerotohero.com/guides/convert-jks-pkcs12/).
- **Clients fail with [`PKIX path building failed`](https://pkizerotohero.com/errors/java-pkix-path-building-failed/):** the server sends an incomplete chain, or clients do not trust your private root. Check the chain length above, and [the chain the server sends](https://pkizerotohero.com/guides/check-remote-certificate-chain/).
- **Clients connecting by IP get [`No subject alternative names matching IP address … found`](https://pkizerotohero.com/errors/java-no-subject-alternative-names/):** add `ip:` entries to the SAN in step 2.

## Why this works

The CSR is a PKCS #10 request, RFC 2986 (PKCS #10), signed with the key in your keystore to prove you hold it. keytool keeps that key under one alias, first with a self-signed placeholder and then, after the import, with the chain the CA returned. Because keytool insists on a chain to a trusted root and on matching public keys, a successful import already proves most of what can go wrong. [Asking for a certificate](https://pkizerotohero.com/handbook/csr/) explains the CSR, [Who do we trust?](https://pkizerotohero.com/handbook/trust-stores/) explains `cacerts` and private roots, and the [file formats appendix](https://pkizerotohero.com/handbook/file-formats/) explains JKS and PKCS #12.

## Go deeper

- [Oracle: keytool (Java SE 21)](https://docs.oracle.com/en/java/javase/21/docs/specs/man/keytool.html): `-genkeypair`, `-certreq`, `-ext` and how a certificate reply is imported.
- [RFC 2986](https://www.rfc-editor.org/rfc/rfc2986): the PKCS #10 request format.
- [RFC 7292](https://www.rfc-editor.org/rfc/rfc7292): PKCS #12, the keystore format.
- [RFC 5280, section 4.2.1.6](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.6): the Subject Alternative Name extension.

**Early edition.** Checked against the standards; an independent expert review is in progress. Found a mistake? [Tell us](https://pkizerotohero.com/contact/?topic=content-error&page=/guides/create-csr-java-keytool/).

Last reviewed 20 October 2026Edition 0.9

## Keep going

### Learn why it works

- [Chapter 10: Asking for a certificate: key generation and the CSR](https://pkizerotohero.com/handbook/csr/)
- [Chapter 12: Who do we trust? CAs, trust stores and self-signed certificates](https://pkizerotohero.com/handbook/trust-stores/)
- [File formats: PEM, DER, PKCS #12 and friends](https://pkizerotohero.com/handbook/file-formats/)

### Error pages

- [PKIX path building failed … unable to find valid certification path to requested target](https://pkizerotohero.com/errors/java-pkix-path-building-failed/)
- [No subject alternative names matching IP address … found](https://pkizerotohero.com/errors/java-no-subject-alternative-names/)

### Tools

- [CSR decoder](https://pkizerotohero.com/tools/csr/): Check a certificate signing request before you send it to a CA.

### Topics

- [Certificates](https://pkizerotohero.com/topics/certificates/)

## More guides: Create keys and CSRs

- [How to create a key and a CSR with OpenSSL (with SANs)](https://pkizerotohero.com/guides/create-csr-openssl/)
- [How to create a CSR on Windows (certreq and IIS)](https://pkizerotohero.com/guides/create-csr-windows/)
