3
3

More than 3 years have passed since last update.

Re: 10秒で衝突するUUIDの作り方

Last updated at Posted at 2019-11-27

元ネタは下記リンクを参照。
「UUID生成はライブラリを使え 自分で書くな」との結論は全く同意。

10秒で衝突するUUIDの作り方 - Speaker Deck
https://speakerdeck.com/tanakahisateru/10miao-dechong-tu-suruuuidfalsezuo-rifang

セキュアコーディング

 元ネタ前半の実装のように、アプリケーション開発者が乱数シードを指定して乱数を生成するような実装だと、第三者がシードの値を推測して「次に生成されるUUIDを予測する」ことができるかもしれない。(下記リンクはJavaにおける類例の解説である。)

MSC02-J. 高品質の乱数を生成する
https://www.jpcert.or.jp/java-rules/msc02-j.html

また、生成される可能性のあるUUIDの種類が少ない場合、第三者が総当たりで「どれでもいいので既存のUUIDのどれかに衝突させる」ことができるかもしれない。

 例えばセッションIDを第三者が上述のような方法で推測または意図的に衝突させると、セッションハイジャック攻撃が可能になる場合がある。セッションIDは推測困難な方法で生成するべきである。

OWASP CheatSheet - Session ID Generation and Verification: Permissive and Strict Session Management
https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#session-id-generation-and-verification-permissive-and-strict-session-management

The session tokens should be handled by the web server if possible or generated via a cryptographically secure random number generator.

 では、どんな乱数生成はセキュアな必要があり、どんな乱数生成はセキュアでなくてよいか? 「生成された乱数を他人が知った場合、何にアクセスしてどのような操作ができるようになるか」によって決まる。 個人情報を含むWebアプリケーションのセッションID生成はセキュアな必要がある。Windowsアプリのソリティアで初期配置を決める乱数の生成はセキュアでなくてもよいように思う。

暗号学的に安全な実装の例

いずれも PHP7

hex

php - Generating cryptographically secure tokens - Stack Overflow
https://stackoverflow.com/questions/18830839/generating-cryptographically-secure-tokens

$token = bin2hex(random_bytes(16));

英数

PHP random string generator - Stack Overflow
https://stackoverflow.com/questions/4356289/php-random-string-generator/31107425#31107425

英数記号

上記リンクの英数ランダム文字列生成を改変、高速化

<?php


function random_str(
    int $length = 20
): string {
    if ($length < 1) {
        throw new \BadMethodCallException('Length must be a positive integer');
    }
    // $keyspace length should be (1<<6) = 64
    $keyspace = '-_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    $randomStr = [];
    while (true) {
        $randomInt = random_int(0, 1 << (10 * 6));
        for ($i = 10; $i > 0 ; $i--) {
            $randomStr []= $keyspace[$randomInt % 64];
            if (count($randomStr) >= $length) {
                break 2;
            }
            $randomInt = intdiv($randomInt, 64);
        }
    }
    return implode('', $randomStr);
}

Hope this helps.

3
3
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
3
3