Подтвердить что ты не робот

Достаточно безопасная 8-символьная короткая уникальная случайная строка

Я пытаюсь вычислить 8-символьные короткие уникальные случайные имена файлов, скажем, тысячи файлов без вероятного столкновения имен. Является ли этот метод достаточно безопасным?

base64.urlsafe_b64encode(hashlib.md5(os.urandom(128)).digest())[:8]

Изменить

Чтобы быть яснее, я пытаюсь добиться простейшей возможной обфускации имен файлов, загружаемых в хранилище.

Я понял, что 8-символьная строка, достаточно случайная, будет очень эффективным и простым способом хранения десятков тысяч файлов без вероятного столкновения при правильной реализации. Мне не нужна гарантированная уникальность, только достаточно высокая невероятность столкновения имен (речь идет только о тысячах имен).

Файлы хранятся в параллельной среде, поэтому увеличение общего счетчика является достижимым, но сложным. Хранение счетчика в базе данных будет неэффективным.

Я также сталкиваюсь с тем фактом, что random() при некоторых обстоятельствах возвращает одинаковые псевдослучайные последовательности в разных процессах.

4b9b3361

Ответ 1

Есть ли причина, по которой вы не можете использовать tempfile для генерации имен?

Функции типа mkstemp и NamedTemporaryFile абсолютно гарантированно дают вам уникальные имена; ничто, основанное на случайных байтах, не даст вам этого.

Если по какой-то причине вы фактически не хотите, чтобы файл был создан еще (например, вы генерируете имена файлов, которые будут использоваться на каком-то удаленном сервере или что-то в этом роде), вы не можете быть абсолютно безопасны, но mktemp по-прежнему безопаснее, чем случайные имена.

Или просто сохраните 48-разрядный счетчик, хранящийся в некотором "глобальном достаточно" месте, поэтому вы гарантируете прохождение полного цикла имен перед столкновением, и вы также гарантируете знать, когда произойдет столкновение.

Все они безопаснее, проще и гораздо эффективнее, чем чтение urandom и делают md5.

Если вы действительно хотите генерировать случайные имена, ''.join(random.choice(my_charset) for _ in range(8)) также будет проще, чем то, что вы делаете, и более эффективным. Даже urlsafe_b64encode(os.urandom(6)) столь же случайен, как и хэш MD5, и более простой и эффективный.

Единственное преимущество криптографической случайности и/или криптографической хэш-функции заключается в том, чтобы избежать предсказуемости. Если это не проблема для вас, зачем платить за нее? И если вам нужно избегать предсказуемости, вам почти наверняка нужно избегать гонок и других гораздо более простых атак, поэтому избегать mkstemp или NamedTemporaryFile - очень плохая идея.

Не говоря уже о том, что, поскольку Root указывает на комментарий, если вам нужна безопасность, MD5 на самом деле не предоставляет его.

Ответ 2

Ваш текущий метод должен быть достаточно безопасным, но вы также можете заглянуть в модуль uuid. например.

import uuid

print str(uuid.uuid4())[:8]

Вывод:

ef21b9ad

Ответ 3

Вы можете попробовать это

import random
uid_chars = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
             'v', 'w', 'x', 'y', 'z','1','2','3','4','5','6','7','8','9','0')
uid_length=8
def short_uid():
    count=len(uid_chars)-1
    c=''
    for i in range(0,uid_length):
        c+=uid_chars[random.randint(0,count)]
    return c

например:

print short_uid()
nogbomcv

Ответ 4

как насчет случайного 8-значного числа? random.randrange(10**8)

import random

print random.randrange(10**8)

print '----------------------'

for x in xrange(10):
    print '{:08}'.format(random.randrange(10**8))

выход:

$ python foo.py
36714482
----------------------
09000782
82536385
29075031
43364370
81089457
53010521
12030602
69531566
07898400
38782440

Ответ 5

Я использую хеш-коды для преобразования временной метки в уникальный идентификатор. (Вы можете даже преобразовать его обратно в метку времени, если хотите).

Недостатком этого является то, что если вы создаете слишком быстро идентификаторы, вы получите дубликат. Но, если вы генерируете их со временем, то это вариант.

Вот пример:

from hashids import Hashids
from datetime import datetime
hashids = Hashids(salt = "lorem ipsum dolor sit amet", alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
print(hashids.encode(int(datetime.today().timestamp()))) #'QJW60PJ1' when I ran it

Ответ 6

Вы можете попробовать библиотеку shortuuid.

Установить с помощью: pip install shortuuid

Тогда это так просто, как:

> import shortuuid
> shortuuid.uuid()
'vytxeTZskVKR7C7WgdSP3d'