RSA鍵、証明書のファイルフォーマットについて

RSAの公開鍵暗号技術を利用するためには、鍵や証明書のファイルを扱う必要があるため、そのファイルフォーマットについて理解しておく必要があります。

実際、いろんな拡張子が登場するので、それぞれの意味を理解していないとすぐにわけがわからなくなります。そんなときのために備忘録をまとめてみました。

# ファイルの拡張子の注意点
## .DERと .PEMという拡張子は鍵の中身じゃなくて、エンコーディングを表している

デジタル暗号化鍵やデジタル証明書はバイナリデータなのですが、MD5のハッシュ値のような単なる **値** ではなく、データ構造をもっています。.DERや .PEMはそのデータ構造をどういうフォーマットでエンコードしているかを表しています。そのため、.DERや.PEMという拡張子からそのファイルが何を表しているのかはわかりません。暗号化鍵の場合もあるし、証明書の場合もあります。

- .DER
	- 鍵や証明書をASN.1というデータ構造で表し、それをシリアライズしたバイナリファイルです。
	- ASN.1というのはISOやITU-Tで定められたデータ構造の記述方法で、DERというのはそれのシリアライズ方法(エンコーディング)の一つです。なので、全然暗号化とは関係無いものに使われていることもあります。詳しくは[こちら](https://web.archive.org/web/20190306230043/http://www.geocities.co.jp/SiliconValley-SanJose/3377/)をご覧ください(Geocitiesのページですが、サービスが終了してしまったのでそのアーカイブへのリンクになります)。
	- DERはバイナリエンコードなので、そのままでは文字列化できません。
	- opensslコマンドで扱う場合は -inform der オプションなどを使って、ファイルフォーマットが DERエンコーディングであることを指定する必要があります。
- .PEM
	- .DERと同じASN.1のバイナリデータをBase64によってテキスト化されたファイルです。
	- ファイルの先頭に ` -- BEGIN...` という行があるのをみたら「PEMだな」と思えば良いです。
	- opensslコマンドのデフォルトのエンコーディングなので、たとえば何も指定せずに鍵を生成すると PEM形式のファイルが作られます。


## .CRT .CER .KEY .CSRはファイルのエンコーディングではなく内容を表している

.DERや.PEMは中身に関係なく、エンコーディングの種類を表していましたが、逆に .CRTなどの拡張子はエンコーディングが何であるかは関係がなく、 **そのファイルが何のファイルなのか** を表しています。

- .CRT
	- Certificate、つまり証明書であることを示しています。
	- エンコーディングは DERだったり PEMだったりします。中身がテキストファイルなら PEMと思えばいいでしょう。
	- 証明書というのは何を証明しているかというと、 **公開鍵が誰の公開鍵であるかを証明している** ものです。なので、中身には公開鍵も含まれています。公開鍵と言いながら .CRTファイルを扱っているケースがあるのはそのためです。
		- **証明書=署名付き公開鍵** と言ってもいいかもしれません
- .CER
	- こちらも Certificateの略、つまり証明書です。マイクロソフトが使っている拡張子の取り決めで使われています。
	- 中身は.CRTと同じです。
- .KEY
	- そのまま「鍵」です。公開鍵、あるいは秘密鍵であることを表しています。
	- エンコーディングは DERあるいは PEMです。

## .p12は、PKCS#12個人情報交換ファイルフォーマットを表している

.p12という拡張子については、[PKCS #12 個人情報交換ファイルフォーマットについて](http://qiita.com/kunichiko/items/3e2ec27928a95630a73a)を参照してください。

# 秘密鍵と公開鍵の生成

## RSA秘密鍵の生成

`openssl genrsa` コマンドを使うとRSAの秘密鍵を生成することができます。

```
> openssl genrsa 1024 > private-key.pem
Generating RSA private key, 1024 bit long modulus
..................++++++
........................................++++++
e is 65537 (0x10001)
```

標準出力出力される鍵はPEMエンコードされているので、ファイル名も.pemとしています。秘密鍵であることがわかるように、private という文字列をファイル名に入れておくと良いでしょう。

## RSA公開鍵の生成
RSAでは秘密鍵があればいつでも公開鍵を生成することができます。`openssl rsa` コマンドを使用して先ほど作成した秘密鍵を読み込ませ、-pubout で公開鍵を出力します。

```
> openssl rsa -in private-key.pem -pubout -out public-key.pem
writing RSA key
```

-outform オプションを指定していないので、PEMエンコードされた公開鍵が出力されます。公開鍵であることがわかるようにpublic-key.pem としています。


# エンコードされたファイルの中身を見る方法
上述のとおり、鍵や証明書のファイルはバイナリファイルだったりそれをBase64エンコードしただけのものなので、テキストエディタなどで中身を見ることができません。この中身をダンプできるようになると後のデバッグが非常にやりやすくなるので是非覚えておきましょう。

## 秘密鍵の中身を見る方法

先ほど作成した秘密鍵の中身を見てみます。

```
> openssl rsa -in private-key.pem -text -noout
Private-Key: (1024 bit)
modulus:
    00:e4:56:a1:6b:90:ce:f5:54:37:61:ca:a4:be:9a:
    e5:62:0f:70:d7:7f:89:f4:40:82:2e:3e:d6:ab:b2:
    7d:d2:fb:51:b1:72:6b:62:a0:f2:5d:0f:34:c2:1b:
    dd:a2:53:52:18:eb:ea:fa:e2:5d:ad:db:c2:10:cf:
    ac:66:01:7c:27:55:49:14:d9:ae:6d:d2:99:a1:2d:
    e2:d4:ed:45:bc:18:d6:17:7c:08:3d:5b:05:12:52:
    c5:14:1c:00:37:50:c7:28:e0:87:7f:d2:05:a3:38:
    34:fc:2a:92:6d:7d:53:21:7d:2e:45:cd:d1:54:b7:
    54:0a:b3:2e:5d:0c:db:c2:1f
publicExponent: 65537 (0x10001)
privateExponent:
    00:d3:d8:37:ec:f7:2d:bb:d8:c5:85:1a:20:1c:a2:
    d2:fc:56:7d:07:c2:51:38:66:7d:20:f0:b5:f4:18:
    26:ba:8e:e6:ad:2e:0d:c9:34:af:87:7d:2b:22:87:
    fd:e9:b3:49:f0:cb:38:78:49:7a:46:6a:23:b3:bb:
    29:24:7e:6e:32:c3:3d:a0:fc:a9:23:51:79:b4:59:
    f7:dd:9e:57:ca:52:cb:cd:e1:fe:8c:9a:3c:18:22:
    a0:36:be:c2:8b:44:44:32:7f:4b:c6:34:ad:1a:dc:
    e3:9b:a2:fa:86:c8:9f:d0:da:38:ee:88:d5:f5:33:
    45:2b:7e:0e:eb:e8:5d:da:61
prime1:
    00:f3:f4:3c:25:ed:78:93:12:30:04:ae:95:00:17:
    87:f4:43:87:e6:66:71:28:98:96:c3:d8:21:6d:8a:
    3f:a4:45:31:3d:fb:09:fb:4a:b3:38:6d:9a:ca:ba:
    bc:47:65:e2:84:20:52:a6:46:a9:42:7e:b8:82:69:
    2f:38:72:73:8f
prime2:
    00:ef:9d:00:81:5b:0f:59:7c:4f:88:d6:1b:d5:b2:
    a4:02:30:c4:e7:a2:73:b2:6d:59:31:e2:6d:d5:5a:
    c1:8e:22:ff:04:8d:15:e5:78:20:3a:75:d4:18:3c:
    aa:43:53:5e:95:72:9b:5f:df:a8:ba:25:6d:75:b4:
    3b:8d:dd:40:71
exponent1:
    08:27:df:26:e9:74:81:7e:37:2a:c0:e7:6c:54:5d:
    10:36:7d:c1:9f:25:23:55:4e:9d:07:89:be:8e:c3:
    a7:eb:44:45:2d:32:5d:3b:57:18:88:d9:86:f3:8d:
    3d:d9:d3:23:d5:ac:cd:b0:49:12:57:08:36:1b:ec:
    1f:37:fc:53
exponent2:
    78:a2:7f:d5:a0:65:ca:f4:b6:0a:3b:59:8a:2e:45:
    3a:41:19:71:51:2d:94:a0:4e:ee:b9:83:f8:8d:97:
    b3:1a:d5:6f:92:24:7b:02:0e:9f:c0:20:c7:0f:0b:
    dd:97:84:a0:13:32:3c:83:9b:2c:14:99:d6:4f:a6:
    48:17:23:51
coefficient:
    00:b5:74:c2:20:d1:57:16:f3:02:05:be:0a:78:f5:
    ea:52:05:e0:c6:b1:46:80:5c:7a:62:18:1f:d2:e9:
    61:34:6c:71:2e:97:e5:f7:b0:4e:0c:d7:c8:31:8e:
    e7:a8:cd:8b:51:49:70:73:60:ff:3b:41:76:46:c1:
    0a:28:93:97:ea
```

これで、ファイルの中身が確かにRSAの秘密鍵であることがわかります。いろいろ入っていますが、prime というのは素数という意味です。prime1と prime2という２つの素数から秘密鍵が作られているのが確認できます。

なお、上記例は鍵ファイルがPEMエンコードされている場合でしたが、もしDERエンコードされている場合は `-inform der` というオプションを指定してください。

```
> openssl rsa -in private-key.der -inform der -text -noout
```

## 公開鍵の中身を見る方法

同様にして公開鍵の中身を見ることもできます。`openssl rsa -pubin` コマンドを使います。

```
> openssl rsa -pubin -in public-key.pem -text -noout
Modulus (1024 bit):
    00:e4:56:a1:6b:90:ce:f5:54:37:61:ca:a4:be:9a:
    e5:62:0f:70:d7:7f:89:f4:40:82:2e:3e:d6:ab:b2:
    7d:d2:fb:51:b1:72:6b:62:a0:f2:5d:0f:34:c2:1b:
    dd:a2:53:52:18:eb:ea:fa:e2:5d:ad:db:c2:10:cf:
    ac:66:01:7c:27:55:49:14:d9:ae:6d:d2:99:a1:2d:
    e2:d4:ed:45:bc:18:d6:17:7c:08:3d:5b:05:12:52:
    c5:14:1c:00:37:50:c7:28:e0:87:7f:d2:05:a3:38:
    34:fc:2a:92:6d:7d:53:21:7d:2e:45:cd:d1:54:b7:
    54:0a:b3:2e:5d:0c:db:c2:1f
Exponent: 65537 (0x10001)
```

なお、上記例は鍵ファイルがPEMエンコードされている場合でしたが、もしDERエンコードされている場合は `-inform der` というオプションを指定してください。

## 証明書の中身を見る方法

証明書の場合は`openssl x509` コマンドを使います。

```
> openssl x509 -in public-key.crt -text -noout
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            b0:a6:d9:14:7e:56:22:56
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=JP, ST=Tokyo, L=Shibuya, O=Ripplex Inc.
        Validity
            Not Before: Dec 26 02:53:29 2014 GMT
            Not After : Jan 25 02:53:29 2015 GMT
        Subject: C=JP, ST=Tokyo, L=Shibuya, O=Ripplex Inc.
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:e4:56:a1:6b:90:ce:f5:54:37:61:ca:a4:be:9a:
                    e5:62:0f:70:d7:7f:89:f4:40:82:2e:3e:d6:ab:b2:
                    7d:d2:fb:51:b1:72:6b:62:a0:f2:5d:0f:34:c2:1b:
                    dd:a2:53:52:18:eb:ea:fa:e2:5d:ad:db:c2:10:cf:
                    ac:66:01:7c:27:55:49:14:d9:ae:6d:d2:99:a1:2d:
                    e2:d4:ed:45:bc:18:d6:17:7c:08:3d:5b:05:12:52:
                    c5:14:1c:00:37:50:c7:28:e0:87:7f:d2:05:a3:38:
                    34:fc:2a:92:6d:7d:53:21:7d:2e:45:cd:d1:54:b7:
                    54:0a:b3:2e:5d:0c:db:c2:1f
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha1WithRSAEncryption
        6a:51:c4:b9:e5:f2:d6:14:6c:88:d3:8b:20:75:54:45:ad:63:
        43:f6:6b:68:73:77:96:63:af:b0:45:60:c5:75:2d:94:17:a2:
        63:5e:18:a5:0d:a5:60:c5:fb:a2:94:26:ed:ae:35:f1:56:a1:
        34:0c:b3:1e:3f:47:6e:e1:92:4a:86:62:cb:8e:aa:aa:0d:1b:
        ec:08:0d:6d:a5:e4:af:79:97:bb:e6:d4:a5:82:09:7a:46:2a:
        30:14:a6:79:c4:b8:e7:57:fc:59:70:37:15:77:08:b6:7a:c0:
        d8:b0:9b:ce:1f:31:4c:74:54:12:e8:e7:f4:9e:36:aa:5c:17:
        85:32
```

なお、証明書もDERエンコードされている場合があります。その場合も `-inform der` というオプションを指定してください。

# エンコーディングの変換方法
上述の通り、暗号鍵や証明書にはDERとPEMの二つのエンコーディングがあります。ライブラリによってはDER形式しか読み込めないものなどがあるので、opensslコマンドを使った相互変換の方法をまとめておきます。

注意すべき点は、 **DERをPEMに変換する汎用的な方法があるわけではない** という点です。あくまで opensslにファイルを読み込ませ、もう一度別のエンコーディングで書き出させることでエンコーディングを変換します。ですので、 **opensslコマンドに該当ファイルを認識させ、正しく読み込ませる** というところが重要です。

### PEM形式の秘密鍵 <=> DER形式の秘密鍵
`openssl rsa`コマンドを使うと、RSAの秘密鍵を使った処理が行えます。

- -in で読み込む秘密鍵を指定
- -out で書き出すファイルを指定
- -outform で書き出すファイルのエンコーディングを指定

という３つのオプションを指定すればOKです。

```
> openssl rsa -in private-key.pem -out private-key.der -outform der
```

このコマンドはあくまで **PEM形式のRSA秘密鍵を読み込み、DER形式でRSA秘密鍵を書き出すコマンド** です。なのでこのファイルの中身が秘密鍵ではなくて証明書だったり公開鍵だった場合はエラーになります。「openssl pem to der」などのキーワードでググって出てきたコマンドをそのまま入れてもうまく動かない場合がありますが、そのときは大抵、フォーカスしているファイルの **中身** が違います。

逆変換は以下の通りです。

```
> openssl rsa -in private-key.der -inform der -out private-key.pem
```

opensslは指定しないとpem形式のファイルとして扱おうとするので、`-inform der`という指定が必要になります。逆に出力はpemなので`-outform`によるフォーマットの指定は必要がありませんが、`-outform pem`と明示的に指定しても構いません。

### PEM形式の公開鍵 <=> DER形式の公開鍵

上記コマンドに`-pubin`を指定すると、秘密鍵ではなく公開鍵の変換ができます。

```
> openssl rsa -pubin -in public-key.pem -out public-key.der -outform der
```
逆変換は以下の通りです。

```
> openssl rsa -pubin -in public-key.der -inform der -out public-key.pem
```

なお、 **公開鍵** と言った場合に、鍵そのものではなく、証明書(署名付きの公開鍵)のことを指している場合もあります。その場合は rsaコマンドでは取り扱えないので、次の証明書の項を参照してください。

**【重要ポイント】扱うファイルがRSAの鍵なら、コマンドは `openssl rsa` から始まる**

### PEM形式の証明書 <=> DER形式の証明書

鍵ではなく証明書の場合です。多くの場合、ファイルの拡張子は.CRTや.CERになっているはずです。

opensslで証明書を扱う場合は rsa ではなく x509 コマンドを使います。

```
> openssl x509 -in public-key.crt -out public-key.der.crt -outform der
```
逆変換は以下の通りです。

```
> openssl x509 -in public-key.der.crt -inform der -out public-key.crt
```

# 証明書(署名付きの公開鍵)を作成する

実は公開鍵には以下の２つの形態があります。

1. 公開鍵が単体で存在する状態(public-key.key, public-key.der, public-key.pem)
2. 第三者(あるいは自分自身)による署名が施された状態(public-key.crt)

上に出てきた public-key.pem というファイルは 1の状態です。これ以外に、第三者による署名が施された公開鍵というものがあります。 **この2番目の状態の公開鍵のことを証明書といいます**

証明書を発行する、つまり公開鍵に署名を施す為には **証明書署名要求 (Certificate Signing Request, CSR)** というファイルを作成し、署名者に渡す必要があります。公的な機関にお願いする場合は費用が発生しますので、opensslコマンドを使った署名をするシチュエーションの多くは、自分自身の秘密鍵を使った **自己署名証明書** を作る場合だと思いますので、その方法を説明します。

自己署名の場合も一度CSRを作ったうえで署名を行います。CSRは`openssl req`コマンドで作成することができます。なお、 **CSRの作成には秘密鍵が必要** です。公開鍵の所有者であることを第三者に証明してもらうわけですから、秘密鍵を持った人しかできないようになっているわけですね(おそらくCSR自体に署名を施す必要がある)。

```
> openssl req -new -key private-key.pem > my-request.csr
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) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Shibuya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Ripplex Inc
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
```

CSRというのは **「この公開鍵の所有者はどこどこのだれそれさんですよ」というのを別の人(あるいは自分自身)に証明してもらうための申込書** です。上記例では、

- 国 = 日本(JP)
- 州 = 東京都(Tokyo)
- 市 = 渋谷区(Shibuya)
- 組織 = リプレックス株式会社(Ripplex Inc)

で申込書(CSR)を作っています。

## CSRの中身を表示する

CSRを作るときに秘密鍵を指定しているので **「CSRには秘密鍵がはいっているんじゃない？」と心配になるかも** しれません。そんな方は鍵の中身を表示した時と同じように、`openssl req` コマンドに `-text -noout` オプションをつけるとダンプすることができますので、見てみてください。

```
> openssl req -in my-request.csr -text -noout
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=JP, ST=Tokyo, L=Shibuya, O=Ripplex Inc.
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:e4:56:a1:6b:90:ce:f5:54:37:61:ca:a4:be:9a:
                    e5:62:0f:70:d7:7f:89:f4:40:82:2e:3e:d6:ab:b2:
                    7d:d2:fb:51:b1:72:6b:62:a0:f2:5d:0f:34:c2:1b:
                    dd:a2:53:52:18:eb:ea:fa:e2:5d:ad:db:c2:10:cf:
                    ac:66:01:7c:27:55:49:14:d9:ae:6d:d2:99:a1:2d:
                    e2:d4:ed:45:bc:18:d6:17:7c:08:3d:5b:05:12:52:
                    c5:14:1c:00:37:50:c7:28:e0:87:7f:d2:05:a3:38:
                    34:fc:2a:92:6d:7d:53:21:7d:2e:45:cd:d1:54:b7:
                    54:0a:b3:2e:5d:0c:db:c2:1f
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha1WithRSAEncryption
        c0:90:dc:f6:67:dc:21:7a:2f:78:29:dc:0a:88:46:b1:8d:ef:
        55:77:07:20:72:b0:61:9e:ae:bd:f0:f5:0a:c3:a0:77:c0:66:
        2c:e9:08:9b:5e:58:41:31:8b:8d:30:23:91:b4:ba:d4:a2:8f:
        f1:50:0c:a0:08:31:53:14:32:37:1a:b5:18:75:be:bd:6d:0d:
        8b:1e:83:54:0e:4f:19:eb:e4:5c:e9:74:d4:2d:7d:e8:a7:58:
        18:90:30:c0:df:04:ba:88:5b:a7:7c:9e:b9:60:ec:03:ab:bf:
        98:50:15:ae:41:e0:3c:39:08:9f:9d:a3:8c:ec:db:d2:50:2c:
        9d:9c
```

ダンプしてみると、公開鍵は含まれていますが、秘密鍵は含まれていないことがわかります。

## CSRから証明書を発行する

Geo Trustなどの証明書発行機関(CA)は、証明書の発行申込書であるCSR(証明書署名要求)ファイルを受け取って証明書を発行します。その際、申込書(CSR)に書かれた所在地などが正しいかどうかを **人力で確認** して証明書を発行します(だからちゃんとした証明書はお金がかかります)。

こういった CA局では ``openssl x509`` に -reqオプションを付けて CSRを読み込ませることで証明書を発行しています。先ほど作成したCSRを読み込ませて、有効期間が10年(3650日)の証明書を発行する場合のコマンドは以下のようになります。

```
> openssl x509 -req -in my-request.csr -CA ca-crt.pem -CAkey ca-private-key.pem -CAcreateserial -days 3650 -out public-key.crt
```
ここで、

 * -CA ca-crt.pem
    * CA局自身の証明書ファイルを指定
 * -CAkey ca-private-key.pem
    * CA局の秘密鍵（上記 ca-crt.pemの中に書かれている公開鍵に対応する秘密鍵）
 *  -CAcreateserial
    *  証明書に付けるシリアル番号を自動生成（ .srlファイルが作られ、以後実行のたびにインクリメントされる）

となります。じゃあ CA局の証明書はどうやって作るのか？という話になりますが、その場合はさらに上位の CA局にお願いして証明書を発行してもらうことになります。

すると、「一番最上位の CA局の証明書はどうなってんの？」ということになりますが、その場合は、最上位のCA局自身の秘密鍵を使って証明書を発行します。これを **自己署名証明書** と言います。

自己署名証明書を発行する場合は `-CA` オプションの代わりに `-signkey` オプションを使って自分自身の秘密鍵を指定します。

```
> openssl x509 -req -in my-request.csr -signkey private-key.pem -out public-key.crt -days 3650
```

`-signkey`で指定した `private-key.pem` が署名用の秘密鍵で、上の例では自分自身の秘密鍵を指定しています。公開鍵に自分自身の秘密鍵で署名を施して証明書を作っているため、 **自己署名** と言われています。

こうしてできた証明書は第三者による証明のない証明書となります。そんな証明書意味あるの？と疑問に思われるかもしれませんが、自己署名証明書は主に以下の２つのケースで用いられます。

### Case 1. ルート証明局の証明書として

以下のように、SSL接続しているサイトでブラウザの鍵アイコンを開くと、鍵の詳細を見ることができます。この上の方に書かれているツリー構造が証明書チェーンです。

![certificate-chain.png](https://qiita-image-store.s3.amazonaws.com/0/41616/6133f9eb-1db3-9a60-c9ec-351f8cf86514.png "certificate-chain.png")

このような正式な証明書を作成するには、通常、証明書機関にお金を払う必要があります(Let's Encryptのような無料で証明してくれる機関もあります)。

この例の場合は、一番根元の CA局が「GeoTrust Global CA」となっています。これがルート証明局です。ルート証明局の証明書には第三者の署名がありませんが、 **使っているブラウザ(OS)が信用している証明局** となっているため、そこから連なる証明書チェーン、つまりこのサイト自体が信用できるということになっています。

皆さんが使っているOSやブラウザなどは、それらの開発元が予め安全だと信用しているルート証明局をいくつか保持しているため、このような仕組みが成り立っています。もし、それらのルート証明局の中に不正な証明局が含まれてしまうと、ブラウザの暗号通信の根底が揺らいでしまうことになります。そのため、ルート証明局として認められるためには、厳格なセキュリティ監査を受け続けるなどする必要があるのです。

余談ですが、不正な経路で入手したOSやブラウザなどには不正なルート証明局が意図的に紛れ込ませてある可能性があります。ジェイルブレイクなどでOSを改造している場合も、意図的に改竄されている恐れがあり、知らない間に不正な証明書を信用して通信していて中身が盗み見られていた……なんてこともあり得ます。ですので、個人的には **OSやブラウザは信用できるものを使おうね** と啓蒙しております。同じような理由で、野良 DNSサーバーや野良プロキシサーバーを使うのもおすすめしないです(アドレス欄に入力したドメインと全く関係ない所有者のサーバーに誘導される恐れがあるため)。

### Case 2. 独自システムにおける独自ルート証明書(通称 "オレオレ証明書")として

インターネット上で皆が利用するルートCA局は、上記の通り限られた機関だけが存在を許されていて、それによって安全性を担保しているわけですが、逆に言えば、独自システムであれば独自に信用しているルートCA局を立てることもできます。

例えばイントラネットなどのように外部から隔離されたネット上で独自にサーバーを立てている場合、家庭内LANに独自のサーバーを立てる場合などは、限られたクライアントからのみアクセスされますので、アクセスしてくる全てのクライアントに独自のルート証明書を配布してしまえば良いのです。(逆に言えば、インターネットに公開したいサービスの場合は、全クライアントに独自証明書を配ってインストールしてもらうわけにはいかないため、きちんとしたルート証明局によって証明してもらう必要がある)

こういった **自分の知っている範囲でのみ通じる証明書で十分** というケースであれば、自分自身の鍵で署名された **自己署名証明書(通称"オレオレ証明書")** を使うことも可能です。


## 証明書から公開鍵を取り出す

証明書には公開鍵が含まれているので、それを取り出すこともできます。`openssl x509` で証明書を読み込み、-pubkeyオプションをつけると公開鍵が出力されます。

```
> openssl x509 -in public-key.crt -pubkey 
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkVqFrkM71VDdhyqS+muViD3DX
f4n0QIIuPtarsn3S+1GxcmtioPJdDzTCG92iU1IY6+r64l2t28IQz6xmAXwnVUkU
2a5t0pmhLeLU7UW8GNYXfAg9WwUSUsUUHAA3UMco4Id/0gWjODT8KpJtfVMhfS5F
zdFUt1QKsy5dDNvCHwIDAQAB
-----END PUBLIC KEY-----
-----BEGIN CERTIFICATE-----
MIICAzCCAWwCCQCgYvbe6d0oLzANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJK
UDEOMAwGA1UECBMFVG9reW8xEDAOBgNVBAcTB1NoaWJ1eWExFTATBgNVBAoTDFJp
cHBsZXggSW5jLjAeFw0xNTAxMDYwNjU1MjJaFw0yNTAxMDMwNjU1MjJaMEYxCzAJ
BgNVBAYTAkpQMQ4wDAYDVQQIEwVUb2t5bzEQMA4GA1UEBxMHU2hpYnV5YTEVMBMG
A1UEChMMUmlwcGxleCBJbmMuMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDk
VqFrkM71VDdhyqS+muViD3DXf4n0QIIuPtarsn3S+1GxcmtioPJdDzTCG92iU1IY
6+r64l2t28IQz6xmAXwnVUkU2a5t0pmhLeLU7UW8GNYXfAg9WwUSUsUUHAA3UMco
4Id/0gWjODT8KpJtfVMhfS5FzdFUt1QKsy5dDNvCHwIDAQABMA0GCSqGSIb3DQEB
BQUAA4GBAC/D6RWTTeshiWvrwwyU98aP47DVxzUhUbfR3HHaAe3r++/FlUlRsvZN
PPKjAjLdIOuzHPOPFbmOUzb+T8uPZp1P7oGe+g1MmjgyR9soKPETiLirCqa4sLfz
GTfdh3X/RrSfugcjHPJmfgtpLDml6K1ikulyPDH56l8/AKulJxLx
-----END CERTIFICATE-----
```

これだと、読み込んだ証明書も出力されてしまうので、`-noout` をつけると公開鍵の出力だけになります。

```
> openssl x509 -in public-key.crt -pubkey -noout
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkVqFrkM71VDdhyqS+muViD3DX
f4n0QIIuPtarsn3S+1GxcmtioPJdDzTCG92iU1IY6+r64l2t28IQz6xmAXwnVUkU
2a5t0pmhLeLU7UW8GNYXfAg9WwUSUsUUHAA3UMco4Id/0gWjODT8KpJtfVMhfS5F
zdFUt1QKsy5dDNvCHwIDAQAB
-----END PUBLIC KEY-----
```

これはPEM形式なので、リダイレクトして、PEMファイルとして保存できます。

```
> openssl x509 -in public-key.crt -pubkey -noout > public-key-recovered.pem
```

# まとめ
以上の説明で、opensslコマンドを使った鍵や証明書の操作は一通りできるようになると思います。

RSA周りの開発をする場合は上記操作をさくさくできるようになっていると作業がはかどりますので、是非トライしてみてください。