認証局にサーバー証明書を発行してもらうには、CSR(Certificate Signing Request)を作成して提出する。CSRはopenssl req -newで作る。
すでに秘密鍵がある場合は、-keyで指定する。
$ openssl req -new -key server.key -out server.csr -subj "/C=JP/ST=Tokyo/O=Example Inc./CN=example.com"
秘密鍵もまとめて新しく作る場合は、-newkeyと-keyoutを使う。
$ openssl req -new -newkey rsa:2048 -noenc -keyout server.key -out server.csr -subj "/C=JP/ST=Tokyo/O=Example Inc./CN=example.com"
CSRには公開鍵とサブジェクト(組織名やドメイン名)が含まれる。秘密鍵は含まれないため、CSRを認証局に送っても秘密鍵は漏れない。
実行例はUbuntu 24.04のOpenSSL 3.0.13のもの。
既存の秘密鍵からCSRを作る
秘密鍵の作り方は別の記事で説明している。
参考: 【openssl】秘密鍵を作成する (genpkey)
ECDSAの鍵を作ってCSRを作る例は以下のとおり。
$ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ec.key
$ openssl req -new -key ec.key -out ec.csr -subj "/CN=example.com"
$ head -1 ec.csr
-----BEGIN CERTIFICATE REQUEST-----
-outを省略すると、標準出力にPEM形式で出力する。
サブジェクトを指定する
-subjは/キー=値を並べた形式で指定する。よく使うキーは以下のとおり。
| キー | 意味 | 例 |
|---|---|---|
C | 国(2文字) | JP |
ST | 都道府県 | Tokyo |
L | 市区町村 | Shibuya |
O | 組織名 | Example Inc. |
OU | 部署名 | Engineering |
CN | コモンネーム | example.com |
-subjを省略すると、対話形式で各項目を入力する。
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
値を空にする項目は.を入力する。スクリプトから実行する場合は、-subjを指定して対話を避ける。
値に/が含まれる場合は、\でエスケープする。,は-subjの区切りではないため、そのまま書ける。
$ openssl req -new -key ec.key -subj "/O=Example, Inc./CN=a" | openssl req -noout -subject
subject=O = "Example, Inc.", CN = a
/で始めないとエラーになる。
$ openssl req -new -key ec.key -subj "CN=a"
req: subject name is expected to be in the format /type0=value0/type1=value1/type2=... where characters may be escaped by \. This name is not in that format: 'CN=a'
SANを追加する
現在のブラウザーは、証明書のコモンネーム(CN)ではなく、SAN(Subject Alternative Name)でホスト名を検証する。CSRにSANを含めるには、-addextを使う。
$ openssl req -new -key ec.key -out san.csr -subj "/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com,IP:192.0.2.1"
-addextは複数回指定できる。キー用途なども追加できる。
$ openssl req -new -key ec.key -out ext.csr -subj "/CN=a" \
-addext "subjectAltName=DNS:a.example.com" \
-addext "keyUsage=digitalSignature" \
-addext "extendedKeyUsage=serverAuth"
認証局によっては、CSRに含めた拡張が無視され、認証局側の設定で上書きされる。申請先の仕様を確認する。
CSRの内容を確認する
-noout -textで、CSRの内容を表示する。
$ openssl req -in san.csr -noout -text
Certificate Request:
Data:
Version: 1 (0x0)
Subject: CN = example.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
...
Attributes:
Requested Extensions:
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com, IP Address:192.0.2.1
Signature Algorithm: ecdsa-with-SHA256
SANはRequested Extensionsに表示される。提出前に、ホスト名や鍵の種類、署名アルゴリズムを確認する。
サブジェクトだけを見る場合は-subjectを使う。
$ openssl req -in san.csr -noout -subject
subject=CN = example.com
CSRの署名が正しいかは-verifyで検証できる。
$ openssl req -in san.csr -noout -verify
Certificate request self-signature verify OK
設定ファイルで指定する
SANや複数の項目を毎回コマンドラインに書くのは面倒である。設定ファイルにまとめて、-configで読み込む。
[req]
distinguished_name = dn
req_extensions = v3
prompt = no
[dn]
C = JP
O = Example Inc.
CN = example.com
[v3]
subjectAltName = DNS:example.com,DNS:www.example.com
$ openssl req -new -key ec.key -config csr.cnf -out csr.csr
$ openssl req -in csr.csr -noout -text | grep -E 'Subject:|DNS:'
Subject: C = JP, O = Example Inc., CN = example.com
DNS:example.com, DNS:www.example.com
prompt = noを指定すると、対話入力なしで[dn]の値を使う。
秘密鍵を暗号化せずに保存する
-newkeyで鍵も作る場合、秘密鍵はパスフレーズで暗号化される。パスフレーズなしで保存するには、-noencを付ける。Webサーバーを自動で起動する場合など、起動時にパスフレーズを入力できない用途で使う。
$ openssl req -new -newkey rsa:2048 -noenc -keyout server.key -out server.csr -subj "/CN=example.com"
$ head -1 server.key
-----BEGIN PRIVATE KEY-----
-noencを付けないと、パスフレーズの入力を求められる。-passoutで非対話に指定できる。
$ openssl req -new -newkey rsa:2048 -passout pass:pw -keyout server.key -out server.csr -subj "/CN=example.com"
$ head -1 server.key
-----BEGIN ENCRYPTED PRIVATE KEY-----
古い記事では、同じ意味の-nodesが使われている。OpenSSL 3.0でも-nodesは動作するが、非推奨である。
鍵の種類を指定する
-newkeyには、鍵の種類を指定する。
| 指定 | 鍵の種類 |
|---|---|
rsa:2048 | RSA 2048ビット |
ec -pkeyopt ec_paramgen_curve:P-256 | ECDSA P-256 |
ed25519 | Ed25519 |
$ openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -noenc -keyout ec.key -out ec.csr -subj "/CN=a"
$ openssl req -new -newkey ed25519 -noenc -keyout ed.key -out ed.csr -subj "/CN=a"
Ed25519のCSRは、署名アルゴリズムがEd25519になる。一般的な認証局では、Ed25519の証明書を発行できない場合がある。RSAかECDSAを使うのが無難である。
バージョンによる違い
OpenSSL 3.5や3.6でも、ここまでの例は同じように動く。
macOS標準の/usr/bin/openssl(LibreSSL 3.3.6)では、以下が異なる。
-noencに対応していない。代わりに-nodesを使う-verifyの出力がverify OKになる
-addextと設定ファイルでのSAN指定は、LibreSSL 3.3.6でも使える。
