nptclのブログ

Common Lisp処理系nptの開発メモです。https://github.com/nptcl/npt

C言語でMD5を取得する

1. はじめに

以前、C言語でxorshiftの乱数を使う投稿をしましたが、 その中で乱数の初期値を決めるためだけに MD5を使っていたと話しました。

一応そのファイルの使い方も紹介します。
せっかく作ったんですし、 書いておかないと自分が忘れますので。

でも、C言語MD5を使うソースなど星の数も無いかもしれませんが、 もっと信頼性の高いものがたくさんあると思いますので、 そちらを使った方がよろしいかと思います。
なんかいつも「他の使えよ」って言ってる気がする。

ファイルはここです。

https://github.com/nptcl/hypd/tree/main/develop/random

  • md5encode.c
  • md5encode.h

2. ドキュメント

MD5アルゴリズムは、RFCのやつを見ました。
それしか見てません。

[RFC1321] The MD5 Message-Digest Algorithm

https://www.ietf.org/rfc/rfc1321.txt

なお、上記RFCにはC言語のソースが載ってます。
でもそれを使ってません。
ソースは一切見てません。
ライセンスの都合上、見るわけにはいかなかったのです。
全部自作と言い張ります。

3. 使い方

先に細かい制限を言っておきますが、 入力は全てバイト単位であり、 ビット単位では無理です。

どうもMD5ってビット単位でも受け付けるようです。
私の配布したソースでは無理。

まず文字列を入力としてみましょう。

uint8_t x[MD5ENCODE_SIZE];

string_md5encode("Hello md5encode", x);

これで、配列xMD5の値が入ります。 ちなみにMD5ENCODE_SIZE16です。

値を見てみましょう。

int i;

for (i = 0; i < MD5ENCODE_SIZE; i++)
    printf("%02x", x[i]);
printf("\n");

結果は下記の通り。

182acd2b34ce893801875f2c201d7547

本当にあっているか確認したいので、 FreeBSDmd5コマンドを実行してみます。

$ echo -n "Hello md5encode" | md5
182acd2b34ce893801875f2c201d7547

うん、いいですね。

文字列じゃなくて、 好きなバイトの列を入力に入れたいなら次の通り。

uint8_t x[MD5ENCODE_SIZE];
void *ptr;

ptr = (void *)"Hello md5encode";
sequence_md5encode(ptr, 15, x);

結果は文字列のときと同じですが、 上記の場合は入力の長さを指定できるので、 バッファの値が文字列の終端を表す0であっても大丈夫です。

今まで使った関数

  • string_md5encode
  • sequence_md5encode

この2つは、入力に単一のバッファのみを受け付けるものでした。
でもストリーム相手にMD5を取得したいときなんかでは使いづらいです。

そうではなく、何度も入力を受け付けて、 最終的に値を返却したい場合は次のようにします。

struct md5encode md5;

clear_md5encode(&md5);

これで準備ができました。
構造体のmd5を使い、 複数の入力を行いましょう。

read_md5encode(&md5, "Hello", 5);
read_md5encode(&md5, " ", 1);
read_md5encode(&md5, "md5encode", 9);

上記の例は文字列を指定していますが、 ポインタなら何でもいいです。

それでは結果を出してみます。

uint8_t x[MD5ENCODE_SIZE];

calc_md5encode(&md5, x);

これで、配列xMD5の値が格納されました。
注意点として、もう一度calc_md5encodeを実行しようとすると、 プロセスごとabort()しますので注意。
考えてみればそこまですることはなかった。

使い方は以上です。

このコードは、何の目的もなく、なんとなく作った記憶があります。
それが今じゃxorshift専用だぜ!