セッションIDの作り方

セッションIDを生成する際にもっとも使われているのはMD5SHA-1などで、時間やプロセスIDをハッシュ化する方法でしょうか。実際にRubyCGI::Sessionは、こんな感じです。

def create_new_id
  require 'digest/md5'
  md5 = Digest::MD5::new
  now = Time::now
  md5.update(now.to_s)
  md5.update(String(now.usec))
  md5.update(String(rand(0)))
  md5.update(String($$))
  md5.update('foobar')
  @new_session = true
  md5.hexdigest
end

ただ、MD5SHA-1でも天文学的な確率で(ハックではない偶然)、コリジョンすることを恐れてユニーク性を保証したいという場合もあります。これは、システムでユニークな連番を振ってIDに付け加えればよいでしょう。つまり、

デタラメな値(できるだけユニーク、推測が不可能) + システムユニークID(推測されても仕方なし)

という組合せでセッションIDのユニーク性とハック不可能性を同時に達成することになります。

ところが、世の中にはとほほなものもあります。時間やプロセスID(できるだけユニーク、推測が不可能)を素のまま使い、それに連番(推測されても仕方なし)を付け加えるケースです。

113555965892740005

これでは、推測不可能があやしくなります。こんなセッションIDがあったら、見る人が見ればシステム時間を使っていると推測されるでしょう。時間やプロセスIDを使っては発番されるIDの帯域を自ら狭めていることになります。「できるだけユニーク、推測が不可能」の部分は単に同じ桁数のランダム値を用いたほうが堅牢です。