いろはにほへと openssl

openssl のコマンドはたくさんあって、使い方が man を読んでもよく分からなかったりします。マニュアルはコマンドがアルファベット順に書かれていることもあり、上から順に読んでいくような形式ではないことも分かり難い原因ではないかなと思います。

ストーリーに沿ってコマンドを一つずつ使っていくと、いつの間にかコマンドを全て網羅していた、というような いろは歌 のような何かにすれば理解しやすくなるのではないか？

そんなことを考えて、 openssl コマンドを場面を想定して、最低一回ずつ全部叩くスクリプトを書いてみました。

# openssl コマンド

openssl コマンドは以下のような形式で実行します。

```shell-session
$ openssl ＜コマンド＞ [オプション ...]
```

この ＜コマンド＞ がたくさんあって、機能の種類も多岐に渡ります。
鍵を生成したり暗号化したりハッシュ生成したりするコマンドと、SSL/TLS のサーバ機能やクライアント機能を実行できるコマンドが同居してます。
どれも SSL/TLS に関わる機能とはいえ、提供される機能の触れ幅が大きすぎて全体を把握するのが難しいのだと思います。

openssl コマンドについては以下のマニュアルを参照できます。
[OpenSSL のマニュアル](https://www.openssl.org/docs/manpages.html)
[LibreSSL のマニュアル](http://man.openbsd.org/OpenBSD-current/man1/openssl.1)

# appstest.sh スクリプトのご紹介

「こんな場面でこんな風に使う」というのを openssl コマンドを全部使ってストーリー仕立てのスクリプトにまとめてみたのが appstest.sh スクリプトです。

appstest.sh スクリプトは以下の場所からダウンロードできます。
http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/usr.bin/openssl/appstest.sh

このスクリプトはこんな時に役に立つと思います。

- 自分の直面してる場面をスクリプトの中から探して openssl コマンドの使い方を見てみる
- openssl のコマンドをスクリプトの中で検索して、どんな場面で使うのかを調べる
- インストールされている、または自分でビルドした openssl コマンドが正常に動作するかを確認する

使い方は簡単で、ダウンロードして以下のように実行するだけです。

```shell-session
$ ./appstest.sh
```

appstest.sh スクリプトは openssl コマンドが /usr/bin/ にある前提で書かれているので、必要に応じて以下の行を書き換えて使います。

```vim
openssl_bin=/usr/bin/openssl
```

appstest.sh スクリプトは実行されると appstest_dir/ というディレクトリを作成して、その中に openssl のコマンドを実行して生成されるファイルを吐き出します。

途中で openssl コマンドの実行エラーが発生すると appstest.sh スクリプトは停止します。

全ての openssl コマンドの実行が成功すると最後に openssl のバージョン情報を表示して終了します。

# appstest.sh 作成の経緯

元々このスクリプトは、[LibreSSL](https://www.libressl.org/) の動作確認を openssl のコマンドの観点からやってみるために作りました。
libcrypto や libssl に対するライブラリ用の回帰テストは既にあったのですが、コマンドに対する回帰テストが充実してなかったのです。

また同時にテストのカバレッジ率の向上も狙ってました。
コマンドを色んな種類実行することでライブラリ用の回帰テストだけでは通せない所をカバーできるかなと。

この２つの目的のため、openssl のコマンドを全部最低一回は叩くものにすることにしました。

その後、コマンドの利用シーンを想定して、その時に使うオプションを組み合わせて実行するというスクリプトに少しずつ改善させていって作られたのがこの appstest.sh スクリプトです。

appstest.sh という名前は、当時 LibreSSL のソースツリーの中で openssl コマンドのソースコードが apps/ 以下にあったことから来ており、apps をテストするスクリプトというつもりで名付けました。もうちょっとなんか適切な名前を付けておけばよかったなあという気もしています。

GitHub のレポジトリで自分用に育てていたのが、何回か LibreSSL での修正ミス発見に役立ったりしたこともあって、l2k16 で OpenBSD の CVS に取り込まれることになり、現在に至っています。
![l2k16 libressl hackathon Nov 2 - 6, 2016 Toulouse, France](https://www.openbsd.org/images/hackathons/l2k16.gif)

# appstest.sh のあらすじ

「こんな場面でこんな風に使う」と書いたように、appstest.sh スクリプトの中は場面と登場人物を想定して書かれており、そのあらすじは以下のようになっています。

* 暗号、メッセージダイジェスト、鍵
  - コマンド使用法usage、list-* コマンド を使ってみる
  - 暗号リスト、エラー文字列 を表示してみる
  - 乱数、素数 を出力してみる
  - メッセージダイジェスト を使ってみる
  - 暗号化と復号化 をしてみる
  - DH、DSA、RSA、EC を使ってみる
* CA の構築
  - CA の環境を構築する
  - CA の自己署名の証明書を発行する
  - TSA の証明書を発行する
  - OCSP の証明書を発行する
* 証明書の申請と発行
  - サーバ管理者が自分の鍵を作ってからサーバ証明書用CSRを生成する
  - CA がサーバ証明書を発行する
  - CA がサーバ証明書を取り消してCRLを生成する
  - サーバ管理者が証明書の内容を確認する
  - サーバ管理者がSPKACサーバ証明書用CSRを生成して CA が証明書を発行する
  - ユーザがクライアント証明書用CSRを生成する
  - CA がクライアント証明書を発行する
* いろんな機能の実行
  - TSA を試してみる
  - S/MIME を使ってみる
  - OCSP の動作を確認する
  - PKCS7、PKCS8、PKCS12 を試してみる
  - SSL/TLS サーバを起動し、SSL/TLS クライアントで暗号化通信をしてみる
  - 暗号化処理のパフォーマンスを測定してみる
* バージョンの確認
  - バージョンを表示する

例えば CA を構築しておかないと、サーバ証明書用CSRに対しての証明書の発行操作ができないので、そういう話の流れの食い違いが発生しないようなあらすじになっているわけです。また登場人物としては CA とサーバ管理者とユーザが出てきます。

# まとめ

openssl コマンドをストーリー仕立てで全部叩く appstest.sh スクリプトのご紹介でした。

OpenSSL 1.0.1g からフォークした LibreSSL のテスト用に書いたこともあり、appstest.sh スクリプトは 1.0.1 のコマンドを網羅しています。

この記事を書くに当たって OpenSSL の 1.0.2 や 1.1.0 のマニュアルを見てみると片方にあって片方にないコマンドもあったりして、改善の余地があるなあと感じました。

暗号化通信のスクリプトなので、サーバ管理者 Alice と クライアント Bob の会話に CA の Charlie が絡む、みたいな内容にすることも考えてたのですが、残念ながらそこまで楽しいスクリプトにはなっていません。

とはいえ、誰かの何かの役に立てばいいなと、この文章を書いてみました。

あさきゆめみし
ゑひもせす
ん