«前の日記(2006-05-05 (金)) 最新 次の日記(2006-05-07 (日))»  

まちゅダイアリー


2006-05-06 (土)

はてなの認証API (2)

はてなの認証APIがコールバックURLへのパラメータ指定をサポートしたみたい。 これまではコールバックURL(はてなでの認証後に戻ってくるURL)は固定だったけど、これにパラメータを付けられるというもの。 Kazuho@Cybozu Labsに、具体的なメリットが書かれている(以下引用)。

パラメータを指定できたほうが良いと思います。固定のままでも、サードパーティアプリ側で Cookie を使えば、パラメータ指定と同等のことはできますが、処理が煩雑になるので。

分かるような分からないような。僕の勉強不足だな…。 前提として、「はてなで認証する前の情報を、認証後も保持しておきたい」ってのがあるのか。 以下の処理を例に考えてみる。

  1. ユーザが、検索サービスに対して何かアクションを起こす(例えば、検索クエリを投げるなど)
  2. サービスは、はてなAPIを使ってユーザを認証する(一度、はてなの認証サーバにリダイレクトする)
  3. サービスは、ユーザに対して応答を返す

コールバックURLが固定だと、ユーザが[2]ではてなから戻ってきた時点で[1]でのアクションの情報(例では検索クエリの内容)が失われてしまう。 [1]の時点で Cookie を発行し、[3]で Cookie からアクションの情報を取得することもできる。 でもそれより、[1]から[2]へのリダイレクト時にパラメータとして渡してあげた方が処理が楽ということかな。 確かに、使い捨ての情報だったらクエリに入れられた方が楽かな。

POST リクエストに対して認証が必要になってリダイレクトするようなケースでは、 CSRF を防ぐために、 Cookie とコールバック URL のパラメタを組み合わせる必要がありますので、そのような動作をサポートしたい (たとえば、ブログのコメントをポストする際に認証を要求するようなウェブアプリに対応したい) のであれば、パラメータ指定は必須になります。

CSRF を防ぐためには、コメントフォームに何かしらのキー(セッションキーだったりワンタイムキーだったり)を埋め込む必要がある。 んで、そのキーの情報は Cookie に入れることはできない(Cookieに入れると CSRF 対策にならない)。 だから、コールバックURLへのパラメータにそのキーを入れたいってことかな。

「アクション」→「認証」→「アクションの応答」というシーケンスだから、処理が複雑なのかも。 事前に認証されていないとアクションができない(例えばブログのコメントフォーム自体が表示されない)という作りにすれば、コールバックURLへのパラメータは不要な気がする。

パラメータ指定への留意点

Kazuho@Cybozu Labs のその後のエントリーで、パラメータ指定に対応する場合の注意点が挙げられている。 勉強になるなぁ。

サードパーティアプリケーション側で、未ログインだった場合にクエリパラメータをそのまま認証サーバへリダイレクトするようなコードを書いてしまうと、それを署名の偽造に利用される可能性が出てきてしまう

現時点では、サードパーティアプリケーション側で汎用的なログイン処理を書く場合には、cert パラメータをログイン URL に含めないよう注意する必要がある

なるほど。 これは認証API側の問題ではなく、アプリ側の問題かな。 「ユーザからの入力をそのまま出力に使ってはいけない」という Web アプリの原則に従って、認証サーバへ渡すパラメータは事前にアプリ側でチェックすべき、と。

この問題については、今後の仕様改訂の際に、 URL Path も含めてハッシュ値を算出するようにすれば良い

この解決策はよく分からなかった。 何が正しいパラメータで何が不正なパラメータかはアプリにしか分からないので、ハッシュに URL を含めても変わらないのでは。 何か勘違いしているかな…。

MD5 と HMAC

同じく、 Kazuho@Cybozu Labs のエントリで、署名の生成に MD5 は危険だから HMAC を使った方がいいと指摘されている。

こういう場合は、HMAC を使うべきだと思います。現在のやり方だと、秘密鍵は被署名データの先頭にしか作用しないので、末尾を上手に構築することで攻撃が (理論的には) 成立します。

『[秘密鍵]api_key[API_KEY]appendDATA』 のようなデータの MD5 値が既知の場合に、『[秘密鍵]api_key[API_KEY]appendDATA\x80\0\0\0......\0\0\x02\x08cert[任意の cert 値]』の MD5 値は、秘密鍵を知らなくても算出することができます

「ある値」のハッシュ値が分かれば、「ある値+α」のハッシュ値が分かるということか。 これが本当なら、僕のハッシュ関数への理解が根本的に間違っていることになるなぁ…。 (もしくは、ハッシュ関数全般の危険性じゃなくて、MD5固有の話?)

  • ハッシュ値から元の値を推測することが困難
  • 同じハッシュ値を持つ2つのメッセージを見つけることが困難

というのがハッシュ値の条件の一部。 確かに「ある条件を満たせば、メッセージを知らなくてもそのハッシュ値を推測できる」というのは、これら条件と矛盾しないか。

それで、 MD5 ではなく HMAC を使えばいいということなんだけど、 HMAC の仕組みと認証APIの署名の仕組みは似ている。 (以下、HMAC の仕組みについては、結城さんの暗号技術入門を参考にしました)

HMAC
hash(opadkey + hash(ipadkey + message))
はてな認証API
hash(secret_key + message)

HMAC の opadkey と ipadkey は、秘密鍵 (secret key) を2つに分けたようなもの。 秘密鍵を2つに分けて2回ハッシュを取ると問題なくて、1回だと問題があるということ?(←よく分かってない)

ここは少し勉強して、出直さないとな…。

本日のツッコミ(全8件) [ツッコミを入れる]
hyuki (2006-05-06 (土) 21:16)

Kazuho@Cybozu Labsさんが書いているのは、ハッシュ一般の話ではなく、MD5固有の話ではないかと思います(わたしもよくわかっていない)。

kazuho (2006-05-06 (土) 22:47)

パラメータ指定が使いたい理由というのは、おっしゃっているとおりの話です。<br><br>URL Path も含めてハッシュというのは、プロトコル仕様をそのように変更すれば /auth.json 用の認証情報を偽造するのに /auth への URL を用いることはできなくなるよ、ということです。<br><br>ハッシュと MAC の違いについては、 http://en.wikipedia.org/wiki/Message_authentication_code の第2段落が、今回の話の肝で、(パラメータ指定ができるという) chosen-plaintext attack が可能になった以上、HMAC を使わなくてはいけない、ということなのだと理解しています。<br><br>SHA1 については知らないですが、MAC の要件は満たしてないんじゃないでしょうか。というより、そういう目的には HMAC ということだと思います。

まちゅ (2006-05-07 (日) 04:24)

情報ありがとうございます。<br>chosen-plaintext attack による攻撃 (existential forgery) に耐えられることが HMAC の要件ということは理解したのですが、(秘密鍵+MD5を使う)はてな方式では問題があるということは理解できませんでした。<br>少し整理して、次の日の日記に改めて書きます。

まちゅ (2006-05-07 (日) 04:36)

それから、「HMAC = ハッシュ関数 (MD5 や SHA1) + 秘密鍵」ですので、SHA1 と秘密鍵を組み合わせれば MAC の要件を満たすことができます (HMAC-SHA1) 。

kazuho (2006-05-07 (日) 05:52)

> (秘密鍵+MD5を使う)はてな方式では問題があるということは理解できませんでした。<br><br>この点については、(同様の問題を抱えているアプリケーションがある場合に) あまり具体的に説明するのはよくないのかなぁ、と悩んでいます。<br><br>> それから、「HMAC = ハッシュ関数 (MD5 や SHA1) + 秘密鍵」ですので、SHA1 と秘密鍵を組み合わせれば MAC の要件を満たすことができます (HMAC-SHA1) 。<br><br>秘密鍵とハッシュ関数を組み合わせる手法によっては、セキュリティホールが発生する可能性がある。このような穴がないことが証明されている組み合わせ手法が HMAC である、ということです。HMAC-MD5 でも HMAC-SHA1 でもかまいません。<br><br>あと、本文中で引用されている<br><br>> cert パラメータをログイン URL に含めないよう注意する必要<br><br>についてですが、すいません、この点に注意するだけでは不足です。cert というパラメータ名をチェックする手法だと &c=e&rt=xxxxxx のようなパターンを拒否することができません。<br>とりあえず、現時点ではパラメータを授受するのはお勧めできないような感じですね。

kazuho (2006-05-07 (日) 08:15)

> (秘密鍵+MD5を使う)はてな方式では問題があるということは理解できませんでした。 <br><br>について、http://labs.cybozu.co.jp/blog/kazuho/archives/2006/05/hash_ne_mac.php に、HMAC の論文を引用しました。よろしければごらんください。

hyuki (2006-05-07 (日) 09:30)

kazuhoさんの解説を理解しました。結城はMD5の脆弱性絡みの話題かと思っていましたが、それは結城の誤解でした。生のハッシュを使うのではなくHMACを使うのが正しいです。<br>kazuhoさんが http://labs.cybozu.co.jp/blog/kazuho/archives/2006/05/hash_ne_mac.php で紹介しているHMACの論文でも、またシュナイアー『暗号技術大全』(p.508)にもありますね。ハッシュ関数がiterativeな性質(出てきたハッシュ値が自分の次の内部状態になる)を持つ限り、この危険性からは免れません。<br>拙著『暗号技術入門』のMACの章ではこの攻撃については触れなかった…(;_;)。p.309に類似のクイズがありますが。<br>勉強になりました。kazuhoさん、ありがとうございます。

まちゅ (2006-05-07 (日) 11:48)

> kazuho さん<br>「秘密鍵とハッシュ関数を組み合わせる手法によっては、セキュリティホールが発生する可能性がある」で納得しました。<br>勉強になりました。貴重な情報に感謝します。<br><br>> hyuki さん<br>完全には理解できていませんが、ハッシュ関数単体では「予測不可能性」を持たないことが原因ということは分かりました。<br>『暗号技術大全』を読んで勉強します。