さて、OAuth で一番わかり難い署名の生成についてまとめます。ここでは HMAC-SHA1 だけ扱うことにします。
キーの生成
HMAC で使うキーを作る必要があります。当然ですね。キーはパラメータエンコードされたコンシューマシークレットとトークンシークレットを "&" で繋げるだけです。
注意点としては、トークンシークレットは存在しない場合があることです。落ち着いてトークンシークレットを空文字列として扱ってあげましょう。
var HMAC_KEY = UrlEncode("CONSUMER_SECRET") + "&" + UrlEncode("TOKEN_SECRET");
まあ、結局はこれだけです。そして作ったキーはバイト列にして HMACSHA1 クラスの Key プロパティに指定してあげます。
var hmac = new HMACSHA1();
hmac.Key = Encoding.ASCII.GetBytes(HMAC_KEY);
これでキーの準備は完了です。次は HMACSHA1 クラスに食わせる文字列を作ります。
署名を作成する元を用意
材料は oauth_ から始まる oauth_signature 以外のパラメータと追加のパラメータです。追加のパラメータってのは GET の時は URL に付けるクエリ文字列、POST で application/x-www-form-urlencoded の時はメッセージボディのパラメータのことです。
それらを全て繋げて署名を作成します。その繋げ方は以下になります。
- パラメータ名でソートする
- 同じパラメータ名が存在するときには値でさらにソート
- パラメータ名、値をパラメータエンコードで変換し、"&" で繋げる
- HTTP メソッド名(大文字)、リクエスト URL(小文字)、1 つ前で繋げたパラメータ の順番でパラメータエンコードの後 "&" で繋げる
わかり難いのが、パラメータは 2 回パラメータエンコードされるという点。最初、1 回しかエンコードしていなかったので、署名の検証が通らず困り果てていました。
var signaturebase = "HTTP METHOD" + "&" + UrlEncode("REQUEST URL") + "&" + UrlEncode("PARAMETERS");
上のようなコードを書く必要があります。実際には string.Format とか使ったほうが楽だけど、本質的な部分ではないのでパス。
後はこれを HMACSHA1 に食わせて、生成されたハッシュのバイト列を Base64 で変換してやれば完成です。