2010/09/11


以前、twitter上で「STL以上、Boost未満な使い心地のライブラリが欲しい。ネットワーク関連込みの。」とつぶやいた所、id:faith_and_braveさんから返事貰った。
Faith and Brave Twitter / Faith and Brave

CLX or Message-Pack or Pocoあたりでしょうか RT @mattn_jp: STL以上、Boost未満な使い心地のライブラリが欲しい。ネットワーク関連込みの。

http://twitter.com/cpp_akira/status/21234425525
CLXは実は前から知っていて何度か捨てコードに使わせて頂いていたのですが、SSL越しにproxyが使えなかったので、ネットワーク関連のコードには使ってませんでした。
まぁでも一応書いて判断すべきかなと思って、僕的な答えとして、さらーーーっと書いた。
CONSUMER_KEY と CONSUMER_SECRET を書き換えて実行して下さい。xAuth認証を使ってtwitterにステータスをポストします。

#include <iostream>
#include <sstream>
#include <clx/base64.h>
#include <clx/hexdump.h>
#include <clx/date_time.h>
#include <clx/format.h>
#include <clx/hmac.h>
#include <clx/https.h>
#include <clx/random.h>
#include <clx/salgorithm.h>
#include <clx/sha1.h>
#include <clx/uri.h>

std::string url_encode(const std::string& url) {
    std::ostringstream rets;
    for(size_t n = 0; n < url.size(); n++) {
        unsigned char c = (unsigned char)url[n];
        if (isalnum(c) || c == '_' || c == '.' || c == '-')
            rets << c;
        else {
            char buf[8];
            sprintf(buf, "%02X", (int)c);
            rets << '%' << buf[0] << buf[1];
        }
    }
    return rets.str();
}


int main(int argc, char* argv[]) {

    if (argc != 4) {
        std::cerr << "usage: " << argv[0]
            << " [username] [password] [message]" << std::endl;
        return -1;
    }

    clx::date_time now;
    clx::random<unsigned int> randgen;
    randgen.engine().seed(time(0));

    std::string consumer_key = "CONSUMER_KEY";
    std::string consumer_secret = "CONSUMER_SECRET";
    std::string username = argv[1];
    std::string password = argv[2];
    std::string message = argv[3];

    std::stringstream ss;
    std::string times = clx::str(clx::format("%s") % now.c_time());
    std::string nonce = clx::hexdump(times);

    ss << "oauth_consumer_key=" << consumer_key
       << "&oauth_nonce=" << nonce
       << "&oauth_signature_method=" << "HMAC-SHA1"
       << "&oauth_timestamp=" << times
       << "&oauth_version=" << "1.0"
       << "&x_auth_mode=" << "client_auth"
       << "&x_auth_password=" << password
       << "&x_auth_username=" << username;

    std::string key = consumer_secret + "&";
    std::string val = "POST&";

    val += url_encode("https://api.twitter.com/oauth/access_token");
    val += "&";
    val += url_encode(ss.str());
    char* hmac = (char*)clx::hmac<clx::sha1>(
            key.c_str(), key.size(), val.c_str(), val.size()).code();
    std::string hm = clx::base64::encode(hmac, 20);

    ss << "&oauth_signature=" << url_encode(hm);

    clx::https session(clx::uri::encode("api.twitter.com"), 443);
    session.post(clx::uri::encode("/oauth/access_token"), ss.str());

    std::vector<std::string> item;
    std::map<std::string, std::string> params;
    clx::split_if(session.body(), item, clx::is_any_of(LITERAL("&")));
    for (unsigned int i = 0; i < item.size(); i++) {
        std::string tok = item.at(i);
        size_t pos = tok.find_first_of("=");
        params[tok.substr(0, pos)] = clx::uri::decode(tok.substr(pos+1));
    }


    ss.str("");
    ss.clear(std::stringstream::goodbit);

    ss << "oauth_consumer_key=" << consumer_key
       << "&oauth_nonce=" << nonce
       << "&oauth_signature_method=" << "HMAC-SHA1"
       << "&oauth_timestamp=" << times
       << "&oauth_token=" << params["oauth_token"]
       << "&oauth_version=" << "1.0"
       << "&status=" << url_encode(message);

    key = consumer_secret + "&" + params["oauth_token_secret"];
    val = "POST&";

    val += url_encode("https://api.twitter.com/1/statuses/update.json");
    val += "&";
    val += url_encode(ss.str());
    hmac = (char*)clx::hmac<clx::sha1>(
            key.c_str(), key.size(), val.c_str(), val.size()).code();
    hm= clx::base64::encode(hmac, 20);

    ss << "&oauth_signature=" << url_encode(hm);

    session.post(clx::uri::encode("/1/statuses/update.json"), ss.str());
    std::cout << session.body() << std::endl;

    return 0;
}

/* vim:set et sw=4: */
URLまわりと、POSTパラメータ構築に便利なのがあっても良いかなと思った。あーそれboost::asioでも言えるか。
Posted at by




先日emacsからtwitter出来る、twittering-modeというのを試してみたんですが、ちゃんとOAuth出来てて便利でした。lispでも色々出来るなーと感心しました。
EmacsWiki: Twittering Mode

twittering-mode.el is a Twitter client

http://www.emacswiki.org/emacs/TwitteringMode
それと同時に、いつもの妖精が耳元でささやいた。
「vimスクリプトでもきっと書けるさ」
で、書きました。
mattn's vim-oauth at master - GitHub

oauth access library for vim

http://github.com/mattn/vim-oauth
sha1, hmac, base64 の処理には、Nakadairaさんの物を使わせて頂きました。
vimでtwitter出来るvimscriptとしてtwitvimがありますが、こちらはOAuthな処理をpython/perl/ruby拡張でやってます(どれか有効な奴を使う)。
vim-oauthがあれば、pure vimscriptでOAuth対応のtwitterが可能です。添付のtwitter.vimのCONSUMER_KEYとCONSUMER_SECRETを書き換えてご試して下さい。最終引数はディクショナリにしてあるので、自分でパラメータを変えればxAuthにも対応可能かと思います。
ちなみにtwitvim、nr2charの使い方が間違ってるのでwindowsで実行すると文字化けしてました。patchを書いて作者と連絡中です。
Posted at by



2010/09/10


ようやくTwitterのやりたい事が分かった気がする。

数日前、TwitterのxAuth/OAuthの扱いについての記事を書いた。
レスポンスの悪さや開発者に足を向けているとも思える対応に、イヤミたっぷりの文面を残したのだが...
mattn:

ところで、Basic認証を廃止した事でTwitterはポスト出来てるアプリケーションの50%を殺したんだと、私は信じているよ。

そのお返事が来ました。が、いきなり出口を塞がれてしまいました。

Twitter Support:

Hi,

Again, we ask that you do not distribute your application's keys and secrets with its source. We are happy to review your application for xAuth once you provide the requested information about it (such as an overview of its functionality and a screenshot of it in action on a Unix-based system or Windows). If xAuth is granted, it will only apply to your application keys and developers who want to compile your source will need to register their own application, apply for it to have xAuth as well, and plug their own keys into the source.

I apologize for the inconvenience that this causes. Please let me know how you would like to proceed.

Thanks

こんにちわ

繰り返しますが、アプリケーションの key および secret はソースで配布しない様、私達はお願いしておきます。 お願いしおりますアプリケーションについての情報(UNIX ベースのシステムもしくは Windows での動作スクリーンショット、および機能概要など)を提供頂いた後に、貴方のアプリケーションについて xAuth の審査をするのが楽しみです。 xAuth が権限付与される場合、それは貴方のアプリケーションキーに対してのみ適用され、貴方のソースをコンパイルしたい開発者は各々のアプリケーションを登録し、その上で xAuth を使える様に反映、そして自信のキーをソースに差し込む事になります。

これに起因するご不便をお詫び致します。どの様にされたいか教えて下さい。

ありがとうありがとう
やっぱりオフィシャルの意向としてはCONSUMER_KEYとCONSUMER_SECRETは公開するなというのが指針らしい。
それではという事でまとめて質問してみた。
mattn:

I have few question.

1. How dangerous publishing the key can be possible?
  If I put the key in the source code, what can be happen?
2. How worse is the hyjack as your said?
  Juggle of timeline of users of my application?
  Speaking ill of my application?
  Spam?
3. How many times we get approval to xAuth?
  I got replies of this issue for 1 or 2 days.
  user of my application will also looking for?

I'm finding the best way or best solution of following problem.

1. All users can use my application immediately.
2. The source code is open source completely.
3. Easy to use, no using browser, no copy and paste of pin code.

Do you have any idea?

I created UI. maybe possible to compile on unix.
screenshot is here:
  http://mattn.tumblr.com/post/1090305624/gtktweeter-on-win32-oauth

Currently, I pushed source code to repository without key.

Thanks. Thanks.

幾らか質問があります。

1. キーを公開するという事はどんな危険がありえるのか?
  ソースコードにキーを置く場合、何が起き得るのか?
2. 貴方の仰るハイジャックはどんなに悪い物か?
  私のアプリケーションを使うユーザのタイムラインを改ざん?
  私のアプリケーションに対する中傷?
  肉詰め?
3. xAuth の許可を得るのにどれだけ時間が掛かるのか?
  私のこの件の返事を貰うのに1日もしくは2日掛かっている。
  私のアプリケーションの使用者も待たされるだろうか?

私は以下の問題を解決し得る一番の解決や方法を探している。

1. 全てのユーザが即座に私のアプリケーションを使う事が出来る。
2. ソースコードは完全にオープンソースである。
3. 簡単に使える。ブラウザは使わない。PINコードをコピペしない。

何かアイデアはありますか?

UIを作りました。おそらくUNIXでコンパイル出来ます。
スクリーンショットはこちら:
  http://mattn.tumblr.com/post/1090305624/gtktweeter-on-win32-oauth

現在、私はキーを含まずにリポジトリへソースをプッシュしました。

ありがとうありがとう
問題視してくれたのか、1日以内に返事来た。

Twitter Support:

Hi Yasuhiro,
To answer your first two questions, if your application keys are public, your application may be compromised and have unintended API calls executed on its behalf. With xAuth, this also means that a compromised application can solicit usernames and passwords and take actions on their behalf that they may not intend. One of our API engineers Raffi Krikorian recently wrote about this, and to quote from his post:

Distributing an application with secrets built into it is equivalent to distributing the secrets themselves. I don't believe that there yet exists a viable platform to store secrets in widely distributed software in such a way that they cannot be eventually extracted.
...
This client identifier can never be the sole security mechanism on a platform. Instead, it is only one part of a puzzle used to maintain security on the network. What this does not mean, is that Twitter will allow applications to distribute their keys in the open. Instead, what the Platform team is trying to create is an ecosystem where getting a new key (in Twitter's case from dev.twitter.com) is significantly easier than re-using a key from another application.

You may read the rest at http://mehack.com/oauth-and-the-twitter-api .

As for your particular application, if you offer a compiled binary with its consumer key and secret made as inaccessible as possible, this should satisfy your first and third qualifications. I have granted your application, client ID 80630, xAuth access. Note that if its keys are compromised, they may be reset and your application's xAuth access may be expired for security reasons. Let me know if you have any other questions.

Thanks


こんにちわヤスヒーロ
最初の2つの質問について...もしアプリケーションキーを公開する場合、貴方のアプ リケーションが侵害される可能性があり、意図しないAPI呼び出しを肩代わりする事になります。 xAuth では、この侵害されたアプリケーションがユーザ名とパスワードを求め、意図しないであろう肩代わりのアクションを実行する事も出来てしまうのです。
我々の API エンジニアの一人である、Raffi Krikorian は最近これについて記しており、彼の記事から引用すると:

広く知られた配布ソフトウェアの中において、非公開情報が結果として抽出されない という手法で、それを格納出来る実用的なプラットフォームが存在するだなんて未だ に信じる事が出来ない。
...
このクライアント識別子は、プラットホーム上の唯一のセキュリティー対策にはなり得ません。 それどころか、ネットワークでセキュリティを維持するのに使用されるパズルの一部にすぎません。 これが意図していないのは、各々のキーをオープンに配布するアプリケーションをTwitterは許す事になるであろう、という事です。 代わりに、Platformチームが作成しようとしているのは、他のアプリケーションからキーを再利用するよりも、極めて簡単に新しいキー(Twitterの場合dev.twitter.comから)を入手する為の「エコシステム」です。

この残りはここで読む事が出来ます: http://mehack.com/oauth-and-the-twitter-api

貴方特定のアプリケーションとして、出来るだけアクセスし難い形にした consumer key と consumer secret を含んだ、コンパイル済みバイナリを計画しているのであれば、まず貴方自信と、第三の資格者を満足させる事が出来るでしょう。
我々は貴方のアプリケーションに xAuth アクセスの許可を与えました。クライアントIDは 80630 です。 キーが侵害され、キーをリセットした場合、セキュリティを理由に貴方のアプリケーションの xAuth アクセスは停止させられるでしょう。
何か他の質問があれば、教えて下さい。

ありがとうありがとう
んー...。要するにユーザIDとパスワードによる認証方式とは別に、いくらでも吐き捨て可能な認証ID公布方式を取りたいんだと。まぁ確かにそれならパスワードという、下手すりゃパンツの中身を見られるよりもダメージの大きい物を曝け出されるよりは、幾分ダメージが小さくなるのかもしれない。
ただしその為には、アプリケーションに付与される権限によってパスワードという秘密の園に到達出来ない仕組みが必要であり、かつ申請方式等といったとてもバカげた物を廃止する必要があり、全てオートメーションにかつMachine Readableに遂行出来る様にもすべきだと思う。
さらには既にあるアプリケーション、例えば私の「gtktweeter」についてのページがあり、そこからボタン一発(例えばforkボタン?)で入力情報がコピーされ新たな consumer key と consumer secret が付与されている...という位の自動化が成されない限りは、Twitterの目論見は失敗へと変わるだろう。

あと、cheebowさんからのコメント
cheebow cheebow

「連投しオフィシャルからbanさせるなんて事も可能です。」ってあるけど、この場合banされるのはこのクライアントを使った「ユーザ」だよね? http://mattn.kaoriya.net/web/twitter/20100908165946.htm #Tw

http://twitter.com/cheebow/statuses/23966546230
上のTwitterの回答を見ると、どうやらbanされるのはアプリケーションの様です。実際どの様になるかは分かりませんが。

なお、gtktweeterについてはブラウザを起動してPINを入力させるという、極めてウンコな実装としてgithubにpushしておいた。ソースコードの CONSUMER_KEY と CONSUMER_SECRET を書き換えてコンパイルして使って下さい。えっメンドクサイ?だってTwitterがそうしろと言ったんだもん。

ところでTwitterさん、最後の質問「xAuth の許可を得るのにどれだけ時間が掛かるのか?」はどうなった?
Posted at by