Что более случайное, hashlib или urandom?
Я работаю над проектом с другом, где нам нужно создать случайный хеш. Прежде чем мы успели обсудить, мы оба придумали разные подходы и потому, что они используют разные модули, я хотел спросить вас, что будет лучше - если есть такая вещь.
hashlib.sha1(str(random.random())).hexdigest()
или
os.urandom(16).encode('hex')
Ввод этого вопроса заставил меня думать, что второй метод лучше. Простой лучше, чем сложный. Если вы согласитесь, насколько это надежна для "случайных" генерирующих хэшей? Как я могу это проверить?
Ответы
Ответ 1
Это решение:
os.urandom(16).encode('hex')
является лучшим, поскольку использует ОС для генерации случайности, которая должна использоваться для криптографических целей (зависит от реализации ОС).
random.random()
генерирует псевдослучайные значения.
Хеширование случайного значения не добавляет никакой новой случайности.
Ответ 2
random.random()
является генератором псевдорадмома, что означает, что числа генерируются из последовательности. если вы вызываете random.seed(some_number)
, то после этого сгенерированная последовательность всегда будет одинаковой.
os.urandom()
получают случайные числа из os 'rng, который использует пул энтропии для сбора реальных случайных чисел, как правило, случайными событиями с аппаратных устройств, существуют даже случайные специальные энтропийные генераторы для систем, где множество случайных чисел.
в системе unix традиционно существуют два генератора случайных чисел: /dev/random
и /dev/urandom
. вызовы в первый блок, если доступ к энтропии недостаточно, тогда как при чтении /dev/urandom
и доступных данных энтропии недостаточно, он использует псевдо-rng и не блокирует.
поэтому использование зависит обычно от того, что вам нужно: если вам нужны несколько одинаково распределенных случайных чисел, тогда необходимо создать встроенный prng. для криптографического использования всегда лучше использовать реальные случайные числа.
Ответ 3
Второе решение явно больше энтропии, чем первое. Предполагая, что качество источника случайных битов будет одинаковым для os.urandom
и random.random
:
- Во втором решении вы извлекаете 16 байт = 128 бит. Случайность
- В первом решении вы получаете значение с плавающей запятой, которое имеет примерно 52 бита случайности (IEEE 754 double, игнорируя субнормальные числа и т.д.). Тогда вы его используете, что, конечно, не добавляет случайности.
Что еще более важно, ожидается, что качество случайности, исходящее из os.urandom
, будет намного лучше, чем случайность, исходящая от random.random
. os.urandom
docstring говорит "подходит для криптографического использования".
Ответ 4
Тестирование случайности, как известно, затруднено - однако, я бы выбрал второй метод, но ТОЛЬКО (или, насколько это возможно, для этого случая), где хеш посеяно случайным числом.
Весь смысл хэшей заключается в создании числа, которое сильно отличается от незначительных различий во входных данных. Для вашего случая использования случайный ввод должен делать. Если, однако, вы хотите хэшировать файл и обнаруживать одну разницу в байтах, что при сильном хеш-алгоритме.
Мне просто интересно: зачем вообще использовать хэш-алгоритм? Кажется, что вы ищете чисто случайное число, и существует множество библиотек, которые генерируют uuid, которые имеют гораздо более сильные гарантии уникальности, чем генераторы случайных чисел.
Ответ 5
если вам нужен уникальный идентификатор (uuid), вы должны использовать
import uuid
uuid.uuid4().hex
https://docs.python.org/3/library/uuid.html