証明書の作り方〜ルート認証局〜

[link-intro]:https://qiita.com/gazami/items/efda6bbfba632441e125
[link-root]:https://qiita.com/gazami/items/2c54a0958c307f479961

# 前回までの記事
* [導入][link-intro]

# ルート認証局を作る
ルート認証局は，自己署名で作る．これはみんな大好き，オレオレ認証局である．
次のようなファイル構成を目指す．

```shell-session
/etc/pki/
├── tls/
│   └── openssl_root.cnf  # ルートCA用コンフィグ
└── RootCA/
    ├── cacert.pem        # ルートCA証明書
    ├── certs/
    ├── crl/
    ├── index.txt
    ├── newcerts/
    ├── private/          # 権限 600
    │   └── cakey.pem     # ルートCAの秘密鍵，権限 600
    └── serial
```

## 準備
コンフィグファイルを作ったり，必要なディレクトリやファイルを作ったり．

### コンフィグファイル
openssl.cnfからopenssl_root.cnfを作る．

```shell-session
[~]# cd /etc/pki/tls
[tls]# cp openssl.cnf openssl_root.cnf
```

openssl_root.cnfの編集箇所は次の通り．

```config:openssl_root.cnf
[ CA_default ]
:
dir		= /etc/pki/RootCA	# Where everything is kept
:
[ v3_ca ]
:
keyUsage = cRLSign, keyCertSign
:
```

`keyUsage`を設定しないと，何でもかんでもできるルート認証局ができる．まあ，実験なら何でもできたって別に構わないのだが，こういう設定があるなら使っておかないと，知らないまま本番環境を作ったりしそうだし．以前は`nsCertType`というのを使っていたようだが，ブラウザにインストールされてる最近の証明書を見ると`keyUsage`を使うのが最近のやり方らしい．

### ルート認証局用のディレクトリ作成
必要なディレクトリとかファイルとか作る．

```shell-session
[~]# mkdir /etc/pki/RootCA
[~]# cd /etc/pki/RootCA
[RootCA]# mkdir certs crl newcerts private
[RootCA]# chmod 600 private
[RootCA]# echo 01 > serial
[RootCA]# touch index.txt
```

## 構築
ルート認証局の秘密鍵と証明書を作る．
次のコマンドを実行．

```shell-session
[RootCA]# openssl req -new -x509 -days 3650 \
-config ../tls/openssl_root.cnf \
-out ./cacert.pem \
-keyout ./private/cakey.pem
```

実行すると，こんな感じ．

```shell-session
Generating a 2048 bit RSA private key
.......+++
.............................+++
writing new private key to './private/cakey.pem'
Enter PEM pass phrase:<ルート認証局用パスワード>
Verifying - Enter PEM pass phrase:<ルート認証局用パスワード>
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [JP]:
State or Province Name (full name) [Kanagawa]:
Locality Name (eg, city) [Yokohama]:
Organization Name (eg, company) [Default Company Ltd]:Matoi
Organizational Unit Name (eg, section) []:    
Common Name (eg, your name or your server's hostname) []:root.ca.myhost
Email Address []:
```

<ルート認証局用パスワード>は中間認証局の署名で使うので，忘れないようにしておく．実験環境だけなら，どうせ信頼できない認証局なのだから`root`とでもしておけば良いんじゃね？どうするかはお好きなように．4文字以上が必須．

Country NameとかStateとか適当に入れていく．デフォルトの値で良ければ，そのままEnterを押していけば良い．Common Nameはルート認証局の名前を入れておく．ここではドメイン名っぽく書いてあるが，よその証明書を見ると普通の文字列で大丈夫のようだ．ただし，他の証明書とは衝突しない，ユニークな文字列にしておかないといけないようだ．

これで，秘密鍵とルート証明書ができた．ルート証明書は自己署名で作るので，よその認証局に署名してもらう必要は無い．

一応，秘密鍵の権限を変更しておく．

```shell-session
[RootCA]# chmod 600 ./private/cakey.pem
```

これで，ルート認証局ができた．

## 再構築
一度ルート認証局を作った後にコンフィグファイルを書き換えて，秘密鍵はそのままで再構築するには次のコマンドを実行．

```shell-session
[RootCA]# openssl req -x509 -days 3650 \
-config ../tls/openssl_root.cnf \
-out ./cacert.pem \
-key ./private/cakey.pem
```

最初にルート認証局を作った時のパスワードを入力すれば，後は同じ．

# 補足
ここでは実験のため，10年（`-days 3650`オプション）使える証明書等を作っているが，実際の運用でこれは長すぎる．2018年3月1日以降，SSL証明書の最大有効期間は2年となっている（それまでは3年）．

[SSL Certificates Will Now Be Capped At Two Years of Validity](https://www.thesslstore.com/blog/cab-forum-ballot-193/)
[SSL証明書の有効期限は2年に短縮される（2018年3月1日施行）](https://rms.ne.jp/digital-certificate-news/ballot-193)

信頼できる各認証局はこれに従っていて，発行可能な証明書の最大有効期間を2年にしているようだ．
実運用なら最大で2年にすべきだが，実験だけなら10年であっても特に問題無く使うことができると思う．証明書の有効期間を見て，はじくシステムはそうそう無いと思う．

# これからやること

* [中間認証局を作る][link-int]
* [サーバ証明書を作る][link-server]
* [nginxでTLSを設定する][link-nginx]
* [Webブラウザにルート証明書をインポートする][link-browser]
* [クライアント認証][link-client]