2011年05月11日

お遊び: gzip ファイルのハッシュ値を選ぶ

以前、お遊び: tar ball のハッシュ値を選ぶでファイルを作成した時刻により md5sum の値が変化するというのを紹介しましたが、調査の結果、 gzip ファイルのヘッダ部分に埋め込まれている MTIME 部分が変化していることが原因であることが判明しました。

ということで、この MTIME 部分の値を書き換えれば、好きな md5sum 値を簡単に取得できるわけです。
TOMOYO Linux の tarball は、「配布用かテスト用か」および「最後までダウンロードされたかどうか」を簡単に見分けられるようにするために、以下のようなプログラムを用いて md5sum 値の先頭4桁が同じになるように選んでいます。(熊猫が作成した tarball かどうかの確認には、ファイル名の末尾に .asc を付与したファイルもダウンロードして、 gpg で確認してください。)

/* gcc this_file.c -lssl */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <openssl/md5.h>

static void mkfile(const char *dir, const char *cmdline, const char *outfile)
{
	unsigned char *buf = NULL;
	unsigned long buflen = 0;
	time_t *mtime;
	FILE *fp;
	if (chdir(dir)) {
		fprintf(stderr, "Can't change directory.\n");
		return;
	}
	fp = popen(cmdline, "r");
	if (!fp) {
		fprintf(stderr, "Can't read gzipped data.\n");
		return;
	}
	while (1) {
		int len;
		buf = realloc(buf, buflen + 1048576);
		if (!buf) {
			fprintf(stderr, "Can't allocate memory.\n");
			pclose(fp);
			return;
		}
		len = fread(buf + buflen, 1, 1048576, fp);
		if (len == 0)
			break;
		buflen += len;
	}
	pclose(fp);
	if (buflen < 8 || buf[0] != 0x1f || buf[1] != 0x8b) {
		fprintf(stderr, "Invalid gzipped data.\n");
		return;
	}
	fp = fopen(outfile, "w");
	if (!fp) {
		fprintf(stderr, "Invalid gzipped data.\n");
		return;
	}
	mtime = (time_t *) (buf + 4);
	while (1) {
		const unsigned char *md5 = MD5(buf, buflen, NULL);
		unsigned char c[4] = { md5[0] >> 4, md5[0] & 0xF,
				       md5[1] >> 4, md5[1] & 0xF };
		printf("%02x%02x%02x%02x%02x%02x%02x%02x"
		       "%02x%02x%02x%02x%02x%02x%02x%02x\n",
		       md5[0], md5[1], md5[2], md5[3],	md5[4], md5[5],
		       md5[6], md5[7], md5[8], md5[9], md5[10], md5[11],
		       md5[12], md5[13], md5[14], md5[15]);
		if (c[0] == c[1] && c[1] == c[2] && c[2] == c[3])
			break;
		(*mtime)++;
	}
	if (fwrite(buf, 1, buflen, fp) != buflen || fclose(fp)) {
		fprintf(stderr, "Can't write.\n");
		unlink(outfile);
	}
}

int main(int argc, char *argv[]) {
	mkfile("ソースのディレクトリ", "tar -zcf - --exclude .svn -- *", "出力ファイル");
	return 0;
}

先頭8桁が同じになるまでループさせるとか言って電力を浪費するの禁止!

posted by 熊猫さくら at 21:00| Comment(0) | TrackBack(0) | Linux
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/45097681
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック