2010年05月15日

OAuth への道―― HMAC-SHA1, Base64, URL Encode

-------------------- HMAC-SHA1 + Base64 でシグネチャーを作る -------------------------

さて、以前にも書いたとおり、この周辺の処理は理解できませんでした……で、ソースを
入手しました。

http://www.koders.com/c/fid645718469E4742143926FA6138FC7FD33BBD3A4F.aspx から入手しました。
使用したのは、base64.h base64.c hmac.h hmac_sh1.c memxor.h memxor.c sha1.h sha1.c です。


Windows の処理系で、かつ、C++で動かそうとすると、いくつかの変更が必要になります。
まず、

・各ソースに含まれている #inlcude は削除します。
 これは、unix 環境でファイルの依存関係などを記述するファイルらしいです。
 が、そもそも、config.h が入手できなかったのと、実際には、なくてもコンパイルできるので、これはあっさりと削除します。

・いくつかのソースにある、restrict を削除します。
 これは、C99 で定義された予約語で、関数の引数として渡された領域が「重なっていない」とコンパイラに仮定させるものです。
 標準の C++ では、まだ定義されてないので、これまた、あっさりと削除します。

さて、実際に、HMAC-SHA1 および、BASE64 でシグネチャーを作成します。

以上のファイルがそれぞれコンパイルできる状態で、

void makeSign(const char *inBuff, char *key, char *outBuff)
{
int inLen = std::strlen(inBuff);
int keyLen = std::strlen(key);
char resBuff[1024];

hmac_sha1 (key, keyLen, inBuff, inLen, resBuff);
base64_encode (resBuff, 20, outBuff, 64);
}

これで、inBuff から始まる文字列を、key という文字列で、ダイジェストし、Base64 で変換したものを、outBuff 以降に保持します。

ただし、実際に使用する際には、もう一段、URL Encode が必要です。

-------------------- URL Encode -----------------------------

URL Encode はそんなに難しい処理ではないので、自力で作りました。
もともと、inBuff と URL Encode して、outBuff にセットするというものです。
3番目の引数の、delChar は、別の用途に使い回したくて、つけています。
これは、URL Encode が必要な文字に対して、%xx とエンコードするのではなくて、「削除」します。
たとえば、

abc+def=ghi

を普通にエンコードすると
abc%26def%3Dghi

ですが、delChar = true; にして呼び出すと、
abcdefghi
とエンコードすべき部分を削除します。

これは、oauth_nonce に使い回すためです。
oauth_nonce は、「POSTごとにランダムな文字列」が要求されますが、ランダムな「文字列」を簡単に作るには、せっかくある、HMAC-SHA1 を使うのが早いと、そういう発想です。
実際には、
Base Strign = "2010/05/15-15:00:00" と時刻から生成し。
key = "1000000" → "1000001" → "1000002" と、POST ごとに+1した数値(を文字列にしたもの)
を使って、oauth_nonceを生成しています。
ただ、この中に、エンコードできる文字が入ってしまうと、ちょっと面倒なので、なら、エンコードできる文字は「削除」という発想でした。


void URLEnc(const char *inBuff, char *outBuff, bool delChar)
{
char *nonEscape = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";

std::string line = "";
while(*inBuff)
{
char c;
char lBuff[16];
std::string orgLine = "";

c = *inBuff++;

if (std::strchr(nonEscape, c))
{
lBuff[0] = c;
lBuff[1] = '\0';
}
else if (! delChar)
std::sprintf(lBuff, "%%%02X", c);
else
lBuff[0] = '\0';

line += lBuff;
}

std::sprintf(outBuff, "%s", line.c_str());

}


こんな感じで、HMAC-SHA1 → BASE64 → URL エンコード と処理を進めることができました。
posted by 麻野なぎ at 15:27| Comment(0) | TrackBack(0) | Twitter と Bot の周辺
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/38106065

この記事へのトラックバック