OpenSSLによるオレオレ認証局が署名した証明書の作成

opensslコマンドを使って、オレオレ認証局（CA）を作成し、そのオレオレCAが署名した証明書を作成する流れについて、たまにやるけどすぐに忘れるのでまとめ。

## CA証明書の作成

### CAの秘密鍵の作成

RSA秘密鍵を作成する。

```
openssl genrsa 2048 > ca.key
```

- `-out`でファイルを指定しても、標準出力をリダイレクトでファイルに書き込んでもどちらでもよい

`-----BEGIN RSA PRIVATE KEY-----`で始まるファイルができる。`-----BEGIN`で始まるファイルはPEM形式のファイルである。鍵や証明書のファイルによく使われる拡張子にはばらつきがあり、`.pem`とか`.der`というのはファイルのエンコーディングを表しているが、`.crt`や`.cer`や`.key`や`.csr`というのはファイルの内容を表している。

秘密鍵の内容を確認する。

```
openssl rsa -text -noout -in ca.key
```

### 公開鍵の作成

秘密鍵から公開鍵を作成する。この後この公開鍵を直接使うわけではないのでオプション。

```
openssl rsa -in ca.key -pubout -out ca-public.key
```

`-----BEGIN PUBLIC KEY-----`で始まるファイルができる。

（参考）

`-pubout`ではなく`-RSAPublicKey_out`を指定すると、`RSA PUBLIC KEY`ができる。`PUBLIC KEY`の場合は先頭の32文字にRSAかDHかECかを示す情報がついているが中身は同じであり、先頭の32文字を取り除いて改行をそろえれば同じになる。

- [How can I transform between the two styles of public key format, one “BEGIN RSA PUBLIC KEY”, the other is “BEGIN PUBLIC KEY”](https://stackoverflow.com/questions/18039401/how-can-i-transform-between-the-two-styles-of-public-key-format-one-begin-rsa)

（参考）

よくSSHの公開鍵認証のセットアップで使う`ssh-keygen`コマンドで鍵ペアを生成した場合、`id_rsa`はPEM形式だが、`id_rsa.pub`はOpenSSHの独自形式のファイルである。このファイルは以下のコマンドでPEM形式に変換できる。

```
ssh-keygen -f id_rsa.pub -e -m pem
```

`-m pem`で`RSA PUBLIC KEY`になる。`-m pkcs8`だと`PUBLIC KEY`になる。`-m ssh2`あるいは`-m`を指定しない場合は`SSH2 PUBLIC KEY`になる。

### 証明書署名要求の作成

秘密鍵から証明書署名要求（CSR）を作成する。

```
openssl req -new -key ca.key -subj "/CN=rootca" > ca.csr
```

- `-subj`を指定しない場合は対話式での入力になる

`-----BEGIN CERTIFICATE REQUEST-----`ではじまるファイルができる。

CSRの内容を確認する。

```
openssl req -text -noout -in ca.csr
```

### 証明書の作成（認証局による公開鍵への自己署名）

証明書署名要求に秘密鍵で署名する（自己署名）。

```
openssl x509 -req -in ca.csr -signkey ca.key -days 10000 -out ca.crt 
```

`-----BEGIN CERTIFICATE-----`ではじまるファイルができる。

証明書の内容を確認する。

```
openssl x509 -text -noout -in ca.crt
```

（参考）

証明書署名要求の作成と証明書の作成をまとめてやる場合は以下。

```
openssl req -x509 -new -nodes -key ca.key -subj "/CN=rootca" -days 10000 -out ca.crt
```

- `-x509`はOutput a self-signed certificate instead of a certificate request.
- `-nodes`はDo not encrypt private keys.（不要？）
- `-days`は`-x509`と一緒に使う

## 証明書の作成

### 秘密鍵の作成

秘密鍵を作成する。

```
openssl genrsa 2048 > server.key
```

内容を確認する。

```
openssl rsa -text -noout -in server.key
```

### 公開鍵の作成

秘密鍵から公開鍵を作成する（オプション）。

```
openssl rsa -in server.key -pubout -out server-public.key
```

### 証明書署名要求の作成

証明書署名要求を作成する。

```
openssl req -new -key server.key -subj "/CN=servername" > server.csr
```

CSRの内容を確認する。

```
openssl req -text -noout -in server.csr
```

（参考）

マルチドメイン証明書用のCSRを作成する場合は、Subject Alternative Namesのx509v3拡張属性を使う必要があり、以下のようにする。

```csr.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
CN = servername

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = othername1
DNS.2 = othername2

[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
```

```
openssl req -new -key server.key -config csr.conf -out server.csr
```

設定値の詳細は以下を参照。

- [x509v3_config](https://www.openssl.org/docs/manmaster/man5/x509v3_config.html)

### 証明書の作成（認証局による公開鍵への署名）

証明書を作成する（CAの秘密鍵で証明書署名要求に署名する）。

```
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 10000 -out server.crt
```

x509v3拡張属性を使う場合は`-extensions v3_ext`と`-extfile csr.conf`を指定する。

```
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 10000 \
  -extensions v3_ext -extfile csr.conf \
  -out server.crt
```

証明書の内容を確認する。

```
openssl x509 -text -noout -in server.crt
```

（参考）

証明書と秘密鍵をまとめてp12形式で保管する。

```
openssl pkcs12 -export -inkey someserver.key -in someserver.crt -out someserver.p12
```

（参考）

秘密鍵にパスフレーズを付与（暗号化）する。

```
openssl rsa -in someserver.key -aes256 -out someserver-enc.key
```

パスフレーズを付与するとファイルが以下のようになり暗号化されていることがわかる。

```
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,B8B08D49647D820B416C1C6B45607BDC

（以下省略）
```

# 参考リンク

- [RSA鍵、証明書のファイルフォーマットについて](https://qiita.com/kunichiko/items/12cbccaadcbf41c72735)
- [RSA公開鍵のファイル形式とfingerprint](https://qiita.com/hotpepsi/items/128f3a660cee8b5467c6)
- [Certificates](https://kubernetes.io/docs/concepts/cluster-administration/certificates/)
- [opensslでマルチドメイン証明書証明書用のCSRを作成](https://rms-digicert.ne.jp/howto/csr/openssl.html)