Entry

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

2007年02月11日

出戻りのエントリです……64進表現で0xFFFを1桁で表示できるなんて,誰が言ったんだ。「あるある」みたいじゃないか。ということで,以下が修正したエントリです(まだ間違いがあるかもな……)。

あるファイルのファイル名を SHA256 のハッシュ値で管理したらどうなるだろう,と,つらつら考えていて,SHA256(1) の出力を見てみました。

aian:~ % sha256 -q foobar
0731a3499241607f2196a082e88fd589fb72aa241de904840d1918add45a99f1

長え……。数えてみたら64桁ありました。もちろん,ファイル名として使えなくはないんですけれど,使われている文字が16種類しか無いので(16進表現),無駄に長いです。長いなら MD5 や SHA1 を使えよって噂もあるのに,なぜ SHA256 なのかというと,桁が長い方がゴツくてカッコイイからです。そう,あたしの趣味。

もっとも,64桁はちょっと長すぎるので,この文字列をもう少しコンパクトにまとめてみることにします。

コンパクトにするには,単純に表現できる文字の種類を増やせばオッケーですよね。16進数は16文字しか使えないから,10進数で15(16進数でF)より上の数は次の桁にあずけなくちゃいけないけれど,例えば,17進数だったら,10進数の16を‘G’と表現できます。この要領で基数を増やせば,文字列をコンパクトにできそうです。

そんなわけで,表現できる文字はどれだけ増やせるのか考えてみます。とりあえず,アルファベットが26文字で,大文字と小文字を区別すれば52文字になります。普通の数字(0-9)を加えれば,62文字です。これで62進数を作ることができます。

ただ,62進数というのも,まあアリっちゃアリなんですけれど,基数として中途半端です。できれば2^nの形にしたいので,あと2文字を加えて‘-' と `_' を加えることにしましょう。これで64進数ができます。64進数と言えば,巷には Base64 があるけれども,これはファイル名と相性の悪い文字(`/')が含まれているし,0 が `A' から始まったりして使いづらいので,採用は見送り。結局,こんな風に作ることにしました。

10進64進
0-90-9
10-35a-z
35-61A-Z
62-
63_

アルファベットは大文字と小文字を区別するので,Windows や MS-DOS では使えませんね。

で,試験的に(というか思い付くままに)ちゃらっと,書いてみる(ちゃらっと書いたら間違えていたので,修正しました)。

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sha256.h>

int
main(int argc, char *argv[])
{
    const char charIndex[] = "0123456789"
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "-_";
    char *strSHA = NULL;
    char buf[3];
    char ret[44];
    char *ptr;
    unsigned long lbuf;
    unsigned long mod;
    int i;
    int j;

    if (argc != 2) {
        fprintf(stderr, "arg error\n");
        exit(0);
    }
    strSHA = SHA256_File(argv[1], NULL);
    if (strSHA == NULL) {
        fprintf(stderr, "file error\n");
        exit(0);
    }
    
    printf("HEX: %s\n", strSHA);
    bzero(buf, 3);
    bzero(ret, 44);
    ptr = strSHA;
    for (i = 0; i < 42; i++) {
        for (j = 0; j < 3; j++) {
            buf[j] = *ptr;
            ptr++;
        }
        lbuf = strtol(buf, NULL, 16);
        mod = ((lbuf & 0xFC0) >> 6) % 64;
        ret[i] = charIndex[mod];
        i++;
        mod = (lbuf & 0x03F) % 64;
        ret[i] = charIndex[mod];
    }
    ret[i] = *ptr;
    printf("B64: %s\n", ret);

    free(strSHA);
    return 0;
}

こんな感じになるのかなぁ……。即値が多いので,あまり参考にはならないかもしれないけれど,一応できたことはできた。strSHA というのが,16進表現のハッシュ文字列で,ret に変換結果が格納されます。lbuf に long を使っているのは,大は小を兼ねるってなことで,適当にアサインしただけです。

64進数にすると0x3Fまでを1桁で表現することができます。つまり,文字列が約2/3になるってことですね。SHA256(3) の出力である64桁を3で割ると21と余りが1なので,出力結果は43桁になります(21 x 2 + 1)。あまり綺麗な桁数じゃないけれど,そこら辺には目をつむることにしましょう。

というわけで,実行してみる(コマンド名を b64 にしています)。

aian:~ % ./b64 .cshrc
HEX: e046ae29f0d5deb39e296ad64866f988c41e1ade9d7fe1117937d7b1b821fd76
B64: U4qKav3lTHeuamHmi6rVycgu6JWtv-4hujvnIrwx_n6

あまり小さくなりませんね……そうでもないか。

あとは,ファイルの管理方法か……ここら辺はもう少し考えてから具体的な話と一緒にエントリにしようと思います。

Trackback
Trackback URL:
[2007年02月12日 01:54] [PC]SHA256を64進数にする from 少女思兼中。
via.qune: プログラミングメモ - SHA256 の出力を64進数にする 面白いけど、UNIXとかのcase sensitiveなファイルシステ... [more]
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