がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

ユニークなID

まぁそもそもとして「一意(ユニーク)である」と「推測困難である」の間には深くて暗い漆黒の溝が広がっているのですが、って突っ込みを前提に。


PHPで、uniqidってのがありやして。
これは「一意な ID を生成する」関数です。


基本「マイクロ秒」基準で文字列を作るようで。
複数ホスト対応とか何とかのために、第一引数としてprefixとか第二引数としてmore_entropyフラグとかが存在するです。
まぁまぁとっとと実験してみませう。

<?php

var_dump(uniqid());
$i = mt_rand() . '';
var_dump($i);
var_dump(uniqid($i, false));
var_dump(uniqid($i, true));


プレフィックスにmt_randを使ってるのは某書籍からの引用。
結果は、こんな感じ。プログラム名に文句言うの禁止w

[gallu@localhost ~]$ php tt2.php
string(13) "509b45fcb43f8"
string(10) "1633347729"
string(23) "1633347729509b45fcb4bc6"
string(33) "1633347729509b45fcb4bea4.40001624"

[gallu@localhost ~]$ php tt2.php
string(13) "509b45fd6bf37"
string(7) "2589811"
string(20) "2589811509b45fd6c707"
string(30) "2589811509b45fd6c7335.39021620"

[gallu@localhost ~]$ php tt2.php
string(13) "509b45fe3307d"
string(10) "1798714701"
string(23) "1798714701509b45fe33463"
string(33) "1798714701509b45fe334863.47027358"

[gallu@localhost ~]$ php tt2.php
string(13) "509b45fededfd"
string(10) "1825280154"
string(23) "1825280154509b45fedf1e7"
string(33) "1825280154509b45fedf20e2.72647857"

[gallu@localhost ~]$ php tt2.php
string(13) "509b45ff8b1a8"
string(9) "547022440"
string(22) "547022440509b45ff8b58c"
string(32) "547022440509b45ff8b5b09.85851852"

[gallu@localhost ~]$ php tt2.php
string(13) "509b46002f473"
string(10) "1495858126"
string(23) "1495858126509b46002f85a"
string(33) "1495858126509b46002f87d1.02211442"


まぁ確かに一意ではあると思うんで、そのあたりに異論はかけらもないんですがね。
問題は、これを「推測困難」とかいって、セキュリティ系で使おうとする暴挙を時々見かけることです。


http://phpweb.ohel-shem.com/manual/ja/function.uniqid.php

一意な ID またはトークンが必要な場合、そして、ネットワーク経由で ユーザにそのトークンを渡そうとする場合(例えば、セッションクッキー)、 次の例のようにするのが推奨されます。
この例は、極めて予測困難な 32 文字の ID(128 ビット十六進数) を作成します。

uniqidは見てのとおり十分「推測可能」だし、randも暗号学的に安全とは言いがたいし、なにがどこがどのように?って感じだ。


http://d.hatena.ne.jp/kakku22/20081016/1224154493

より安全な(推測されにくい)文字列を得たい場合は,uniqid()で生成されたユニークIDのハッシュ値を取ればよい.

「ハッシュしたら推測しにくい」っていうその論理の飛躍がよくわからない。


http://pentan.info/php/sample/uniq_id.html

これよりほかの乱数エントロピーを組み合わせたほうがより推測困難になります。

ここも一緒。


んと…「推測可能なものと推測可能なもの」を足し算しても、推測困難にはなりませんし。
ハッシュにしても別に推測にはさほどの障害にはならんですだよ。


なんていうかこぉしみじみと「…如何なものか」感が全力で漂ってきます。

ハッシュするんならせめて「ハッシュ空間より広い元データ」を与えてあげないと、ただでさえ限定されてるハッシュ空間がよりいっそう狭くなりますし(解析速度への影響ってより、単純に「空間がもったいない」って考えてまふw)。
っていうかMD5なんて「まだ使ってるんだぁ…へぇ…」ってものをこんだけ見かけるとも思いませんでしたねぇ B-p


おいちゃんは、なんでDIID(difficulty imagining ID)って名前をつけたロジックを愛用してます。
ロジックはこちらをどんぞ。
http://d.hatena.ne.jp/gallu/20120607/p1


ちなみに、実行結果。

<?php

$token = hash('sha512', file_get_contents('/dev/urandom', false, NULL, 0, 128), false);
var_dump($token);

[gallu@localhost ~]$ php tt2.php
string(128) "3a635b477c7fa8ecdeebc06bc93a9e9c6692e1034a16705d922b45215478c0157bfc8dd700610c227b2c2b801f40e849b35231ca92943a755817ea4644c10008"

[gallu@localhost ~]$ php tt2.php
string(128) "f7772546f68157ccf470a36ef9c019ed7c2d56071b4797cabf469edff0afd3134edfe8424fe3bbddb88ab9cc177c9a0e7e088f2f04b5c2d8572d5654d15053b7"

[gallu@localhost ~]$ php tt2.php
string(128) "fa385db8d578ad0bf4acaf5ddf054de968cb715c9caa5040e29276861b58e1d377ceebb30a924c3e7b60a359c0e5d8de1e28690726195831d4ae12a287abd316"

[gallu@localhost ~]$ php tt2.php
string(128) "389c554f469e9ed915cc3a6341b38b276f106448adb8545d7fcd6b22b29ad6ec7ac60c5fd25ba441a0a5ab8d3734fe9c77c5989d33494f9eb406a5122f14d26e"

[gallu@localhost ~]$ php tt2.php
string(128) "64df88c8b82e4838084894a51a25878ca97c73a63acb506722f0e594d4dfa1736cb4c11b34d1a68f2d9688d7e86bba1596c0b742663bf35d628bfe4698cc6e95"

[gallu@localhost ~]$ php tt2.php
string(128) "064fa0f97208268394cd5fff8ac34104986f8289618d994092c1bcf4bfcc3c00aed3d608b545191573c75e1fbd15a350d89e52b99c50ea947da101ffa0c0eb20"


いやまぁ別に推測困難な方法ならなんでもいいとは思うのですが。
あんまり推測困難じゃないものを指して「推測困難」とかいうのもどんなもんかなぁ? とか思うので、ふと。


「一意」と「推測困難」は、ちゃんと区別しましょう!!