SSL通信の仕組みを図で徹底解説

SSL通信とは

はじめに

ブラウザのURLに表示される鍵マークがSSL通信を行っていることを意味しています。ちなみに、この鍵マークを押すとSSL証明書を見ることができます。

ssl-connection-01

これまで、SSL通信の仕組みをちゃんと理解せずとも何とかなっていましたが、最近データベースのSSL通信について問い合わせを受ける機会がありました。

良い機会ですので、改めてSSL通信がどんな仕組みで動いているのか、調べ直してみました。そして、意外と知らないことが多くて焦りました。

SSL通信はエンジニアであれば知ってて当然と思われます。なぜなら、世の中のほぼ全てのサービスがSSL通信で提供されているからです。

今回は、SSL通信がどういう仕組みで動作しているか、図を使って解説していきたいと思います。

参考としたサイト

この記事を書く前に色々なサイトを読み漁りましたが、GMOグローバルサイン、さくらインターネットの解説が最も整理されていると感じましたので載せておきたいと思います。

SSL通信にはサーバー証明書、中間証明書、色々な種類や用途がありまして、そういったことの解説も一通り読んでおくと良いですね。

SSL通信の仕組み

SSL通信をする目的

SSL通信を行う目的は大きく分けて2つあります。

  • サーバーが本物であることの証明
  • クライアントとサーバー間の暗号化通信

これらをどのように実現しているか見ていきましょう。

サーバーが本物であることの証明

認証局(CA)がサーバーを審査します。国内の認証機関であるGMOの説明によりますと、厳密には「認証局は、電子証明書の申請者が提出した所有者情報を審査する機関である登録局」があるそうです。

そして、インターネットサービスを利用するクライアント、サービスを提供するサーバー、認証局(CA)は、以下のような流れでサーバー証明書のやりとりを行います。

ssl-connection-02

流れとしては以下です。

  1. サーバーで秘密鍵を作る。
  2. サーバーで申請書を作る。申請書の中には公開鍵も含まれる。
  3. 認証局(CA)は申請者の情報を審査する。問題なければ、申請書からサーバー証明書を作成する。
  4. サーバー証明書をサーバーに配置する。
  5. クライアントからサーバーに通信するとき、サーバー証明書の署名をルート証明書を使って検証する。
  6. 署名がルート証明書の内容と合致すると判断されれば、サーバーが本物であると判定される。

はい、出ました。ルート証明書とは何でしょうか。私はこのルート証明書の意味を理解していませんでした。

ルート証明書とは

ルート証明書とは、認証局(CA)のオレオレ証明書のことです。認証局(CA)は厳格な監査基準を満たし、セキュリティもばっちりなので、認証局(CA)のオレオレ証明書は信頼が置けるのです。

各種ブラウザには既定でセットされているルート証明書がたくさんあります。Chromでは、ブラウザの「設定」>「セキュリティ」>「証明書の管理」で確認することができます。

ssl-connection-03

ルート証明書を発行する流れを図にすると以下のようになります

ssl-connection-04

上記のように、私の知らないところでルート証明書が既にブラウザにセッティングされていたのでした。なるほど、それでHTTPS通信がどの端末からでも出来るようになっていたのですね。

オレオレ証明書を使って、SSL通信するときはクライアント側でオレオレ証明書をインストールする手順が出てくると思います。その理由は、オレオレ証明書はブラウザに規定でセッティングされていないので、手動でセッティングする必要があったということなんですね。

クライアントとサーバー間の暗号化通信

これまでの流れにおいて、サーバー証明書の正当性は認証局により担保されています。

ssl-connection-05

クライアントとサーバーの暗号化通信は以下の順で達せられます。

  1. クライアントで共通鍵を作成する。
  2. クライアントで共通鍵を公開鍵を使い暗号化してサーバーに送信する。
  3. サーバー側で送信された共通鍵を秘密鍵で複合化する。もともと、クライアントに渡っている公開鍵はサーバーの秘密鍵によって生成されたものですので複合も可能です。
  4. 共通鍵を使ってクライアントとサーバー間でSSL通信が可能となります。

以上がSSL通信の仕組みでした。いや〜、簡単なようで意外と複雑で難しかったですね。

やってみる

実はここからが本題です。理屈は分かっても実際にやってみないことには、本当の理解は得られません。

証明書の中身を見てみる

こちらのQiitaの記事を参考とさせていただいました。

ファイルの拡張子

これから作成するファイルの拡張子は何のファイルかを示しているだけでエンコーディングを表しているわけではありません。

拡張子 意味
.key 秘密鍵、公開鍵で使います。
.csr サーバー証明書の申請書で使います。
.crt サーバー証明書で使います。

やってみる

一通り、鍵の作成からオレオレサーバー証明書の作成まで実施します。

秘密鍵を作ります。

[psgdevvm01admin@psg-dev-vm01 20210213]$ openssl genrsa 1024 > private.key Generating RSA private key, 1024 bit long modulus (2 primes) .....................+++++ .................................+++++ e is 65537 (0x010001)

公開鍵を作ります。

[psgdevvm01admin@psg-dev-vm01 20210213]$ openssl rsa -in private.key -pubout -out public.key writing RSA key

サーバー証明書の申請書を作ります。

[psgdevvm01admin@psg-dev-vm01 20210213]$ openssl req -new -key private.key > private.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) [XX]:ja State or Province Name (full name) []:tokyo Locality Name (eg, city) [Default City]:chuo Organization Name (eg, company) [Default Company Ltd]:Sample Organizational Unit Name (eg, section) []:Develope Common Name (eg, your name or your server's hostname) []:psg-dev-vm01-dgyf3zeehekww.eastus.cloudapp.azure.com Email Address []:sample@sample.co.jp Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:

オレオレのルート証明書を作ります。

[psgdevvm01admin@psg-dev-vm01 20210213]$ openssl x509 -in private.csr -days 365 -req -signkey private.key > root-ca.crt Signature ok subject=C = ja, ST = tokyo, L = chuo, O = Sample, OU = Develope, CN = psg-dev-vm01-dgyf3zeehekww.eastus.cloudapp.azure.com, emailAddress = sample@sample.co.jp Getting Private key

一連のファイルが作成されていることを確認します。

[psgdevvm01admin@psg-dev-vm01 20210213]$ ls private.crt private.csr private.key public.key

申請書(private.csr)に公開鍵(public.key)が含まれていることを確認します。Modulusの内容が一致しています。

[psgdevvm01admin@psg-dev-vm01 20210213]$ # 公開鍵の中身を見る [psgdevvm01admin@psg-dev-vm01 20210213]$ openssl rsa -pubin -in public.key -text -noout RSA Public-Key: (1024 bit) Modulus: 00:c9:20:1b:ca:e7:91:d5:75:46:78:11:24:d7:4b: 17:01:59:53:bd:e0:b1:c2:24:0d:d6:16:e1:9f:b5: 9c:0c:86:b3:a2:f1:0e:e6:7f:c5:72:1b:63:90:e7: 15:f5:73:ce:60:b4:ad:a8:94:e0:c2:b8:71:b2:82: 9b:9f:ae:64:69:c3:69:78:ca:06:6a:dd:54:dd:60: a8:90:8e:81:e7:3f:62:49:5f:be:02:a9:b5:80:ac: fa:8e:36:99:6c:54:46:6a:4b:5d:d7:c9:e4:65:70: b9:0d:58:bf:2b:51:f9:f3:8c:e9:57:ad:d4:74:40: 18:88:38:9b:c8:82:79:b8:77 Exponent: 65537 (0x10001) [psgdevvm01admin@psg-dev-vm01 20210213]$ # 申請書の中身を見る [psgdevvm01admin@psg-dev-vm01 20210213]$ openssl req -in private.csr -text -noout Certificate Request: Data: Version: 1 (0x0) Subject: C = ja, ST = tokyo, L = chuo, O = Sample, OU = Develope, CN = psg-dev-vm01-dgyf3zeehekww.eastus.cloudapp.azure.com, emailAddress = sample@sample.co.jp Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (1024 bit) Modulus: 00:c9:20:1b:ca:e7:91:d5:75:46:78:11:24:d7:4b: 17:01:59:53:bd:e0:b1:c2:24:0d:d6:16:e1:9f:b5: 9c:0c:86:b3:a2:f1:0e:e6:7f:c5:72:1b:63:90:e7: 15:f5:73:ce:60:b4:ad:a8:94:e0:c2:b8:71:b2:82: 9b:9f:ae:64:69:c3:69:78:ca:06:6a:dd:54:dd:60: a8:90:8e:81:e7:3f:62:49:5f:be:02:a9:b5:80:ac: fa:8e:36:99:6c:54:46:6a:4b:5d:d7:c9:e4:65:70: b9:0d:58:bf:2b:51:f9:f3:8c:e9:57:ad:d4:74:40: 18:88:38:9b:c8:82:79:b8:77 Exponent: 65537 (0x10001) Attributes: a0:00 Signature Algorithm: sha256WithRSAEncryption 6d:da:45:91:1b:2e:42:09:d6:f4:de:b7:a6:72:12:13:d3:71: 28:00:6e:33:1b:15:67:f6:49:a0:ef:ae:c7:fa:81:e4:f2:c2: 41:e6:50:e7:39:92:4d:a5:65:53:64:fb:4d:ad:11:47:5d:c1: ad:23:e8:02:73:56:ed:48:d8:00:f7:e0:36:b4:fa:e4:33:27: 40:af:0a:f8:f9:47:1c:8d:29:81:ad:d0:3a:9f:c3:5f:8c:b9: 65:fc:89:97:bd:5a:11:14:dd:59:a7:50:68:d4:1a:1f:ee:b4: e9:43:2b:b5:61:b7:13:3c:02:c2:86:f1:ee:f7:94:98:c9:ff: e7:5b

ルート証明書の内容を確認します。

[psgdevvm01admin@psg-dev-vm01 20210213]$ openssl x509 -in root-ca.crt -text -noout Certificate: Data: Version: 1 (0x0) Serial Number: 17:55:6c:57:69:14:e5:90:62:60:b2:93:c5:f7:b6:a2:a3:de:fb:bc Signature Algorithm: sha256WithRSAEncryption Issuer: C = ja, ST = tokyo, L = chuo, O = Sample, OU = Develope, CN = psg-dev-vm01-dgyf3zeehekww.eastus.cloudapp.azure.com, emailAddress = sample@sample.co.jp Validity Not Before: Feb 13 14:35:28 2021 GMT Not After : Feb 13 14:35:28 2022 GMT Subject: C = ja, ST = tokyo, L = chuo, O = Sample, OU = Develope, CN = psg-dev-vm01-dgyf3zeehekww.eastus.cloudapp.azure.com, emailAddress = sample@sample.co.jp Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (1024 bit) Modulus: 00:c9:20:1b:ca:e7:91:d5:75:46:78:11:24:d7:4b: 17:01:59:53:bd:e0:b1:c2:24:0d:d6:16:e1:9f:b5: 9c:0c:86:b3:a2:f1:0e:e6:7f:c5:72:1b:63:90:e7: 15:f5:73:ce:60:b4:ad:a8:94:e0:c2:b8:71:b2:82: 9b:9f:ae:64:69:c3:69:78:ca:06:6a:dd:54:dd:60: a8:90:8e:81:e7:3f:62:49:5f:be:02:a9:b5:80:ac: fa:8e:36:99:6c:54:46:6a:4b:5d:d7:c9:e4:65:70: b9:0d:58:bf:2b:51:f9:f3:8c:e9:57:ad:d4:74:40: 18:88:38:9b:c8:82:79:b8:77 Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption 21:2a:94:cd:84:08:61:01:f3:1e:83:51:14:38:8c:70:63:e6: 75:25:98:7e:f6:09:05:0f:b8:3e:80:91:e5:2e:8f:33:3a:a3: 18:70:18:27:cb:39:ad:2a:75:86:d6:09:c6:e9:29:c3:7e:f7: d3:ed:da:74:04:ed:57:c8:6e:77:d9:b5:01:5b:89:70:e8:b2: bd:3c:5a:80:33:fc:75:da:94:d1:3c:c4:40:7e:ad:94:3a:51: 6f:e5:96:e8:0d:ea:b1:cc:5b:36:f6:17:01:a1:04:2d:25:7f: e6:49:45:c0:6f:32:bc:71:f9:dc:0c:fc:9a:27:47:43:26:ca: 8e:13

オレオレ認証局によるサーバー証明書発行

続いて、別の秘密鍵を作成して、オレオレ認証局によるサーバー証明書を発行していきます。

手順は先ほどと、ほぼ同様なのでコマンドだけ記載していきます。

[psgdevvm01admin@psg-dev-vm01 20210213]$ # 秘密鍵を作成 [psgdevvm01admin@psg-dev-vm01 20210213]$ openssl genrsa 1024 > private2.key [psgdevvm01admin@psg-dev-vm01 20210213]$ # 申請書を作成 [psgdevvm01admin@psg-dev-vm01 20210213]$ openssl req -new -key private2.key > private2.csr [psgdevvm01admin@psg-dev-vm01 20210213]$ # サーバー証明書を作成 [psgdevvm01admin@psg-dev-vm01 20210213]$ openssl x509 -req -in private2.csr -CA root-ca.crt -CAkey private.key -CAcreateserial -days 365 -out private2.crt [psgdevvm01admin@psg-dev-vm01 20210213]$ # 申請書の中身を確認 [psgdevvm01admin@psg-dev-vm01 20210213]$ openssl req -in private2.csr -text -noout Certificate Request: Data: Version: 1 (0x0) Subject: C = ja, ST = kanagawa, L = yokohama, O = rainbow-bridge, OU = sales, CN = psg-dev-vm01-dgyf3zeehekww.eastus.cloudapp.azure.com, emailAddress = test@sample.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (1024 bit) Modulus: 00:a7:4f:53:4e:aa:8d:5f:a6:51:25:a1:27:2b:f1: 8b:05:7b:a1:48:2b:b6:e8:19:8b:b0:5b:e7:79:0c: 4f:87:cc:36:1e:fe:25:76:64:91:62:cb:03:1a:ab: 76:01:3f:cc:83:11:89:07:72:9c:14:75:0a:7d:f6: ce:b3:19:29:69:ea:65:9a:03:fa:64:4f:60:cf:ab: ba:30:1d:f6:5c:8a:9a:5d:2a:b9:17:8b:0e:76:2a: a6:49:15:18:77:b2:4a:bb:98:d0:5a:cc:a1:ca:d7: f5:58:d8:db:65:b7:65:c4:11:a1:42:0c:46:11:91: 05:c4:fe:f7:cf:e3:e2:c7:4b Exponent: 65537 (0x10001) Attributes: a0:00 Signature Algorithm: sha256WithRSAEncryption 02:39:ff:8f:09:9f:ec:61:ae:c7:d5:2d:5c:ca:67:cc:fa:d0: 9a:35:43:e2:d3:ee:dc:b7:d1:8f:3a:74:26:9c:a3:72:6e:73: 62:9d:59:3d:50:8b:3d:2e:66:fe:4b:9b:62:fc:e5:73:4e:7b: 90:ac:06:f0:da:65:4c:35:f5:48:83:72:74:3e:fb:d7:a7:18: a1:2a:67:22:e2:3c:39:91:e1:67:5b:da:18:e6:08:01:22:ba: b3:c1:30:90:f4:a2:8d:80:65:06:39:b9:33:ab:8a:2e:d6:0f: 98:17:a8:e1:1e:a4:44:26:92:d1:bf:81:0a:d8:bf:99:fb:47: cb:e4 [psgdevvm01admin@psg-dev-vm01 20210213]$ # サーバー証明書の中身を確認 [psgdevvm01admin@psg-dev-vm01 20210213]$ openssl x509 -in private2.crt -text -noout Certificate: Data: Version: 1 (0x0) Serial Number: 20:8b:bc:14:47:37:db:ea:17:7c:7a:14:d7:28:9f:b5:a7:f9:4e:78 Signature Algorithm: sha256WithRSAEncryption Issuer: C = ja, ST = tokyo, L = chuo, O = Sample, OU = Develope, CN = psg-dev-vm01-dgyf3zeehekww.eastus.cloudapp.azure.com, emailAddress = sample@sample.co.jp Validity Not Before: Feb 13 14:46:13 2021 GMT Not After : Feb 13 14:46:13 2022 GMT Subject: C = ja, ST = kanagawa, L = yokohama, O = rainbow-bridge, OU = sales, CN = psg-dev-vm01-dgyf3zeehekww.eastus.cloudapp.azure.com, emailAddress = test@sample.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (1024 bit) Modulus: 00:a7:4f:53:4e:aa:8d:5f:a6:51:25:a1:27:2b:f1: 8b:05:7b:a1:48:2b:b6:e8:19:8b:b0:5b:e7:79:0c: 4f:87:cc:36:1e:fe:25:76:64:91:62:cb:03:1a:ab: 76:01:3f:cc:83:11:89:07:72:9c:14:75:0a:7d:f6: ce:b3:19:29:69:ea:65:9a:03:fa:64:4f:60:cf:ab: ba:30:1d:f6:5c:8a:9a:5d:2a:b9:17:8b:0e:76:2a: a6:49:15:18:77:b2:4a:bb:98:d0:5a:cc:a1:ca:d7: f5:58:d8:db:65:b7:65:c4:11:a1:42:0c:46:11:91: 05:c4:fe:f7:cf:e3:e2:c7:4b Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption 46:17:3f:97:cf:b7:c8:d0:9a:4b:27:07:e6:cf:a5:23:2a:22: 4b:fa:eb:3e:f1:b8:70:33:8f:a5:46:4b:19:da:7f:05:9b:51: c0:2b:30:b3:8e:9e:8c:a2:53:e9:ad:92:46:fc:4b:76:3e:bb: f6:3b:7c:57:5a:8a:4a:c7:9a:fe:33:6b:1e:15:1d:ac:56:ad: b0:c6:37:12:92:67:ac:19:f8:d0:7b:bc:0c:a4:db:b9:5a:b7: 8f:a6:f7:4c:63:10:d6:f7:05:a6:3b:0e:a0:01:fc:d8:66:28: 36:40:0b:35:98:31:78:98:1f:18:8c:6f:cb:fd:b5:0f:fe:62: 86:75

"Issuer" と "Subject" の内容を見ると、ルート証明書では両者が一致しているのに対して、サーバー証明書では、"Issuer" が認証局の情報となり、"Subject" が自身の情報となっていることがわかります。

最後に

コマンドを手で実行して結果を自分で確認することでSSL通信に対する理解が深まりました。

ちょっと調べようと思ったところから、ここまでの記事を書くことになってしまいました。