web-dev-qa-db-ja.com

pythonでパスワードを生成

Pythonで英数字のパスワードを生成したいと思います。考えられる方法は次のとおりです。

_import string
from random import sample, choice
chars = string.letters + string.digits
length = 8
''.join(sample(chars,length)) # way 1
''.join([choice(chars) for i in range(length)]) # way 2
_

しかし、私は両方が好きではありません:

  • way 1一意の文字のみが選択され、長さ> len(chars)のパスワードを生成できません
  • 方法2未使用のi変数があり、それを回避する良い方法が見つかりません

だから、他の良いオプションはありますか?

追伸そのため、ここではtimeitを使用した100000回の反復テストを行っています。

_''.join(sample(chars,length)) # way 1; 2.5 seconds
''.join([choice(chars) for i in range(length)]) # way 2; 1.8 seconds (optimizer helps?)
''.join(choice(chars) for _ in range(length)) # way 3; 1.8 seconds
''.join(choice(chars) for _ in xrange(length)) # way 4; 1.73 seconds
''.join(map(lambda x: random.choice(chars), range(length))) # way 5; 2.27 seconds
_

したがって、勝者は''.join(choice(chars) for _ in xrange(length))です。

44
HardQuestions

Python 3.6以降

secretsモジュール を使用して、暗号的に安全なパスワードを生成する必要があります。これは、Python 3.6。ドキュメントからの適応:

import secrets
import string
alphabet = string.ascii_letters + string.digits
password = ''.join(secrets.choice(alphabet) for i in range(20)) # for a 20-character password
83
gerrit

暗号PRNGの人々のために:

def generate_temp_password(length):
    if not isinstance(length, int) or length < 8:
        raise ValueError("temp password must have positive length")

    chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
    from os import urandom
    return "".join(chars[ord(c) % len(chars)] for c in urandom(length))

均等な分布では、chars文字列の長さは128の整数の除数である必要があります。そうでない場合は、スペースから均一に選択する別の方法が必要になります。

33
Ben Mosher

[〜#〜] warning [〜#〜]重大なセキュリティ問題のため、この回答は無視する必要があります!

オプション#2は、いくつかの改善点を追加できることを除いて、かなり合理的です。

''.join(choice(chars) for _ in range(length))          # in py2k use xrange

_は従来の「そこに何があるかは気にしない」変数です。そこにリストを理解する必要はありません。ジェネレーター式はstr.join。また、それが唯一のcorrect方法である場合、「遅い」が何を意味するかも明確ではありません。

13
SilentGhost

これでうまくいくと思います。 random.SystemRandomは、os.urandomと同じ基になる暗号ランダム関数を使用しますが、おなじみのrandomインターフェイスを使用します。この関数は、Benの答えのように、奇妙な128バイトの対象にはなりません。

import random
import string

def gen_random_string(char_set, length):
    if not hasattr(gen_random_string, "rng"):
        gen_random_string.rng = random.SystemRandom() # Create a static variable
    return ''.join([ gen_random_string.rng.choice(char_set) for _ in xrange(length) ])

password_charset = string.ascii_letters + string.digits
gen_random_string(password_charset, 32)
5
Tim Ludwinski

python <3.6:

import os, math, string, struct

def generate_password(pass_len):
    symbols = string.printable.strip()
    return ''.join([symbols[x * len(symbols) / 256] for x in struct.unpack('%dB' % (pass_len,), os.urandom(pass_len))])

これには、Ben Mosherのソリューションに勝る利点があります。これは、シンボルからの各シンボルの発生が均等に変化するのに対し、モジュラスを使用すると、アルパベットの最初のシンボルがわずかに優先されるためです。この提案では、記号のアルファベットも大きくなっています。

4
gardarh