LoginSignup
5
4

More than 5 years have passed since last update.

Django 1.4.2 の セッションキーの生成

Posted at

ふと unique な key を作るのに django はどうしてるんだろうと思って隣の人と一緒に調べた。

セッションIDの作り方 - スコトプリゴニエフスク通信

手元の 1.4.2 だと OS の pid を取ってるコードは見当たらなかった。

django.contrib.sessions.base.SessionBase に _get_new_session_key() てメソッドが生えてるんだけど、その中では django.utils.crypto にある get_random_string() が使われてて多分それがキー生成してる関数。

crypto.py
def get_random_string(length=12,
                      allowed_chars='abcdefghijklmnopqrstuvwxyz'
                                    'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
    """
    Returns a securely generated random string.

    The default length of 12 with the a-z, A-Z, 0-9 character set returns
    a 71-bit value. log_2((26+26+10)^12) =~ 71 bits
    """
    if not using_sysrandom:
        # This is ugly, and a hack, but it makes things better than
        # the alternative of predictability. This re-seeds the PRNG
        # using a value that is hard for an attacker to predict, every
        # time a random string is required. This may change the
        # properties of the chosen random sequence slightly, but this
        # is better than absolute predictability.
        random.seed(
            hashlib.sha256(
        "%s%s%s" % (
                    random.getstate(),
                    time.time(),
                    settings.SECRET_KEY)
                ).digest())
    return ''.join([random.choice(allowed_chars) for i in range(length)])

useng_sysramdom が False の時は
random.getstate() と time.time() と settings.SECRET_KEY を SHA256 にかけた値を種にしてるね。

using_sysramdom フラグは crypto.py の中で random.SysRandom が使用可能かどうかを判断してセットされてる。
ここは上の blog の内容と同じ。

crypto.py
import random
try:
    random = random.SystemRandom()
    using_sysrandom = True
except NotImplementedError:
    import warnings
    warnings.warn('A secure pseudo-random number generator is not available '
                  'on your system. Falling back to Mersenne Twister.')
    using_sysrandom = False

これは、最終的には ramdom な値なので、 unique なキーとしてはどうなのかなぁ、という疑問が少し残ってるけど、まぁこんなもんかなぁ。

ちなみに自分が昔 unique な値作ろうとしてやった時は Catalyst::Plugin::Session (perl) のを拝借してた。

Session.pm
my $counter;

sub session_hash_seed {
    my $c = shift;

    return join( "", ++$counter, time, rand, $$, {}, overload::StrVal($c), );
}

# ~~ snip ~~

sub generate_session_id {
    my $c = shift;

    my $digest = $c->_find_digest();
    $digest->add( $c->session_hash_seed() );
    return $digest->hexdigest;
}

最後に ramdom かけてないので、こっちのほうが一意な気はするんだけどわからん。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4