У меня есть генератор паролей:
import random, string
def gen_pass():
foo = random.SystemRandom()
length = 64
chars = string.letters + string.digits
return ''.join(foo.choice(chars) for _ in xrange(length))
В соответствии с документами SystemRandom использует os.urandom, который использует /dev/urandom для выброса случайных биттов. В Linux вы можете получить случайные биты из /dev/urandom или/dev/random, они оба используют любую энтропию, которую может получить ядро. Количество доступной энтропии можно проверить с помощью команды tail/proc/sys/kernel/random/entropy_avail, это вернет число, подобное: 129. Чем выше число энтропии, тем доступнее. Разница между /dev/urandom и/dev/random заключается в том, что /dev/random будет выплевывать только биты, если entropy_avail достаточно высок (например, как минимум 60), а /dev/urandom всегда выплюнет биты. Документы говорят, что /dev/urandom хорош для криптографии, и вам нужно использовать /dev/random для ssl certs и тому подобное.
Мой вопрос будет gen_pass хорош для создания надежных паролей криптографического класса? Если я вызову эту функцию как можно быстрее, я перестану получать сильные критические биты в какой-то момент, потому что пул энтропии исчерпан?
Вопрос также может заключаться в том, почему /dev/urandom всегда производит сильные биты cryto и не заботится об энтропии_avail?
Возможно, что /dev/urandom сконструирован таким образом, что его пропускная способность ограничена количеством циклов, которые вы можете догадаться, будет коррелировано с количеством энтропии, но это предположение, и я не могу найти ответ.
Также это мой первый вопрос о стеке, поэтому, пожалуйста, критикуйте меня. Меня беспокоит то, что я много рассказывал, когда кто-то, кто знает ответ, вероятно, знает фон.
Спасибо
Обновление
Я написал некоторый код, чтобы посмотреть на энтропийный пул, пока /dev/urandom
читал:
import subprocess
import time
from pygooglechart import Chart
from pygooglechart import SimpleLineChart
from pygooglechart import Axis
def check_entropy():
arg = ['cat', '/proc/sys/kernel/random/entropy_avail']
ps = subprocess.Popen(arg,stdout=subprocess.PIPE)
return int(ps.communicate()[0])
def run(number_of_tests,resolution,entropy = []):
i = 0
while i < number_of_tests:
time.sleep(resolution)
entropy += [check_entropy()]
i += 1
graph(entropy,int(number_of_tests*resolution))
def graph(entropy,rng):
max_y = 200
chart = SimpleLineChart(600, 375, y_range=[0, max_y])
chart.add_data(entropy)
chart.set_colours(['0000FF'])
left_axis = range(0, max_y + 1, 32)
left_axis[0] = 'entropy'
chart.set_axis_labels(Axis.LEFT, left_axis)
chart.set_axis_labels(Axis.BOTTOM,['time in second']+get_x_axis(rng))
chart.download('line-stripes.png')
def get_x_axis(rng):
global modnum
if len(filter(lambda x:x%modnum == 0,range(rng + 1)[1:])) > 10:
modnum += 1
return get_x_axis(rng)
return filter(lambda x:x%modnum == 0,range(rng + 1)[1:])
modnum = 1
run(500,.1)
Если запустите это и запустите:
while 1 > 0:
gen_pass()
Затем я довольно надежно получаю график, который выглядит так:
Выполнение графика во время работы cat /dev/urandom
выглядит smiler, а cat /dev/random
падает до нуля и остается очень быстрым (это также выводится как байт каждые 3 секунды или около того)
Обновление
Если я запускаю тот же тест, но с шестью экземплярами gen_pass(), я получаю следующее:
Итак, похоже, что что-то делает так, что у меня достаточно энтропии. Я должен измерить скорость генерации пароля и убедиться, что на самом деле он ограничен, потому что если это не так, то может произойти что-то подозрительное.
Обновление
Я нашел эту цепочку
Это говорит о том, что urandom перестанет тянуть энтропию, когда у пула только 128 бит. Это очень согласуется с приведенными выше результатами и означает, что в этих тестах я часто выпускаю нежелательные пароли.
Предполагалось, что если entropy_avail был достаточно высоким (скажем, выше 64 бит), то результат /dev/urnadom
был хорошим. Это не так, кажется, что /dev/urandom
был разработан, чтобы оставить дополнительную энтропию для /dev/random
в случае, если она ему нужна.
Теперь мне нужно выяснить, сколько истинных случайных битов требуется вызову SystemRandom.