プロになるためのWeb技術入門

「プロになるためのWeb技術入門」 ――なぜ、あなたはWebシステムを開発できないのか

「プロになるためのWeb技術入門」 ――なぜ、あなたはWebシステムを開発できないのか

本書はid:naoyaさんも賞賛されていますし、Amazonでも3人のレビューが5点満点を付けていて高い評価を受けています。

本書のスタンスが分かると思いますので、まず「はじめに」から少し抜き書きします。

(略)
根本の仕組みを理解していなければ、問題が発生したときにその原因を突き止めて解決することは出来ませんし、既存技術の問題点を捉えて新しい技術を生み出していくことも出来ません。
(略)
新人のうちから技術の根本に触れ、その奥深さや面白さを知っていくことが重要なのではないでしょうか。
(略)
本書は、何年先も通じるWebアプリケーションの基礎技術を、1冊で手軽に楽しく身につけられるようにすることを目標に執筆しました。
(略)

かなり大上段に構えていることが分かりますが、看板倒れに終わることなく、網羅的とは言えないものの初心者がweb開発を始めるに渡って理解すべきコンセプトやトピックが色々と盛り込まれています。世の中に個別のフレームワークや言語について書かれた入門書やオンラインのチュートリアルはたくさんあるのですが、web開発全般について俯瞰するような書籍は珍しいので、貴重な一冊だと思います。初心者だけでなく、1年ぐらい開発を経験した後のエンジニアにとっても、知識をまとめなおすに好適かもしれません。

何より文章が平易なので、難しい内容でも理解しやすいと感じました。自分が、開発初心者の後輩に頼まれて何冊か技術書を紹介するとしたら、本書はそのうちの一冊になると思います。


ところで、かように貴重かつ優れた本書なのですが、公開鍵暗号について書かれた一節について気がついた点がありましたので、少し書かせていただきたいと思います。(不適切な点があればコメントやtwitterで知らせていただけると幸いです。訂正させていただきます。)

公開鍵は盗まれてもよい?

p.247より引用

公開鍵暗号を使ってAliceからBobへメッセージを送る場合、Bob(メッセージの受け手)が一対の公開鍵と秘密鍵を生成し、公開鍵をAliceへ送ります。公開鍵は盗まれてもかまわないので、メールで送っても問題ありません。Bobの公開鍵を受け取ったAliceは、その公開鍵を使ってBobへ送りたいメッセージを暗号化して送ります。(以下略)

単刀直入に言うと、この部分の記述は誤解を招くおそれがあるように感じました。(Aliceがメールが本当にBobから送られてきたものかどうか検証する手段があるという前提なら話は別ですが、そもそもメールの署名には一般的に公開鍵暗号を使いますので、公開鍵が交換できていないという前提条件と矛盾します。)

以下に説明します。

危険性

まず、一般に共通鍵暗号を使って安全に通信を行う場合、あらかじめ通信する相手と秘密鍵を交換する必要があり、その鍵交換自体には共通鍵暗号が使えないという問題があり、鍵配送問題と呼ばれています。公開鍵暗号(方式)は、鍵配送問題を解決するために考案されました。暗号化と復号に別の鍵を用いるため、復号用の鍵さえ秘匿できれば、暗号化用の鍵は第三者に知られても構わないという点が画期的でした。
では、単純に公開鍵暗号を使えば鍵配送問題が解決するかというと、そうは問屋が卸しません。Bobが生成した公開鍵を不用意に電子メールでAliceに送ってしまうと、中間者攻撃(Man-in-the-middle attack)によって、AliceからBobへ送信した情報が盗まれたり、改ざんされる恐れがあります。

ここで、そもそも通信を暗号化する理由として、Alice-Bob間の通信路の安全性が保証されていないことを思い出してください。悪意の第三者(Charlie)は、BobがAliceに送った公開鍵b-pを盗み取り、新たにCharlieが生成した鍵ペアの公開鍵c-pをボブのものであるとしてAliceに送りつけることが可能です。Aliceは、Charlieの生成した公開鍵c-pをBobの公開鍵として登録します。Aliceは、送信したい電文をc-pを使って暗号化して送出しますが、これはCharlieの秘密鍵c-sで復号できますので、Charlieは電文を読むことができます。さらに、Charlieがb-pを使って再び電文を暗号化しBobに送りつけると、Bobは自分の秘密鍵b-sによって電文を復号することになりますが、盗聴には気がつきません。ここで、CharlieがAliceから取得した電文をそのままb-pで再暗号化してBobに送れば「盗聴」ですが、内容を操作すれば「改ざん」が可能になります。

つまり、公開鍵暗号を用いてAliceがBobに安全に電文を送るためには、公開鍵と所有者の対応付けを適切な方法によって検証できる必要があるのです。AliceはBobが作ったとされる鍵が、本当にBobのものであるか確認する必要があるのです。単純にメールで送ることはできません。

公開鍵の検証の実際

では、通信相手の公開鍵を検証する方法には何があるのでしょうか。いくつか方法があります*1が、webに話を限定すると、HTTP通信を暗号化する手段としてのSSLHTTPS)では、ディジタル署名を用います。

ところで、公開鍵暗号方式では、受信者の公開鍵で電文を暗号化することで、電文の秘匿を実現していました。受信者の秘密鍵を持っているのは本人だけなので、正当な受信者だけが電文を読むことができます。もちろん、前述のように、受信者の公開鍵が本物でなければなりません。
ディジタル署名では、これを逆転させます。(公開鍵の仕組み上、秘密鍵によって暗号化した電文は、対応する公開鍵でしか復号できないことに注意してください。)まず、送信者が電文を送るに当たって、電文とセットで電文のメッセージ・ダイジェストを送信者自身の秘密鍵で暗号化して送信します。受信者は、送信者の公開鍵で暗号化されたダイジェストを復号すると共に、受信した電文のメッセージ・ダイジェストを自ら計算した結果と付き合わせます。この結果が一致すれば、正しい送信者から送信された電文が改ざんされずに受信できたことを判定できます。(ここでも、受信者が送信者の正しい公開鍵を入手できることが重要です)

話をwebに戻しますが、webブラウザーはアクセス先のサーバーが送信してきた公開鍵を、ディジタル署名によって検証しています。

具体的にはディジタル証明書を用います。ディジタル証明書の代表的な仕様にはX.509がありますが、ドメイン名などのサーバー情報と公開鍵のセットを認証局(CA: Certificate Authority)と呼ばれる第三者*2ディジタル署名することで内容を保証したものとなっています。主要なwebブラウザには、いくつかのディジタル証明書が出荷段階で組み込まれているため、ブラウザ開発者が信頼に足ると判断した認証局の公開鍵を持っていることになります。

ようやく結論に至りますが、ブラウザがSSL/TLSを利用するサーバーにアクセスすると、通信を暗号化するのに先立ってブラウザはサーバーの証明書を取得します。証明書には、ディジタル署名を行った認証局の情報も書かれているため、その認証局の証明書がブラウザに組み込まれていれば、その証明書の正しさを検証し、その結果、内包されている公開鍵がサーバーのものであることを確認できるのです。

SSLは以上の仕組みによって、インターネットのような信頼できない通信路の上での安全な通信を実現しています。繰り返しますが、公開鍵暗号方式であるからといって、単純に電子メールで公開鍵を送りつければ安全な通信ができるわけではありません。



長くなってしまいましたが、公開鍵を信頼できない通信路で送ってしまったら、安全な通信はできないということを自分の言葉で説明してみました。今後、多くの初心者が本書を読むことになるでしょうから、僭越ながら、この点について誤解の余地がない記述になっているとよいと感じました。


(本書の著者である)小森さんの名誉のために言うと、実は引用箇所の直後である248ページの脚注ではSSL証明書の検証についても軽く触れられているのですが、あえて私が指摘を試みた理由としては、かつて世の中に「オレオレ証明書」が蔓延してしまったことの背景には、公開鍵暗号において公開鍵を検証する重要性が理解されていなかったからだと思うからです。当時、通信が暗号化されてさえいれば安全であると誤解のもとに、不特定多数が利用するwebアプリケーションに自己署名証明書を用いるということが行われ、多くの人のデータが危険に晒されてしまいました。

*1:主に電子メールについて書かれたものですが、IPAのページ公開鍵を信頼するためにが参考になります。

*2:原理的には、自分自身で署名することも可能で、自分自身で署名したものを「自己署名証明書」と呼びます。