GUIDをちゃんと作る

COMコンポーネントを作るうえで避けられないGUID作成について。
(今回僕がGUID作成したいのは、COMコンポーネント用ではないんだけどね)


よくあるGUID作成説明では、

import pythoncom
print pythoncom.CreateGuid()

という風にGUIDを作っていますが、これ、全くのランダムのようです。
本当に全くのランダムだったらいいのですが、
乱数のロジックも分からないし、正直ユニーク性がどこまで担保されているのか分からない。


今回僕が使う用途では、MACアドレスが入っていて欲しいなと思う。
今日日みんなMACアドレスは取れるだろうし、
取れない環境はまあランダムでもあきらめがつく。
詐称も、僕が今回使いたい用途では問題がない。


C:\Python25\Lib\site-packages\pythoncom.py
を開いて、どんな実装をしているのかを見ようと思った。

# Magic utility that "redirects" to pythoncomxx.dll
import pywintypes
pywintypes.__import_pywin32_system_module__("pythoncom", globals())

超シンプル!


DLLが呼び出しているWin32APIをOllyDbg v1.10なんかで
解析しようとも一瞬思ったが、
自分が求めているものと違うと予想される実装を追ってもしょうがない。


というわけで、実装が落ちてないか検索して調べることに。


まず、こいつはアウト。単なるランダム。

ちなみにPythonのrandom.random()はMTを使っている。
seedはos.urandom()を使うようになっているので結構信頼できるのだが、
seedを元にMTをまわしているので乱数の精度が53bitに落ちていると思われる。
というわけで、ランダムな中でも質が悪い。


次に、タイムスタンプとIPアドレスの会わせ技。

う〜ん微妙。いろんな環境でGUIDを作成することを想定しているので、
192.168.1.2とかがIPアドレスに入るとかぶる可能性が結構出てきそうだ。


と、あきらめ気分で検索を続けていたら、
pythoncom.CreateGuid()がどういう実装なのかが書いてあった。

やはりランダムな値を返しているらしい。
そして、ctypesを使ってUuidCreateSequentialを呼び出すサンプルも付属しているじゃないか!!!


そのサンプルを元に、さらにいろんなUUID生成方法をまとめたモジュールが以下にあります。

みんなこれを使うといいよ。


そして、FreeBSDにもuuidgenっていうC関数があるのね。知らんかった。

[追記]
UuidCreateSequentialでためしに検索したら以下の文書がヒット。


う〜ん、プライバシー問題か…ややこしいな。
Wordにマシン固有の情報が入っているって話題は聞いたことがあったけど、
その中身はGUIDだったのね。トホホ。


やりたいことは、ユーザ登録をせずに(メールアドレスなどを手に入れずに)
端末&ユーザをなるべく分離したいということなので、
GUIDはとてもいいんだけどな…
携帯の端末固有番号+タイムスタンプみたいなイメージで使いたいのです。


うるさい人もいるだろうから、UuidCreateSequentialとCoCreateGuidのどちらを使うか
選べるようにしておこう。こうすりゃ文句あるめぇ。
CoCreateGuidは128ビットフル精度でユニーク性の高い乱数を元に作られると信じて。