mTLS・RSA・CSRの基礎
相互TLS認証(mTLS)の仕組みを理解するために必要なRSA鍵ペア、CSRの作成と用途指定(Key Usage / EKU)をまとめて解説する
TL;DR
- RSAは公開鍵暗号方式。秘密鍵で署名し、公開鍵で検証する
- CSRはCAに「この公開鍵で証明書を発行してほしい」と申請する際のリクエストファイル。Key Usage / EKU(Extended Key Usage)で用途を指定する
- mTLSはサーバーだけでなくクライアントも証明書を提示する双方向の認証。API間通信や内部サービスのゼロトラスト構成に使われる
RSAとは
RSA(Rivest–Shamir–Adleman)は 公開鍵暗号方式 の一つ。
「秘密鍵」と「公開鍵」のペアを使う。
| 鍵 | 役割 |
|---|---|
| 秘密鍵(private key) | 自分だけが持つ。署名・復号に使う |
| 公開鍵(public key) | 誰でも持てる。検証・暗号化に使う |
TLSの文脈では、サーバーは秘密鍵を使ってハンドシェイクに応じ、クライアントはサーバーの公開鍵(証明書に含まれる)を使って相手を検証する。
# RSA秘密鍵の生成(2048bit または 4096bit が一般的)
openssl genrsa -out server.key 2048
# 公開鍵だけ取り出す場合
openssl rsa -in server.key -pubout -out server.pubCSR(Certificate Signing Request)とは
CSRは「この公開鍵をもとに証明書を発行してほしい」という 申請書 のようなもの。
CA(認証局)や自己署名用の手順でCSRを経由して証明書(.crt)が発行される。
CSRには次の情報が含まれる。
- Subject(CN, O, C など)
- 公開鍵
- Key Usage / Extended Key Usage(用途の指定)
- Subject Alternative Name(SAN)(ドメイン名 / IP)
CSRの作成
# 秘密鍵とCSRをまとめて生成
openssl req -new -newkey rsa:2048 -nodes \
-keyout client.key \
-out client.csr \
-subj "/CN=my-client/O=MyOrg/C=JP"Key Usage と Extended Key Usage(EKU)
証明書の 用途を制限するフィールド。これを正しく指定しないと、意図しない用途に使われたり、一部のクライアントライブラリが接続を拒否したりする。
Key Usage(主な値)
| 値 | 意味 |
|---|---|
digitalSignature | 署名(TLSハンドシェイク等)に使える |
keyEncipherment | 鍵の暗号化(RSA鍵交換)に使える |
keyCertSign | 下位証明書への署名(CA専用) |
cRLSign | CRL署名(CA専用) |
Extended Key Usage(EKU)(主な値)
| 値 | 用途 |
|---|---|
serverAuth | TLSサーバー認証(HTTPS等) |
clientAuth | TLSクライアント認証(mTLS等) |
codeSigning | コード署名 |
emailProtection | S/MIME等のメール署名 |
設定ファイルで用途を指定する例
CSRや証明書に Key Usage / EKU を含めるには、OpenSSLの設定ファイルを使うか -extfile で拡張を渡す。
# ext-client.cnf
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = my-client.internal# CSRと秘密鍵を生成
openssl req -new -newkey rsa:2048 -nodes \
-keyout client.key \
-out client.csr \
-subj "/CN=my-client/O=MyOrg/C=JP"
# CA秘密鍵・CA証明書で署名して証明書を発行(自己CAの場合)
openssl x509 -req \
-in client.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt \
-days 365 \
-extfile ext-client.cnf \
-extensions v3_reqmTLS(Mutual TLS)とは
TLSはHTTPS等で使われる通信の暗号化・認証プロトコル。通常は サーバーだけ が証明書を提示するが、mTLSではクライアントも提示する。
通常のTLS(一方向TLS)では サーバーだけ が証明書を提示し、クライアントはそれを検証する。
mTLS(相互TLS)では クライアントも証明書を提示 し、サーバーがそれを検証する。
通常のTLS:
Client → サーバーの証明書を検証 → 接続
mTLS:
Client → サーバーの証明書を検証 → 接続
Server → クライアントの証明書を検証 → 接続いつ使うか
- マイクロサービス間のAPI通信(内部サービス同士を証明書で認証)
- ゼロトラスト構成(IPや位置ではなくIDで認証)
- 外部からのアクセスをB2Bに限定したいAPIエンドポイント
証明書チェーンの全体像
mTLSを自己CAで構築する場合の一般的な手順。
1. CA(認証局)の秘密鍵・自己署名証明書を生成
2. サーバー用に: 秘密鍵 → CSR(serverAuth) → CA署名 → 証明書
3. クライアント用に: 秘密鍵 → CSR(clientAuth) → CA署名 → 証明書
4. サーバーに ca.crt を渡し、クライアント証明書の検証に使わせる
5. クライアントに ca.crt, client.crt, client.key を渡すCA作成
# CA秘密鍵
openssl genrsa -out ca.key 4096
# CA自己署名証明書
openssl req -x509 -new -nodes \
-key ca.key \
-sha256 -days 3650 \
-out ca.crt \
-subj "/CN=MyCA/O=MyOrg/C=JP"サーバー証明書(serverAuth)
openssl req -new -newkey rsa:2048 -nodes \
-keyout server.key -out server.csr \
-subj "/CN=api.myservice.internal/O=MyOrg/C=JP"
# ext-server.cnf で extendedKeyUsage = serverAuth を指定
openssl x509 -req \
-in server.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt \
-days 365 \
-extfile ext-server.cnf -extensions v3_reqクライアント証明書(clientAuth)
openssl req -new -newkey rsa:2048 -nodes \
-keyout client.key -out client.csr \
-subj "/CN=my-client/O=MyOrg/C=JP"
# ext-client.cnf で extendedKeyUsage = clientAuth を指定
openssl x509 -req \
-in client.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt \
-days 365 \
-extfile ext-client.cnf -extensions v3_req証明書の内容を確認する
# 証明書の内容を人が読める形で確認
openssl x509 -in client.crt -text -noout
# CSRの内容確認
openssl req -in client.csr -text -nooutKey Usage / EKU が意図通り含まれているか、必ずここで確認する。
よくある落とし穴
EKUがない証明書をmTLSに使うと拒否される
Go や OpenSSL の新しいバージョンは clientAuth EKU がない証明書を拒否することがある。必ず extendedKeyUsage = clientAuth を付けて発行する。
SANがないと一部クライアントで接続できない
CNだけでは不十分なクライアントがある(Chrome等)。subjectAltName を証明書に含める。
CAの証明書を双方に配布しないと検証できない
クライアント側にも ca.crt を渡し、--cacert や trust store に追加する。
証明書の有効期限
自動更新の仕組みがないと気づかず失効する。発行日と有効期限を管理する。
curlでmTLSを試す
curl https://api.myservice.internal \
--cacert ca.crt \
--cert client.crt \
--key client.key