Skip to content


OAuthの署名方式を掘り下げる

当ブログでこれまで何度かOpenSocialに絡んだOAuthについて取り上げてきましたが、MySpaceを参考にしていたため、署名方式としてHMAC-SHA1のみを対象にしてきました。しかしShindigを掘り下げる上でRSA-SHA1を避けて通ることはできず、むしろこちらについても十分な知識を得ていないとなかなか先に進めないことが分かりましたので、この機会にまとめてみます。(OpenSocialをある程度前提にしていますが、署名の話はOpenSocialに限らないものです。)

署名とは何か

ITの世界で署名とは、問い合わせ元がその人であることを証明するための手段、と言えます。OAuthだと、コンシューマがサービスプロバイダに対して、名乗っている通りの者であることを証明することを意味します。これは、「自分」もしくは「相手と自分」にしか分からないものをリクエストに付け加えて送ることで実現されます。

OAuthの仕様では、署名方式について厳密に規定していませんが、HMAC-SHA1、RSA-SHA1、PLAINTEXTの3つの署名方式を説明しています。

OAuth does not mandate a particular signature method, as each implementation can have its own unique requirements. The protocol defines three signature methods: HMAC-SHA1RSA-SHA1, and PLAINTEXT, but Service Providers are free to implement and document their own methods. Recommending any particular method is beyond the scope of this specification.

HMAC-SHA1

HMAC-SHA1を使ったOAuthでは、予めコンシューマとサービスプロバイダが、同じコンシューマキー(oauth_consumer_key)とコンシューマシークレット(oauth_consumer_secret)を持ちます。コンシューマシークレットはもちろん、秘密というくらいですから、2者以外に知られてはいけません。2者がコンシューマシークレットを共有することから、Shared Secretと呼んだりもします。

MySpaceでは、コンシューマキーをアプリケーションのURL、コンシューマシークレットをMD5らしきランダムな(?)ハッシュ文字列としていますが、コンシューマキーはディベロッパの任意で変更可能です。詳しくはこの辺りをご覧下さい。

RSA-SHA1

逆に、RSA-SHA1の方式では、コンシューマが公開鍵と秘密鍵を持ちますが、サービスプロバイダは秘密鍵を知ることはありません。コンシューマは秘密鍵で暗号化した署名を加えたリクエストを投げます。この暗号化された署名は、公開鍵でしか解くことができませんし、秘密鍵でしか作ることができないため、コンシューマが身分を証明できる、という訳です。

署名を作る際、HMAC-SHA1方式の場合、コンシューマシークレット(oauth_consumer_secret)とトークンシークレット(oauth_token_secret)を”&”で繋いだものをkeyとして利用しますが、RSA-SHA1方式の場合、秘密鍵をkeyとして使って暗号化します。そのため、コンシューマシークレットとトークンシークレットは不要です。

逆にサービスプロバイダは、公開鍵を使って署名が正当なものであることを確認します。

$publickeyid = openssl_get_publickey($cert);
$ok = openssl_verify($raw, $signature, $publickeyid);
openssl_free_key($publickeyid);

$certは公開鍵、$rawは署名の基本文字列(Signature Base String)、$signatureは署名文字列(oauth_signature)を表しています。$rawと$signatureはコンシューマからのリクエストで生成することができますが、$certについてはちょっと考察が必要です。

RSA-SHA1の公開鍵の扱い

OAuthの拡張としてOAuth Key Rotation Extensionが提案されています。これはコンシューマがサービスプロバイダにリクエストする際、公開鍵のIDをリクエストと一緒に渡すことで、サービスプロバイダに鍵をダウンロード/認識させるための仕様です。公開鍵のIDはxoauth_signature_publickeyパラメータで渡されます

OAuth Key Rotation Extensionのドラフト、OpenSocial/Gadgetの仕様書など、いくつかのドキュメントにxoauth_public_keyと記述されていますが、Shindigの実装でxoauth_signature_publickeyが使用されており、こちらが正式なものとなるようです。

ここで公開鍵のIDと言いましたが、もちろん、これだけでは公開鍵を取得することができないので、これを使ってゴニョゴニョする必要があります。

が、、、。

OpenSocial/Gadgetの仕様書には

The container should make its public key available for download at a well-known location. The location https://container-hostname/opensocial/certificates/xoauth_public_keyvalue is recommended.

と書いてあるのですが、Shindigの実装ではhttp://container-hostname/public.cerになっていたりと、仕様が一貫していません。

現実はどうしているかというと、xoauth_signature_publickeyを無視して、コンテナのドキュメントに書いてある公開鍵をコピペしてソースコードにハードコーディングしています。hi5、Orkutについては動作確認ができました。iGoogleについてはここに公開鍵が書いてありますが、動作しませんでした。

OAuthが広まって様々なコンシューマが登場するまでは、まだまだこの中途半端な状態が続くのではないでしょうか。

コンシューマは誰か

ここで勘のいい方は気付かれたと思いますが、RSA-SHA1方式の場合、署名元がOpenSocialのコンテナサイトそのものになっています。MySpaceのように、ガジェットではありません。ということは、もちろんコンシューマキー(oauth_consumer_key)もOrkutなら”orkut.com”、hi5なら”hi5.com”といった具合に、コンテナサイトを表すものが使用されます。

またこの方式の場合、どのガジェットがリクエストを投げているのかを表すため、xoauth_app_urlというパラメータが追加されます。これを提案しているのがOAuth Gadget Extensionです。

MySpaceのようにHMAC-SHA1を使っている場合は、ガジェットごとにコンシューマキーを設定し、ガジェットのリクエストをコンテナがProxyするという形を取っていました。これはShindigを使っているiGoogle、Orkut、hi5と、独自にOpenSocialを実装しているMySpaceとの方針の違いから来るものです。

HMAC-SHA1方式でコンテナをコンシューマとして扱おうとすると、シークレットは2者間のみで共有されなければならないため、コンシューマは、サービスプロバイダごとにキーとシークレットを発行しなければなりません。しかし、RSA-SHA1方式であれば、コンテナがコンシューマでも、公開鍵と秘密鍵の組み合わせは一つだけあれば使い回せるため、OpenSocialにおけるmakeRequest (Outbound OAuth)のように、コンテナが外部サービスからデータを取得するアーキテクチャの場合、RSA-SHA1方式にした方がコンシューマにとってサービスプロバイダの追加も容易になりますし、サービスプロバイダにとってコンシューマの署名を確認する作業も楽になるのが利点です。

ShindigがRSA-SHA1方式を中心に実装されているのはそんな理由がありそうです。ちなみに、Shindigの開発はGoogleが中心になって行われており、HMAC-SHA1方式についても現在実装中らしいですが、iGoogleでのコンシューマキーとコンシューマシークレットの発行は、メールで依頼することになっているため、今のところ本気で考えてはいなさそうです。

In the case of the iGoogle sandbox, you can send mail to oauthproxyreg@google.com with the following information to register your shared secret:
* URL of your gadget
* The shared secret assigned to you by the service provider
* The consumer key assigned to you by the service provider
* Whether to use symmetric or asymmetric signing with the service provider (or say that you don’t know)
Until your shared secret has been registered, your gadget will not work.  If you change the URL of your gadget, you will need to re-register the secret for that gadget.

まとめ

現時点ではOpenSocialのOutbound OAuthではMySpaceがHMAC-SHA1方式でガジェットをコンシューマに、Shindig系コンテナはRSA-SHA1方式でコンテナをコンシューマにしていますので、外部サーバーとやり取りを多なうOpenSocialガジェットを作る場合、どちらからのリクエストも受け付けられるよう構築しておく必要がありそうです。

参考サイト

Comments

comments

Powered by Facebook Comments

Posted in OAuth.

Tagged with , , , , .


3 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. kazu says

    公開鍵の扱いが中途半端な実装になっているのは、RSA署名方式自体が、署名の潜在的偽造の可能性があるからかもしれないのか? HMAC方式はお互いに秘密鍵を保有することで、すでに秘匿性が担保されていると考えてもいいのか。

    コンシューマーがリクエストする際に公開鍵を指定する仕様なら、誰でもなりすましができてしまう。
    ハードコーディングは、公開鍵を事前に渡しておくことと捉えるなら、それなりに納得できる気もするが。

  2. Eiji says

    > 公開鍵の扱いが中途半端な実装になっているのは、RSA署名方式自体が、署名の潜在的偽造の可能性があるからかもしれないのか?

    これは単純に、まだ内輪で話が済んでいるからでしょう。もっと一般的になってくると、厳密に仕様を作り、乗っ取っていなければならなくなると思います。

    > HMAC方式はお互いに秘密鍵を保有することで、すでに秘匿性が担保されていると考えてもいいのか。

    秘匿性とはなんでしょうか?署名はあくまで自分が名乗っている通りである事を証明するものであり、リクエストの内容を隠すものではありません。リクエストの内容を隠したい場合はSSLなどを利用します。

    > コンシューマーがリクエストする際に公開鍵を指定する仕様なら、誰でもなりすましができてしまう。
    ハードコーディングは、公開鍵を事前に渡しておくことと捉えるなら、それなりに納得できる気もするが。

    公開鍵は誰が見ても、誰が使っても、なりすましには利用できません。
    署名の目的は、自分が名乗っている通りの者である事を証明すること。RSA秘密鍵を使って作られた署名は、RSA公開鍵を使ってのみ可逆なので、公開鍵で開けらる署名は秘密鍵の持ち主だと判断できます。また、その公開鍵で開けられる署名は、対となる秘密鍵でしか作る事ができません。

    というわけで、秘密鍵が漏洩することさえなければ、公開鍵をハードコーディングする事も、動的に公開鍵を渡す事も特に問題はありません。

  3. 石田 says

    RT @agektmr OAuthの署名方式を掘り下げる http://bit.ly/3Hl8Q9



Some HTML is OK

or, reply to this post via trackback.