Entry

プログラミングメモ - 「SHA256 の出力を64進数にする」の補足

2007年02月12日

ひとつ前のエントリで,後になったら自分でも何やってるのか分かんなくなってるかも,と思ったので,少し補足しておきます。SHA の作り方は SHA(3) を参照してもらうことにして,本題は16進を64進にするところです。

64進数は Base64 の作り方を見ても分かるように,12ビットで2つの文字を作ります。12ビットで2つの文字ですから,6ビットを使って文字を表現するわけですね。「12ビット」なる数字がどこから出てきたのかというと,これは,64 == 2^6(64進表現)の6ビットと,16 == 2^4(16進表現)の4ビットの,最小公倍数です。

簡単に表すとこんな感じ。12ビットを4ビットずつ区切れば16進で表現できるし,6ビットずつ区切れば64進数で表現できるというわけです。

16進数: 1111 1111 1111 (4ビット x 3文字)
64進数: 111111  111111 (6ビット x 2文字)

こうすれば,「表現の上では」3文字を2文字に縮めることができますよね。これは Base64 の基本的な発想なので,取り立ててあたしが考えついたことじゃありません。

具体的な処理としては「16進数の文字を3文字取ってきて,64進数の文字2文字に変換する」という作業が基本になります。ソースではこんなことやってます。

        lbuf = strtol(buf, NULL, 16);
        mod = ((lbuf & 0xFC0) >> 6) % 64;
        ret[i] = charIndex[mod];
        i++;
        mod = (lbuf & 0x03F) % 64;
        ret[i] = charIndex[mod];

この中で 0xFC0 とか 0x03F とかいったマスクが謎だと思うんですけれど,これは,それぞれ2進数表現で「111111000000」と「000000111111」を表します。これでお分かりの通り,最初のマスクでは,12ビットの数値のうち上6ケタを取り出して,6ケタ分右にシフトしているわけです。これで,6ビットの値を手に入れることができます。下6ケタについては,マスクするだけで目的の数値を取れます。

次に取り出した数値から文字を作ります。これは普通の基数変換と同じで,基数で割ったときの余りを取ればいいのでした。けれど,ここで取り出した数値は全て64以上にはならないので(6ビットの数値だから),余りを取る必要はありませんよね。そういうわけで,64で割ったときの余りを取るところは不要だったのでした……なんで割っちゃったんだろ,トホホ(割っても問題はないんだけど)。

最後に,ほんの少しテクニカルなところと言えば,目的の文字をインデックスを使って探すところです。余りを添字にして,インデックスを検索すれば,一発で目的の文字を見付けることができます。インデックスはこんな感じ。

    const char charIndex[] = "0123456789"
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "-_";

これもあたしが考えたことじゃなくて,誰かがどこかのソースでやってたことのパクリです(どこかで見たんだけれど,忘れちゃった)。

やってること自体は大したことないのに,レビューしたらまた要らんところが見付かってしまいました。なんだかなぁ。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN