さて、以前にも書いたとおり、この周辺の処理は理解できませんでした……で、ソースを
入手しました。
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 エンコード と処理を進めることができました。