ゴールデンウィーク中はバイトで体がやばいことになっていました。
まあ、ずっと立ち続けで作業を行うものであるのと、普段がデスクワーク専門なのでひどくなるのも当然だったりします。
デスクワークばかりではおもしろくないのもありまして、肉体労働はいい刺激になるのがいいところです。長期間はやりたくないですが。
それは置いておきまして、何を思ったかHMACを実装してみました。
ある意味ハッシュ処理の仲間のように扱える
正しくはハッシュ処理ではないのですが、その性質上「秘密鍵付きのハッシュ処理」として実装が出来るのがありがたいです。
なので、以前に実装したハッシュインターフェイスを継承する形で実装できるのが簡単です。
問題はどうやって付属させるハッシュ処理を組み込むか、です。
一応ハッシュ処理をコンストラクタで与える物とテンプレートでハッシュ処理を指定して組み込む物を両方持てば使いやすいだろうと言うことで実装しています。
ハッシュの秘密鍵の作成に対象ハッシュアルゴリズムのブロック長が必要とは・・・
初めに組んだときにはWikipediaの説明だけから組んでみたのですが、phpのサンプルやらとは結果がかなり違っているので訳がわからなくなり
結局仕様書であるRFC2104を見ることに。見てみるとびっくりした構文が。
・・・
認証鍵 K は、最大そのハッシュ関数のブロック長 B までその長さを取ることができる。B バイトより長い鍵を使用するアプリケーションは、最初に H で鍵をハッシュし、その結果生じる L バイトの文字列を HMAC への実際の鍵として使用する。
・・・
HMAC において使用される鍵は、どのような長さのものでもよい(B バイトより長い鍵は最初に H でハッシュされる)。しかし L バイトより短いものは、その関数のセキュリティ強度が減少するため使用してはならない。L バイトより長い鍵も受け入れられるが、その余分の長さは、あまり関数の強度を増さないだろう。(その鍵の乱数的性質が弱いとみなされる場合には、より長い鍵が勧められるかもしれない。)
つまり、HMACを計算するときには対象のハッシュアルゴリズムのブロック長が取得できないと計算できない、という事実が判明。
ここで言うブロック長とは、
対象のハッシュ関数が一回のハッシュ計算で参照するデータ長
という意味です。
追加で説明するなら、たとえばMD5の場合はデータが64byte(正しくは64octet)そろった時点でハッシュ計算を行い、次に計算を行うのは64byteそろってから、という順序をとります。
そのため、MD5の場合はこのブロック長が64byte(64octet)である、ということになります。
RFC2104にも説明されていますが、今のハッシュ関数でよく使用されているMD5(HMAC-MD5)、SHA1(HMAC-SHA1)、RIPEMD160(HMAC-RIPEMD)はこのブロック長が64byteなのでそう説明されている物もあります。
が、ここでSHA-384/512を持ってくると、この二つの場合はブロック長が128byteと定義されている(128byteそろった時点でハッシュ計算が行われる)ので、このBの部分が128byteになります。
これに気がつかずに実装すると大変になるところでした。
ちなみに、はじめにWikipediaを見たときにはパディング長はハッシュ長と同じLだと思い込んでいました。ちゃんと仕様は確認しなさい、というやつですね。
問題の部分がわかれば後は簡単に実装
共通の部分として「秘密鍵からパディングデータを作成する」があるので、それを共通インターフェイスとして再度定義すれば簡単です。
プログラム的にもそれほど難しいことではない(固定メモリを確保しておいてそこからパディングデータを作成すれば良いだけ)です。
実装したからと言って使うか?といわれると厳しいところだったりします。後々パスワード認証か何かで使うかもしれないな~と思い実装しただけですので。