Last Updated: 2/6/2024, 5:44:57 AM

# SSL 秘密鍵と証明書を発行する。

記事を書いてから気づきました。この記事がわかりやすいです。 なぜ自分で記事を書いてしまったのだろう... orz ちゃんと検索しなかったのかな...

# はじめに

# ◯ 作業環境

 この記事の作業環境は macOS です。  SSL/TLS の秘密鍵、証明書を発行するために、 Certbot というツールをわざわざインストールする必要があるからです。

え?ウェブページからサクッとダウンロードできないのかな? なんでわざわざインストールしないといけないんだろう? 秘密鍵と証明書を発行するのに OS 関係あるの?って思いました。

# ◯ ウェブからダウンロードしない

と思ったら書籍「現場のプロから学ぶ SEO 技術バイブル」に書いてありました。 秘密鍵っていわばパスワードなので、中間者攻撃で他の人に見られたら問題という訳です。

基本的にサーバー上でコマンドを叩いて各種ファイルを取得しますが、 ブラウザ上で各種ファイルを取得できる非公式ツールも存在します。 ただし、秘密鍵の漏洩は非常に危険なので、 可能な限りサーバー上で処理してください。
現場のプロから学ぶ SEO技術バイブル (opens new window)

# ◯ 中間者攻撃

それでも HTTPS 通信してればいいんじゃないの?と思ったりしたのですが、完璧を期したいということなのでしょうか。

もし TLS termination proxy (opens new window) を使わないといけないネットワークなら、 完璧に秘匿することはできないですしね...

# ◯ mkcert

以下は既にドメイン名をお持ちのものとして、話を進めさせていただきます。 もしまだ example.com のようなドメイン名をお持ちでなかったら mkcert で簡単に開発環境用の秘密鍵と証明書を発行できます。

$ brew install mkcert
$ mkcert 127.0.0.1

# Step 1. certbot をインストールする。

自分は macOS を使っているので brew コマンドでインストールしました。

$ brew install certbot

証明書を発行するのにいちいちクライアントソフトをローカルにインストールしたりしないといけないのでつまる。 brew install しないといけないなんて思いもよらなかった。

# Step 2. コマンドを実行

root 権限が必要です。

$ sudo certbot certonly --manual

# Step 3. ドメインを指定する。

example.com を買ったとして話を進めます。

Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): example.com

ちなみに、途中で間違えたりした場合、 最初からやり直しになるので、すこし面倒です。

# Step 4. Yes を押下

Yes を押下します。 IP アドレスが公開されても、良いか聞かれます。

- - - - - - - - - - - - - - - - - - - - - - -
NOTE:
    今回、証明書を発行するにあたり、
    この機械の IP アドレスは公に記録されます。
    The IP of this machine
    will be publicly logged
    as having requested this certificate.

    もし manual モードで cerbot を走らせている
    サーバがご自身のものでない場合は、
    上記のことに留意してください。
    If you're running certbot
    in manual mode on a machine
    that is not your server,
    please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

訳して見たものの、この「IP アドレス」が 自分が現在作業しているパソコンの IP アドレスなのか、 それとも HTTPS 化するサーバの IP アドレスか、 わからないです...

# Step 5. ACME challenge

指定されたファイルパス 英語の長い文字列その1 に 文字列 英語の長い文字列その2 を記載したファイルを置きます。

Create a file containing just this data:

長い英語の文字列その1

And make it available on your web server at this URL:

http://example.com/.well-known/acme-challenge/長い英語の文字列その2

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Flask の方は、末尾をやり方を参考にしてください。 そちらの方が簡単です。

# Step 6. 有効期限を確認

成功すると晴れて証明書 fullchain.pem と秘密鍵 privkey.pem が生成されます。 あとはこれを利用するだけです。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem

以下のように有効期限が切れる期日をしれっと書き込んでくるので注意してください。

   Your cert will expire on 2019-09-01. To obtain a new or tweaked
                            ^^^^^^^^^^ <--- ココ
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"

Microsofot でさえ更新忘れで障害を起こしてしまうくらい、忘れやすいものらしいです。 更新は crontab というコマンドで自動化できるらしいです。

Google の検索結果はこちら。

# Step 7. 秘密鍵と証明書を移動

あとは fullchain.pemprivkey.pem を 使う場所に移動してください。

以下の操作では、カレントディレクトリにコピーしています。

$ sudo cp /etc/letsencrypt/live/example.com/fullchain.pem fullchain.pem
$ sudo cp /etc/letsencrypt/live/example.com/privkey.pem   privkey.pem

root 権限でしか読み込めないので、 ユーザ権限でも読み込めるように権限を変更する。

$ sudo chmod 644 privkey.pem 
$ sudo chmod 644 fullchain.pem 
$ sudo chown your_name:admin privkey.pem
$ sudo chown your_name:admin fullchain.pem 

# そのほか調べたこと

# (1) Let's Encrypt

無料だけど大丈夫なのかなと思ったのですが、関係団体はかなり固い。

Let's Encrypt - Wikipedia (opens new window)
Let's EncryptはInternet Security Research Group(英語版)(ISRG)がサービスを提供している。 主要なスポンサーは電子フロンティア財団 (EFF)、 Mozilla Foundation、アカマイ・テクノロジーズ、シスコシステムズである。 その他の関係団体としては認証局のIdenTrust(英語版)、 ミシガン大学、スタンフォード・ロー・スクール、Linux Foundation[19]などがあり、 レイセオン/BBNテクノロジーズのStephen Kent、CoreOSのAlex Polvなどが関わっている[6]。

the official Let’s Encrypt client は、古いようです。 Certbot の方が新しいようです。

certbot (opens new window)
Certbot was developed by EFF and others as a client for Let’s Encrypt and was previously known as “the official Let’s Encrypt client” or “the Let’s Encrypt Python client.”

あとは PaaS で有名な Heroku は HTTPS 化する時は、 手動で秘密鍵と証明書を作る必要がありません。 自動的に作ってくれるのですが、 その時に使っているのは Let's Encrypt だそうです。

Automated Certificate Management uses Let’s Encrypt, the free, automated, and open certificate authority for managing your application’s TLS certificates. Let’s Encrypt is run for the public benefit by the Internet Security Research Group (ISRG).
Automated Certificate Management - Heroku Dev Center (opens new window)

# (2) 3種類の形態

Let's Encrypt が神すぎる, 3 種類ある形態のうち DV のみだけど、自分の用途では問題はなさそう

Let's Encrypt - Wikipedia (opens new window)
完全自動化のため、  ドメイン認証 (Domain Validation: DV ) 型  証明書のみ発行しており、  企業認証 (Organization Validation: OV) 型   EV (Extended Validation) 型  は提供していない[13]。 日本語ドメインなどの国際化ドメイン名には対応する[14]。

高いお金を払ってもあまり違いは無いようです。

エンドユーザーの立場で言えば、証明書が有効でありさえすれば、無料のLet's Encryptでも21万円するDigiCertグローバル・サーバID EVでも、Webサイトの利便性は何も変わらない。私たちWeb制作業者の立場でも、代理店契約でもしない限り、証明書そのものの価格は一定なので、高い証明書を買わせるインセンティブもまるでない。(強いて言えば、DV証明書でファイル認証できれば発行手続きが楽でいいなあ、と思うぐらいである)
オレオレ証明書を使い続ける上場企業をまとめてみた (opens new window)

その他の有償のお値段をちょっと見てみました。 普通に買おうとすると馬鹿高い...

# (3) オレオレ証明書

Let's Encrypt が登場するまでは、秘密鍵と証明書を有料で発行しなければなりませんでした。 これは HTTPS を使うには、判定する認証局などを立てたりしないといけないので、意外と維持費がかかるからだと思います。 詳しいことはわかりません。

そのため、動作確認にあたっては、よく昔は「オレオレ証明書」という手を使って発行していたようです。

オレオレ証明書 - 「分かった」気になれる IT 用語辞典 (opens new window)
コンピュータの世界における「胡散臭い機関が発行した身元証明書」

ちなみに Let's Encrypt は、オレオレ証明書ではありません。

# (4) openssl コマンド

Google で検索していると、よく openssl コマンドを使ったオレオレ証明書を発行する方法が見つかります。

openssl コマンドは OpenSSL を使うためのコマンドらしいです。 Oracle Linux のドキュメントを引用します。 「自己署名証明書の作成」というのは、おそらく「オレオレ証明書」のことだと思われます。

opensslパッケージに含まれるopensslコマンドを使用すると、 OpenSSLライブラリから次のような様々な暗号化機能を実行できます。

  • 秘密鍵と公開鍵のペアの作成および管理
  • 公開鍵暗号化操作の実行
  • 自己署名証明書の作成
  • ...

3.3.1 opensslコマンドについて - Oracle Linux セキュリティ・ガイド リリース6 (opens new window)

# (5) OpenSSL

OpenSSL は TLS/SSL を使うためのライブラリらしいです。

OpenSSL (opens new window)
OpenSSL(オープン・エスエスエル)は、 SSLプロトコル・TLSプロトコルの、オープンソースで開発・提供されるソフトウェアである。 中心となっているライブラリ(C言語で書かれている)は基本的な暗号化関数と様々なユーティリティ関数を実装している。

# Flask での ACME challenge の置き方

Python のウェブアプリケーションフレームワークである Flask を使っている場合は、以下のようになります。

英語の長い文字列その2 の文字列のファイルは、 以下のようにするとやりやすいかなと思います。

import flask

app = flask.Flask(__name__)

@app.route(
    "/.well-known"
    "/acme-challenge"
    "/長い英語の文字列その1")
def acme_challenge():
    return "長い英語の文字列その2"

app.run()

# 参考

こちらの記事を参考にしました。

あと日本語の解説サイトがあるけど、非公式みたい... "SEO 技術バイブル" では公式って書かれてたけど... 公式っぽいんよね笑

Let's Encrypt 総合ポータル (opens new window)
当サイトは、Let's Encrypt に関する非公式の解説サイトであり、公式サイトではありません。

# おわりに

以上になります。ありがとうございました。