Pythonで疑似乱数生成というとrandomモジュールが浮かびます。これは一様分布や正規分布など、種々の分布に従った乱数を生成することができ便利なのですが、実はセキュリティ的には強い乱数ではないようです。
パスワードやセキュリティトークンを生成するときには、暗号学的に強い乱数を生成できるsecretsモジュールを使うことが推奨されています。
乱数生成方法の違い
secretsモジュールの解説には以下のように書かれていました。
secretsモジュールは OS が提供する最も安全な乱雑性のソースへのアクセスを提供します。
この記述について、具体的には、os.urandom
とrandom.SystemRandom
をインタフェースにしてOSの安全なランダムソース、Linuxでは/dev/urandom
、 WindowsではCryptGenRandom()
にアクセスされる仕様のようです。(PEP506)
Linuxの/dev/random
や/dev/urandom
はハードウェアの環境ノイズを使った乱数(エントロピープール)となり、高品質な乱数ができることで知られています。
一方のrandomモジュールは、メルセンヌ・ツイスタという疑似乱数生成器を使っています。これは線形漸化式を使った優れた疑似乱数生成法なのですが、暗号論的疑似乱数列生成器(CSPRNG)ではなく、予測可能な生成方法となっています。
この乱数生成方法の違いから、パスワードやセキュリティトークンを生成する乱数モジュールはsecretsを使うべきだということのようです。
個人的に全然知らなかったので、備忘録として記事にしました。