2010年06月04日

「月の異名(というか、月の呼び名)」さらに……。

さて、先日月の異名(というか、月の呼び名というほうが一般的みたいですね)の算出ロジックを変更したとアップしたばかりですが、改めて、ちょっと詳しく書いてみようと思います。

まず、実例をご紹介します。
これは、2010年6月12日から、7月11日までのグラフです。
(これは、旧暦の5月いっぱいに相当します)
juneall.gif

月が出ている時間帯・旧暦の日付・そして、新しく変更した「月の呼び名」算出ロジックによる「月の呼び名」の変化状態を表しています。横軸の日付は、2日ごとにつけられており、たとえば、6/12 と書かれている線から、次の線までが、実際には6/12 になります。
画像では詳細が見られないと思いますので、詳しく見られるように、PDF にしたものをこちらにおいておきます。
tokyo_2006_06.pdf

まず、ここからわかるのは、6月12日から7月11日の間は30日あるのに、月は29回しか出ていないということです。
こんなわけで、月の呼び名は、(無理矢理全部につけたとしても)29個しかなく、30日間に割り振るのは無理だということだったのです。

さて、少しずつ見てゆきましょう。
まず、(旧暦での)月初めです。
jun01.gif
月初めは、太陽と月がほぼ同時に出入りしますので、この段階は、旧暦の日付と月の出現回数はよく揃っています。
実際、「節気さんシリーズ」でも、旧暦のついたちは、旧暦の日付にあわせています。
それでも、徐々に月の出が遅れてきているのがわかると思います。

引き続き、月の半ばです。
jun02.gif
ここで、6/29(6/28 と 6/30 の間)の線を横切っているのが、いわゆる十五夜の月です。
このように、夕暮れ近くから、夜明け近くまで、夜半をまたがって出現します。
当然、月が出ている間に、旧暦の15日から、16日に日付が変わってしまいます。
「今出ている月の名前」としては、夜半を境にして名前が変わってしまうというのは、やはりまずいかなと思うわけです。
このようなわけで、節気さんシリーズのロジックでは、一番上の線にあるように、月の出前から、月の入りの後までを、その月の名前として統一するという形になっています。
これが、出現回数を基準にした名付けです。

それでも、――十五夜が、「旧暦15日の夜の月」と言われているように――その日の夜の月の名前なのだと考えれば、まだつじつまは合います。

では、月末付近はどうでしょうか?
これが、月末付近の詳細です。
jun03.gif
ここで、7/6 の前の月の出は 7/5 の 23:31 です。そして、7/6 の後の月の出は、7/7 の 0:04 です。
つまり、カレンダー上では、7/6 には一度も月の出がなかったということになります。
ですから、7/6 は旧暦の26日であっても、「この日に出る月」の名前というのは、決められません。
また、7/7 の月の出の直前には、日付も旧暦の27日に変わってしまいますから、「その後に出る月」ともいえません。
こうして、旧暦の日付基準では、二十六夜に相当する月が決められなくなってしまうわけです。

節気さんシリーズでは、出現回数ベースで月の名前をつけているので、この、7/7 の未明に出ている月が、二十六夜の月になります。

種々述べてみましたが……やっぱり、図があるとわかりやすいですね。

2010年06月03日

「月の異名」再び

【2010年8月29日 追記】

この記事で書いている、「月の名前」の付け方(というか、名前を変えるタイミング)を変更しました。

もともと、月の名前というのは、現に空にあって見えている月に対するものかと思うわけで、月が沈んでいるときの名前というのはないような気もします。
が、節気さんシリーズで、一日中ツイートしている関係もあって、まあ、そうもいっていられない。

そこで、当初は、「月の入りの時刻と、次の月の出の時刻の真ん中で月の名前を変える」という方針にしました(この記事の後半にはそのままの形で残っていますが)

ただ、これだと、普通に「今日は十五夜です」などといわれるのに比べて、かなりタイミングが後ろにずれるわけです。
「今日は中秋の名月です」という日の、昼前まで別の名前をツイートしていたり。

これを考慮して、「日本全国で(実際には、50地域の月の出君がカバーしている50の地域)月の出が終わった10分後」に名前を変えることにしました。

これで、「月の出とそれに対応する月の入りの月の名前は同じ」という条件を確保しつつ、通常いわれるタイミングにかなり知覚することができました。

------- 追記ここまで。

さて、「節気さんシリーズ」で、月の異名(三日月とか、十六夜とかそういう名前)を表示するようにしました。
この月の異名は、多くは旧暦の日付に基づいたものであるとして、旧暦の日付の日付を算出して、それに名前を割り当てるようにしていたのですが、どうも、これは違うらしいという記述を見つけました。

直接見たのは、WikiPedia の、この記事です。

http://ja.wikipedia.org/wiki/%E6%9C%88
(記事の中の、「月齢と呼び名」)


ただ、当初は、「旧暦の日付ではなく、月が出た回数を元に決める」ということの真意がわからず、節気さんシリーズでは、上述の通り旧暦の日付をもとに名前をつけていました。

ところが、これではちょっとまずいかもしれない――と、気づきました。
たとえば、このブログを書いている2010年6月はじめは、月は午後11時過ぎに昇り、翌日の午後になって沈みます。
ところが、節気さんシリーズの月の名前は、「旧暦の日付」に基づいていますから、午前0時で(日付が変わるのに伴い)名前が変わってしまいます。
しかし、現に空にある月の名前が、突然変わってしまって良いものでしょうか? せめて、月の出から月の入りまでは「同じ名前」でないとまずいのではないでしょうか?
これが、「旧暦の日付ではなく、月が出た回数で決める」という記述の真意でした。

さて、これで計算しようとすれば、(旧暦における)一ヶ月分の月の出・月の入りの時刻一覧を準備しなければなりません。さらに、月の出から月の入りまで――ということは、その日の月の出・月の入りの時刻に依存するというわけで、言い換えると、「どの場所における」というのを定義しないと、「今から臥し待ち月」などといえないわけです。

悪いことに、節気さんシリーズの「月齢君」は、地域に依存しないような Bot にしています(実際、月齢と月相は地域に依存しない)。
結局、以下のように処理をして、なんとか、それらしく表示することにしました。

・朔を含む日は「朔月」とする。(優先)
・朔の前の日(旧暦の月末)は、「晦日」とする。(優先)
・前回の月の入りの時刻と、今回の月の出の時刻の真ん中を、「名前が変わるとき」とする。
 ※この場合の、月の出・月の入りの基準は「東京」
 ※いすれにしても、地球の裏側に月があるときなので、地方毎の誤差は気にしないことにします。
・「今の時刻」が、「名前が変わるとき」を何回通過したかを元に、月の名前を決める。

当面、これで様子を見ることにしました。

2010年05月30日

月に関するいくつかの指標 ―― 月齢・月相 そして、月の異名

「節気さんシリーズ」に、最近、「月齢君」を加えました。
その件は、ご案内ということで、記事にいたしましたが、このときに、月の異名を併せて表示するようにしました。
また、節気さんシリーズ全体としても、月に関しては、「月齢」と「月相」という二つの数値を表示しています。

ここでは、このあたりのことについて書いてみたいと思います。

【基準となる瞬間 ―― 朔】

月に関わる数字で、日常的に関わる(言い換えると、地球から見たときに関わりのある数字)の基準は、「朔」です。
言い換えると、新月の瞬間ということで、さらにいえば、「太陽と月が同じ方向に見える瞬間」です。
ただ、同じ方向といっても、太陽と月は滅多に重ならないので(完全に重なるときには日蝕になります)おおざっぱに言えば、横方向の位置が一致したときになります。
※ただし、横方向というのが、地平線の方向ではないので、横方向の位置が一致したときといっても、もしも見えたら(それこそ、新月の瞬間なので実際は見えませんが)違和感のある位置だと思います。

これを基準にして、月齢や月相が定義されます。

【月齢とは】

堅い言葉で言えば、「朔の瞬間からの経過日数」です。
たとえば、これを書いているときから、一番近い朔(新月の瞬間)は、2010年6月12日の20:15(日本時間)です。
これを元にして、翌日(6月13日)の20;15 には月齢1、翌々日(6月14日)の20:15には、月齢が2……と数えるわけです。

【小数点のある月齢表示は?】

上記の通り、「朔の瞬間」を基準に月齢を数えるわけですが、さらに、1日 = 1.0 として、算出する場合に小数点以下を含めた表示を行います。上記の例では、12時間(= 0.5日)経過した翌日(6月12日)の、8:15 には、月齢 0.5 となります。

【月齢と月の形】

さて、月齢というのは経過時間を元にした数字です。一方で、月が地球の周りを回る早さも、地球が太陽の周りを回る早さも一定ではありません。こんな訳で、月齢と月の形は、完全には一致しません。
たとえば、2010年5月28日 8:07 は満月になった瞬間ですが、このときの月齢は 13.9 でした。
一方で、2010年12月21日 17:13 の満月は、月齢 15.6 です。
そうはいっても、月齢12で満月になるというようなことはありませんから、十分目安にはなるということです。

【月相とは】

これに対して、月の形を正確に反映しているのが「月相」です。
月相とは、「見かけの月と太陽がなす角度」のことされています。
つまり、月相が0度であれば、太陽と月は同じ方向=新月。180度なら、反対方向=満月。90度と270度は半月です。
これには、もうひとつの表し方があって、0度〜360度を、0〜28の数字で表すものです。節気さんシリーズで使用しているのはこちらの数字になります。
こちらの数字を使った場合には、月相0が新月、月相14が満月、月相7と21がそれぞれ半月です。
上述した、5月28日と、12月21日の満月も、月相はいずれも14.0になっています。

※節気さんシリーズで、「そろそろ満月」「概ね上弦」「まさに新月」などと表示しているのは、この、月相を基準にしています。

【旧暦の日付と、月の異名】

さらに関連しているのが、旧暦(太陰太陽暦でした)の日付です。
この暦は、「朔の瞬間を含んだ日がついたち(一日)」として、それ以降、2日、3日……と日付を振っていったものです。
そして、月の異名の多くが、この日付を基準としています。

よく知られている、「十五夜」という表現は、この、「旧暦15日の夜の月」を意味しています。
旧暦の日付の決め方は、先に述べた月齢の定義と類似しています。言い換えれば、月の異名もまた、月の形と完全には一致しないということです。
このため、いわゆる中秋の名月(旧暦8月15日の夜)は、必ずしも満月ではないという事態も発生します。
(もっとも、満月に近いというのは間違いありません)


節気さんシリーズにおいて、月の名前は、以下のようにつけています。

朔月(1)・既朔(2)・三日月(3)・夕月(4)・夕月(5)・宵月(6)・弓張月(7)
九夜月(9)・十日夜(10)・十日余の月(11)・十三夜(13)・小望月(14)・十五夜(15)
十六夜(16)・立待月(17)・居待月(18)・臥待月(19)・更待月(20)・二十日余の月(21)
弓張月(23)・有明月(24, 25, 27, 28)・二十六夜(26)・暁月(29 以降)
(括弧の中は、朔を含む日から数えた(当日も含む)付きの出現回数)

※ただし、朔の前日(旧暦の月末)は、晦日月

2010年05月25日

(ご案内)節気さんシリーズに、「月齢君」を追加しました。

え……タイトルの通りです。
節気さんシリーズには、月齢・月相「だけ」をつぶやくBotはありませんでした。
というわけで、なんとなく、「月齢君」を追加しました。

・一日に14回(午前と午後の、0時(12時)・3時・5時・6時・7時・9時・10時)に月齢と月相をつぶやきます。
・つぶやく時刻が中途半端なのは……作者が、「月の情報ならこの時刻かな」と適当に設定しました。
・毎正時だとちょっと多すぎるかなどうかな、などと思いながら。
・朔月・望月・半月の瞬間に、「ただいま朔(新月)です」などとつぶやきます。
・朔月・望月・半月が近づくと、(おおむね2日前から)そろそろ、概ね、ほとんど、まさに……などをつけて、つぶやきます。
・朔月・望月・半月の前後(20時間以内)には、「xx時間xx分後」とか、「xx時間xx分前」などもつけます。
・最後の3つは、節気さんシリーズ(世界の……を除く)共通の仕様ですが。

以上、ご案内でした。

そうそう、URL は、 http://twitter.com/sekki_getsurei です。

2010年05月19日

ツイッターのツイートはどこまで公開されているのか

この記事を書いている日、ツイッターでは、「無断フォロー」をきっかけとして、ちょっとした騒動があった。
その是非は置くとして、少なくとも、「自分のツイートを無断で見て欲しくない」という感情を抱きつつ、ツイッターを続けていたということなのだろうなと思う。

さて、この件については、類似の内容を「ツイッターの『嘘』」というタイトルで書いたばかりであるが、今一度、書いてみたい。

【ツイッターの一般的な印象】

どうも、インターネット上の「掲示板」などに比較すると、一般的な使い方では、ツイッターというのは、ずいぶんと「閉じた」環境に見えるらしい。
自分のフォロワーや、フォローを中心としたタイムラインという閉じた世界で、ツイートが連続するというイメージである。

だから、知らない人に勝手にフォローされる=知らない人に自分のツイートが読まれるのはちょっといやだな――という、そういう感覚が発生しうるのだろう。
しかし、考え方を変えれば、誰かをフォローするというのは、「ツイートを読みます」と意思表示をした上で読むということに過ぎない。
実際、そういった意思表示をしなくても、ツイートを読む方法というのは普通に存在するのだし、また、むしろ、自分が全く知らないところでも読まれ得るのだと意識しておくのは悪くないと思う。

【誰かのツイートを読むいくつかの方法】

たとえば、私自身、@asano_nagi のツイートを読むにはどんな方法があるだろうか。

ひとつは、 http://twitter.com/asano_nagi にアクセスするという方法である。これはあえて紹介する必要もないだろうと思う。
もうひとつは、 http://twitter.com/statuses/user_timeline/59402332.rss を RSSリーダーなどにフィードするという方法である。

これらは、特に珍しい方法ではない。そして、注目すべきは、ログインする必要も、そもそも、ツイッターのアカウントを持っている必要もないということである。

【もしかしたら、嗜好に関わる問題かも】

さらにいえば、ツイッターには、「おきにいり」という機能がある。
文字通り「おきにいり」だったり、後で読もうという目印だったり、それぞれに使われている機能だと思う。

いずれにしても、この機能を、「自分だけのメモ」として使っているというケースも多いのではないかと思う。
しかし、これも、たとえば、http://twitter.com/asano_nagi にアクセスしたあと、その場所で、「おきにいり」をクリックすれば、見ることができてしまう。
これも、ログイン不要である。
「自分自身のメモ用」として使うのか、「私としてはこれをおすすめします」という意味で使うのか、どちらを意識するかで、内容も異なってくると思うのである。

また、「ふぁぼったー」というサービスを経由すれば、さらに過去にさかのぼって「おきにいり」を確認することができる。

【終わりに】

以上書いたように、ツイッターのツイートは(そして、「おきにいり」も)普通に公開されているものである。
わざわざフォローしなくても、それどころか、ツイッターのアカウントを持っていなくても見えるものであると、そういう意識が、どこかで必要なのではないかと、そう思うのである。

※もっとも、ツイートを「公開しない」設定の場合、それは、きっと公開されていないのだろうと思う。
posted by 麻野なぎ at 21:08| Comment(0) | TrackBack(1) | Twitter と Bot の周辺

2010年05月18日

OAuth への道 ―― Twitter 専用 OAuth 認証モニタ(とっても簡易版)

Twitter における、Basic 認証の終了期限が近づいております。
そういうわけで、節気さんシリーズは、なんとか、OAuth 対応を終えたわけですが、もしかして役に立てばと思い、検討中に使用した、簡易型のモニタをアップしてみました。

oauth_mon.gif

ただし、もともと、単なる確認用に、やっつけ仕事で作成したものなので、statuses/update (単に、つぶやきを、ポストするだけ) しか対応していません
また、つぶやきとして設定する文を作成する手段も持っていません。
さらに、Proxy にも対応していません
それでも、もしも役に立つところがあれば

というわけで、実体はこちら → http://axis.blue/tec/oauthmon.html


posted by 麻野なぎ at 21:38| Comment(0) | TrackBack(0) | Twitter と Bot の周辺

2010年05月17日

OAuth への道 ―― OAuth はなぜ安全か(もうひとつ追加)

OAuth だと Basic 認証に比べてなぜ安全なのか? これは、以前に書いたのですが、書き忘れが当たったので追加します。
もうひとつ、OAuth 認証だと、「誰が書き込んだか」がはっきりわかるという点があります。
たとえば、あるアカウントから大量・無差別なメッセージが書き込まれたとします。
これは、誰がやったのでしょう?

もしかしたら、そのアカウントの正当な利用者かもしれません。もしくは、その利用者が利用しているどこかのサービスかもしれません。もしくは、パスワードが盗まれたのかもしれません。詐欺的なサービスに引っかかったのかもしれません。

従来、このような場合、「アカウント停止」という手段がとられがちでした。
そのアカウントの所有者が、本当に「やった」のかどうかが判断できないのと、それ以前に、SPAM を確実に止めるとしたら、そのアカウントを停止するしか方法がなかったからです。

Basic 認証では、「該当のアカウントのIDとパスワードだけを使う」仕様なので、これは同じ事です。
一方で、OAuth 認証が絡むと事情が変わってきます。
OAuth 認証で何かをしようと思うと、該当するアカウントに関する情報だけでなく、それを投稿する側の(たとえば Bot の)情報も必要です。
ですから、もしも、あるアカウントからSPAMが発信された際、少なくとも、「どんなアプリケーションを使ったか」は特定できます。

それが、たとえば、詐欺的なアプリケーションだった場合、(ユーザーのアカウントではなく)そのアプリケーションのアカウントを停止することで、ユーザーアカウントを有効にしたまま、SPAM を止めるということもできるようになります。

こういう利点もあるのでした。
posted by 麻野なぎ at 12:03| Comment(0) | TrackBack(0) | Twitter と Bot の周辺

2010年05月16日

OAuth への道 ―― C++で、OAuth認証(ただし、単純な Bot 限定)

さて、最終的に、OAuth 認証ヘッダを作成して、Bot として動作できそうなところに来ました。
実は、私が管理しているのは、「節気さんシリーズ」といいまして、単純に生成したメッセージを(とりあえず、メッセージを生成するまでの過程はそれなりに複雑)単純にポストするだけのものです。
ですから、Twitter へのリクエストは、POST http://api.twitter.com/1/statuses/update.xml のみです。(一応レスポンスのコードはチェックしていますが)

まず、非常におおざっぱに言いますと、Basic 認証であろうと、OAuth 認証であろうと、送信するヘッダ、ボディはほとんど同じです。
Authorization: Basic (Basic 認証ヘッダ)が
Authorization: OAuth (OAuth 認証ヘッダ)に変わるだけです。

というわけで、OAuth 認証ヘッダを生成できれば、Botとして動作可能というわけです。

----------- OAuth 認証ヘッダ作成プログラム -----------------
こんなのを作りました。

ヘッダファイル : create_oauth.h : http://www.axis.blue/tec/create_oauth.h
ソースファイル : create_oauth.cpp : http://www.axis.blue/tec/create_oauth.cpp

※上記のソースの中で、

#include <system.hpp>
#include <Classes.hpp>

の2行と、

void makeNonce() にある、 AnsiString time = Now().FormatString("yyyy/mm/dd-hh:nn:ss");
int UnixTime(TDateTime aTime) や、void makeTimeStamp() にある、Now() や、TDateTime 型は、Turbo C++ の処理系に依存しています。

別の処理系では、
AnsiString time = Now().FormatString("yyyy/mm/dd-hh:nn:ss");
は、単純に、time = "aaajajajajaja"; // ランダムな文字
とかで良いはずです。

時刻系のものは、なんとか、Unix Time を算出してください。(Visua C++ なら、CTime が使える気がします。

さらに、AnsiString も、処理系依存です。
こちらは、ほぼ、std::string で書き直せると思います。

これが、OAuth 認証ヘッダの生成に使うソースになります。

------------- 具体的にポスト ----------------------------

まず、単純に、abcd という文字をポストすることにします。
ボディは、 status=abcd です。

また、基本情報として、

OAuthDataDef mine =
{
"My_API_Name", // これは実際には使いません
"my_Consumer_key", // 実際には、入手した Consumer_key 以下同じ
"my_Consumer_secret",
"my_Access_Token",
"my_Access_Token_Secret"
};

と元になるキーを定義しておきます。
また、Body は、

char *body = "status=abcd";

とでもしておきます。

さて、このあと、

makeNonce(); // Nonce の生成
makeTimeStamp(); // timestamp の生成

AnsiString key = mine.Consumer_secret;
key += "&";
key += mine.Access_Token_Secret;
// ここまで、HMAC-SHA1 の鍵生成

AnsiString baseString = makeBaseString(mine, body);
// Base string を生成して

makeSignHere(baseString, key);
// シグネチャーを作って、

AnsiString oauthHeadder = makeHeadder(mine, body);
// OAuth 認証ヘッダを生成

となります。
create_oauth の内部構造が整理できていないので、呼び出しはこの順番でなければなりません。

※例によって、AnsiString は、処理系依存です。これも、std::string で置き換えられると思います。

ここまでで、OAuth ヘッダが生成できました。あとは、これを送信するだけです。
すでに、コネクションが成立したという前提で、(さらに、server->SendTo() でテキストが送信できるという前提で)

まず、"Content-Length: を生成します。

const char * CRLF = "\x0d\x0a";

AnsiString lenHeader = "Content-Length: ";
lenHeader += std::strlen(body);
lenHeader += CRLF;

で、

server->SendText("POST http://api.twitter.com/1/statuses/update.xml HTTP/1.1" CRLF);
server->SendText("Host: api.twitter.com" CRLF);
server->SendText("Content-type: application/x-www-form-urlencoded" CRLF);

oauthHeadder += CRLF;
server->SendText(oauthHeadder);
server->SendText(lenHeader);
server->SendText(CRLF);

server->SendText(line);
server->SendText(CRLF);

となります。
あとは、レスポンスを待つことになります。

【補足】

上記の例では、単純化するため、送信テキストを、"abcd" にしました。
しかし実際には、日本語を送信することが多いでしょう。
たとえば、
status=おはよう
であれば、UTF-8 で、URLエンコードしますから、実際に送るテキストは、

status=%E3%81%8A%E3%81%AF%E3%82%88%E3%81%86

になります。
シグネチャーを作成するための Base Text では、ここからさらに ERL エンコードされるので、Base Text の中では、
status%3D%25E3%2581%258A%25E3%2581%25AF%25E3%2582%2588%25E3%2581%2586
となります。

このあたり、最初ちょっと気がつきませんでした。
posted by 麻野なぎ at 11:06| Comment(0) | TrackBack(0) | Twitter と Bot の周辺

OAuth への道 ―― Bot にとって、OAuth とは何だったのか?

OAuth については、種々解説もありますが、もともと、OAuth という考え方は、「いかに安全に第三者に自分のアカウントへのアクセスを許すか」という点を重視したものです。
ですから、実際のところ、「ユーザーの許可をどう得るか」という点に、多くの機能があてられています。

一方で、Twitter の Bot は、自作のものである限り、Bot の作者も、Bot のアカウントの管理者も同一だと考えて良いでしょう。つあり、はじめから、「ユーザー(この場合は、Bot のアカウント)の許可」はとれているということになります。
そのため、「Twitter で Bot として振る舞う」だけであれば、一般的な OAuth の解説のうち、かなりの部分を省略できます。

【OAuth の「一般的な」手順】

OAuth の解説の中で、一般的な手順は、たとえばこのように書かれています。
( APIアクセス権を委譲するプロトコル、OAuthを知る http://www.atmarkit.co.jp/fsecurity/special/106oauth/oauth02.html より、記述はかなり省略してあります)

1.コンシューマ登録
(1) コンシューマは、APIを通じたユーザーリソースの利用者としてサービスプロバイダへ登録を要求する。
(2) サービスプロバイダは、「コンシューマ・シークレット」をコンシューマに発行する。

2.リクエスト・トークン要求とユーザーの同意確認
(1) ユーザーはコンシューマのサービスを利用するために、Webブラウザでコンシューマにアクセスする。
(2) コンシューマはサービスプロバイダに接続して「リクエスト・トークン」の発行を要求する。
(3) サービスプロバイダは未承認の(Unauthorized)リクエスト・トークンをコンシューマに返す。
(4) コンシューマは、リクエスト・トークンにユーザーの承認を取るために、をサービスプロバイダにリダイレクトする。
(5) サービスプロバイダはユーザーにコンシューマがアクセスするユーザーリソースの内容と条件を表示し、同意の確認を促す。
(6) ユーザーの同意が取れたら、リクエスト・トークンを「承認(Authorized)」にして、コンシューマへリダイレクトして返す。

3.アクセス・トークン要求とAPI接続
(1) コンシューマは「アクセス・トークン」の発行を要求する。
(2) サービスプロバイダはアクセス・トークンと「トークン・シークレット」をコンシューマに返す。
(3) コンシューマはAPIに接続を要求する。
(4) サービスプロバイダはそれぞれのパラメータの値を確認し、問題がなければ、APIの応答データをコンシューマに返す。

これをすべてこなすのはかなり大変です。

【Twittter の Bot として振る舞う際に、最低限必要な手順】

1.コンシューマ登録
(1) コンシューマは、APIを通じたユーザーリソースの利用者としてサービスプロバイダへ登録を要求する。
(2) サービスプロバイダは、「コンシューマ・シークレット」をコンシューマに発行する。

3.アクセス・トークン要求とAPI接続
(1) コンシューマは「アクセス・トークン」の発行を要求する。
(2) サービスプロバイダはアクセス・トークンと「トークン・シークレット」をコンシューマに返す。
(3) コンシューマはAPIに接続を要求する。
(4) サービスプロバイダはそれぞれのパラメータの値を確認し、問題がなければ、APIの応答データをコンシューマに返す。

以上です。2.項が丸ごと抜けてしまいました。
これでもちょっと大変……という気がしますが、実運用は(Bot に限定すれば)それほどでもありません。

既に書きましたが、
(Bot 用、Access Token、Access Token Secret 入手法 http://asano-nagi.sblo.jp/article/37853895.html
Twitter にログインした状態で、簡単に入手できるわけです。

これをふまえてさらに書き換えると

【Twitter の Bot として振る舞う際に、最低限必要な手順 ―― Twitter にログインして】

1.準備
(1)コンシューマ登録をし、Consumer key, Consumer secret を取得する (上記「入手方法」の1.〜5.)
(2)その後、My Account Toke をクリックして、Access Token と、Access Token Secret を取得する。
   (上記「入手方法」の6.〜8.)

2.Bot として動作するとき
(1)OAuth 認証ヘッダを作成する。
(2)それを使って認証を行う。

以上に集約できます。

OAuth 認証ヘッダについては、次の機会に。
posted by 麻野なぎ at 11:04| Comment(0) | TrackBack(0) | Twitter と Bot の周辺

2010年05月15日

OAuth への道 ―― OAuth はなぜ安全なのか

さて、OAuth の具体的な対応方法は一時お休みして、そもそも、OAuth 認証というのが、Basic 認証に比べてなぜ安全なのか、とう安全なのかを書いてみようと思います。
一般的な解説記事などによれば、OAuth が安全なのは、「ユーザーのIDとパスワードを使わないから」といわれています。
確かにこの通りではあるのですが、OAuth では、その代わりに、Consumer key, Consumer secret, Access Token, Access Token Secret という4つの鍵を使用します。
そして、確かに、(ボットがそうするように)このキーを使って、ユーザーのかわりに様々な操作をすることができます。
さて、IDとパスワードなら危険で、同じように様々な操作をすることができる、4つの鍵なら安全だというのはどういうことでしょうか?

まず、何をもって「安全」とするかを考えなければなりません。
たとえば、従来の Basic 認証ならユーザーに成り代わっていろいろなことができるけど、OAuth 認証ではできることが限られるというわけではありません(ただし、実際には、「できることを制限する」という機能はあります)
また、一時話題になった、ダイレクトメッセージの機能を使って、SPMA のような拡散をさせるというものがありましたが、これも、OAuth 認証の元で動いていました。
ですから、ユーザーが、「承認した」状態では、機能的にはどちらであっても同じことできてしまいます。

では、何が「安全」なのでしょうか? それは

・ユーザーがいつでも(自分のパスワードを変更しなくても)承認を取り消すことができる。
・ユーザーがいつでも自分の都合でパスワードを変更できる。
・OAuth 認証では、ホストに送信される情報が盗まれても、それが流用できない(Basic 認証だとこれができてしまいます)

という点になります。

【ユーザーはいつでも承認を取り消すことができる】

従来のBasic認証では、それが、Twitter クライアントであっても、つぶやきの転送のようなものであっても、IDとパスワードを、連絡しなければなりません。(または、設定しなければなりません)
逆に言えば、何かのサービスを「もう使いたくない」として、絶対に使われないようにしようと思えば、パスワードを変更するという方法しかありませんでした。
新しいパスワードを知らない、クライアントなりサービスなりは、それ以降ユーザーのアカウントにアクセスできなくなります。
しかし、言い換えれば、そのほかの「まだ使いたい」サービスなどに対しても、パスワードを変更したと連絡する必要があるということです。

これに対して、OAuth 認証の枠組みでは、特定のサービスの「承認を取り消す」ことで、それ以降アクセスを禁止することができます。

【ユーザーはいつでも自分のパスワードを変更できる】

これは、前項とは逆の状況です。
たとえば、安全のために定期的にパスワードを変更する。または、パスワードが漏れたらしいので、変更する。
これも、従来の Basic 認証の枠組みでは、自分が使っているクライアントやサービスの事情をいちいち気にしなければなりません。

これに対して、OAuth 認証の枠組みでは、ユーザー以外のサービスはパスワードを使いませんから、いつでもパスワードを変更することができます。

【ホストに送信される情報が流用できない】

実は、「安全」という観点ではこれが一番重要なポイントです。
まず、インターネットでは、「暗号化」がなされていない限り、ホストに送信される情報は(受ける情報も)盗まれる可能性があるというのが前提となります。
ですから、Basic 認証であろうと、OAuth 認証であろうと、ホストに送信される「ユーザーのアカウントにアクセスするための情報」は、盗まれる可能性があります。

ただ、「盗まれた」情報が流用できるかどうかで、Basic 認証と、OAuth 認証の安全性に差が出ているわけです。

Basic 認証では、ホストに送信されるユーザー情報は、ユーザーのIDとパスワードから生成されるもので、いつでも同じものです。
つまり、一度盗まれてしまえば、何度でも(ユーザーが気づいてパスワードを変更するまで)利用できてしまいます。
これが、Basic 認証におけるセキュリティ上の問題点とされていたわけです。

一方で、OAuth 認証において、ホストに送信されるユーザー情報は、「アクセスの度に変化」します。
このため、ユーザー情報が盗まれたとしても、その情報は、2度と使えないという仕掛けになっています。

その仕掛けについて、少々書いてみましょう。

OAuth では、ホストに送信されるユーザー情報は、
「Consumer key」「Access Token」「付加情報」「署名」
です。
ここで注意したいのは、先に紹介した4つの鍵のうち、2つの鍵しか送信しないということです。
つまり、送信する情報が丸ごと盗まれたとしても、まだ、2つの鍵については秘密が守られるということです。

また、「付加情報」には、「Timestamp = 送信時刻」と「nonce = ランダムな文字列」が含まれます。
送信時刻が含まれるため、このTimestamp とかけ離れた(実際には、5分を超えたずれのある)時刻に受け取られたものは、ホストから拒否されます。
まず、盗んだ情報を元に、毎日アクセスするなどということはできないわけです。
さらに、「ランダムな文字列」というのは、単に、ランダムなだけではなく、「送信の度に異なる」ものでなければなりません。

送信時刻は、5分までのずれが許されました。といって、盗んだ情報をすぐに使おうとしても、今度は、「nonce = ランダムな文字列」として、「同じものが送信された」ということで、やはり、ホスト側から拒否されます。

したがって、もしも、この情報を盗んだとしても、2度とつかない情報だというわけです。

最後に、「署名」です。
この署名は、送信する、「Consumer key」「Access Token」「付加情報」の部分を、「鍵」を使って行います。
処理の内容は省略しますが、つまりは、署名に使う「鍵」を知っている人でないと署名を作成できないというものです。

さて、この、「鍵」になるのが、残った、Consumer secret, Access Token Secret の2つです。
つまり、この鍵を知らなければ、署名が作成できません。

前述の通り、「全く同じユーザー情報は2度と使えない」「異なる情報を作ろうとすれば、secret という名前のついた鍵が必要」「しかも、secret という名前のついた鍵は、ホストに送信されることがない」ということで、情報が盗まれたとしても安全だという仕掛けです。

【最後に――全部の鍵が盗まれたら】

以上のことを踏まえると、Consumer key, Consumer secret, Access Token, Access Token Secret が揃っていれば、不正アクセスでもできてしまうということになります。
一応、Consumer secret, Access Token Secret は盗まれることがない仕掛けになっているのですが、パソコンを丸ごと盗まれるとか、いろいろあるかもしれません。

実は、その場合でも、気づけば(というか、本当は、盗まれたことに気づくということが最も重要)アプリケーションの作者は、Consumer key, Consumer secret を変更できます。この時点で、盗まれた、Consumer key, Consumer secret は、無効になってしまいます。
しかも、Access Token, Access Token Secret も、「このアプリケーション専用」なので、他のアプリケーションから、盗んできた Access Token, Access Token Secret をもとに不正アクセスするということもできません。

このようなわけで、少なくとも、被害拡大は防げるようになっているわけです。
posted by 麻野なぎ at 20:43| Comment(0) | TrackBack(0) | Twitter と Bot の周辺