エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

『フルスクラッチして理解するSSL/TLS』の裏側

【デジカルチーム ブログリレー6日目】デジカルチームの末永です。5月31日から開催される技術書典18で頒布するエムスリーテックブック8の、フルスクラッチして理解するSSL/TLSという章を担当しました。この章では、標準ライブラリ縛りでTLS 1.3のサーバーサイドを実装していきます。

techbookfest.org

ここでは執筆の流れや小話などの裏側を書いていきます。

フルスクラッチして理解するSSL/TLS

まずはどんな章を書いたのかをざっくり紹介していきます。フルスクラッチして理解するSSL/TLSは、フルスクラッチして理解するOpenID Connect作って理解するPasskeys*1に続くフルスクラッチシリーズ3作目になります。

冒頭にも書いたように、TLS 1.3を標準ライブラリのみで実装していきます。使用言語はTypeScriptです。最終的にブラウザで https://localhost を開けるようになります。写経するだけで動くものが完成するように、コードを全文載せました。 コードを全文載せるのは文量が長くなりすぎて書籍にするには不向きなのですが「コードを載せないならRFC読めばいい」「自分は学習するときに具体的なコードが欲しい」という思いがあるため全文載せる判断としました。 なお、私の章は70ページ強あります。

コードはGitHubに公開しています(asmsuechan/tiny-tls)

執筆スケジュール

入稿は5月末だったのですが、次のようなスケジュールで執筆をしていました。

  • 1月: 情報収集
  • 3月: プロトタイプ実装開始
  • 4月中旬: プロトタイプ完成、執筆用にリファクタ
  • 4月下旬: 末本文の執筆開始
  • 5月: 執筆しながらコードを調整

原稿を書くにあたって、コードは2回作り直しました。まずプロトタイプを作って、本文を執筆しながらリファクタ(作り直し1回目)。そして書いた本文に従って実装をしながら最終調整(作り直し2回目)です。

なお、執筆にはRe:VIEWを使用しており、エムスリーテックブックで使用しているテンプレートはGitHubに公開しています(m3dev/techbook-templete)

いちばん大変だったポイント

TLSでは、鍵交換アルゴリズムを使ってクライアントとサーバーで共通のシークレットを生成する必要があります。実装中にこのシークレットが全然一致しなかったのです。server_handshake_traffic_secretの導出部分を実装するだけで5日間くらいかかりました。実装時、openssl s_connectをクライアントとして利用していましたが、途中でどうしてもクライアント側のログを確認したくてopensslをローカルに落としてデバッグログを追加した状態でビルドし直したりもしました。

結論としては、「AIが生成したコードが完全に間違っていた」ことが原因でした。後述しますが、これがあってからAI生成にほぼ頼らず実装を進めることになります。

実装・執筆小話

「長すぎる」問題

みんなで執筆を進めるにつれて、私の章が長すぎて販売価格を再考しないと大赤字になってしまう問題が発生しました。 長すぎる問題への対処として、いくつかアイデアが出ました。

  • 「エムスリーテックブック末永外典」を出す
  • 書籍は諦めてテックブログに公開する
  • zenn bookにする
  • 短くして載せる

今回これらの案は結局採用せず、執筆チームで話した結果「書きたいものを書きたいように書くのが同人誌だろう、よって長いまま出すぞ(意訳)」という結論に至りました。他サークルや技術書執筆者へのリスペクトも込めて価格側を調整しようという話もあり、出来る限りの3方良しな意思決定に繋がった点も執筆活動の一環として良い経験になりました。

同期との心暖まる会話

実際どれくらいAI使った?

コードや文章の構成と叩きを作った後の「書くだけ」や「やるだけ」の状態から生成AIを使うとかなり捗ることが多いと思います。私も実装や執筆に生成AIを活用しようとしたのですが、うまくいきませんでした。

まず、TLS 1.3をフルスクラッチする実装例が少なくてマトモなコードを生成してくれませんでした。cryptoパッケージの存在しない関数を呼び出したり、存在しない引数を入れたり、全く違うロジックを追加したり、という生成結果が多く見られました。ですので結局実装はほぼほぼ手書きです。あたたかみがありますね。

AIの間違いにより教育される様子

次に、ある程度実装部分を原稿に落とし込んだ後で文章の方も生成しようとしました。しかし、これも失敗に終わりました。文章が長すぎたのか、簡単な誤字修正などの校正タスクを指定して実行しても、完了したと思い確認したら文章をほとんど消されていたり、ということがありました。

AIに文章を消されて悲しむ様子

やはり、あまりみんなが書かないコードや長すぎる文章をAIに任せるには工夫が必要に思いました。校正についてはファイル分割がかなり有用そうです。もっとちゃんと指示を書いて使いこなしていきたいです。

フルスクラッチとは言っているが・・・

フルスクラッチを銘打って、実際に標準ライブラリのみで実装しましたが、Node.js標準のcryptoパッケージを多用しています。そしてそもそもNode.jsのcryptoパッケージはopensslに依存しています。したがって暗号周りの実装は「標準ライブラリ縛り」であって「フルスクラッチ」ではないのです。ただ、opensslを自作しようとすると最低限の機能だけでも恐らくページ数が倍くらいになってしまうので、しないことにしました。

おすすめポイント

内容についても宣伝します。先ほど書いたように、この章にはTLSサーバーの実装がほとんど全て入っています。ここがいちばんのアピールポイントです。

込み入った仕様のものを実装する時は、仕様を隅から隅まで読むよりも、手を動かして具体的なコードを読み書きする方が早く理解を進めることが出来ると考えています。

仕様や理論の部分は後述の本で賄えるため、本章の内容は副読書として利用出来ると思います。手を動かしてから本を読むのも、本を読んでから手を動かすのも、どちらも楽しいと思います。

TLS関連書籍の補助として使えるというのも、価値のひとつだと捉えています。

参考書籍の紹介

RFCを読んで実装を開始する前に何冊か本を読んで事前知識を身につけました。その時に読んだ本を紹介します。

  • SSL/TLS実践入門
    • この本を読めば完璧なのでは?と思わせる力作。最初に読んでTLSの流れを頭に入れることが出来た。イチオシ。
  • 徹底解剖 TLS 1.3
    • WolfSSLの中の人たちが書いた書籍。具体的なコードも書かれているため、実装の雰囲気を掴むのに便利。
  • マスタリングTCP/IP 情報セキュリティ編
    • TLSの章はTLS 1.2の説明なのでダイレクトに参考にできるわけではないが、暗号技術の概説がわかりやすい。2冊目に読んで助けられた。
  • 暗号技術入門: 秘密の国のアリス
    • TLSで使われる暗号技術について分かりやすく解説している本。暗号技術においては言わずと知れた名著。

まとめ

一時は「これ本当に実装間に合うのか?」と思うこともありましたが、なんとか楽しく書き上げることが出来ました。TLSのRFCを全然読んだことがない状態から実装まで手をつけることが出来て、私としてもかなり身になりました。

最後に、エムスリーテックブックに興味を持ってくださった方は技術書典で手に取っていただければ幸いです。私はオフラインの会場にもいる予定です。

techbookfest.org

We're hiring!

私が所属するデジカルチームでは、クリニックの診療を支えるクラウド型電子カルテであるエムスリーデジカルを開発しています。 開発チームの紹介資料もありますので是非ご覧ください!

speakerdeck.com

また、エムスリーではエンジニアを絶賛募集中です。 興味を持って頂けた方、カジュアル面談や採用へのご応募をお待ちしています。

jobs.m3.com

*1:cborのパースだけライブラリを使ったのでフルスクラッチを銘打ちませんでした。