Python и случайные ключи 21 символа макс.

После своего рода эфианизма я разобрался с ответом на свой вопрос, поэтому здесь другие могут сослаться на него в будущем.

правильные функции следующие:

bool check (char hiddenArray [][ARRAY_SIZE], int x1, int y1, int x2, int y2){
    bool result = false;

    if (hiddenArray[x1][y1] == hiddenArray[x2][y2] && hiddenArray[x1][y1] != 'X' && hiddenArray[x2][y2]){
        result = true;
    }
    else if (hiddenArray[x1][y1] > ARRAY_SIZE || hiddenArray[x2][y2]){
        result = false;
    }
    return result;
}

//UPDATES ARRAY WITH CORRECT ANSWERS
void updateArray (char visibleArray[][ARRAY_SIZE], char hiddenArray [][ARRAY_SIZE], int x1, int y1){
    visibleArray[x1][y1] = hiddenArray[x1][y1];
}

Я также обнаружил ошибку, которая возвращала странные значения в моих функциях пользовательского ввода, и они также исправлены ниже, чтобы не вводить пользователя в заблуждение: [114 ]

//USER CHOICE FUNCTIONS
int userChoiceX (){
    int x;
    cout << "Please select a row value:";
    cin >> x;
    return x-1;
}

int userChoiceY (){
    int y;
    cout << "Please select a column value:";
    cin >> y;
    return y-1;
}
7
задан coulix 7 March 2009 в 10:36
поделиться

5 ответов

Если я считал Ваш вопрос правильно, Вы хотите генерировать некоторый произвольный маркер идентификатора, который должен быть 21 символом максимум. Это должно быть очень стойким к предположению? Пример, который Вы дали, не "crytographically силен", в котором он может быть предположен путем поиска намного меньше, чем 1/2 всего возможного ключевого пространства.

Вы не говорите, могут ли символы быть всеми 256 символами ASCII, или если это должно быть ограничено, скажем, печатаемым ASCII (33-127, включительно), или некоторый меньший диапазон.

Существует модуль Python, разработанный для UUID (Уникальные идентификаторы Universals). Вы, вероятно, хотите uuid4, который генерирует случайный UUID и использует поддержку ОС при наличии (на Linux, Mac, FreeBSD и вероятных других).

>>> import uuid
>>> u = uuid.uuid4()
>>> u
UUID('d94303e7-1be4-49ef-92f2-472bc4b4286d')
>>> u.bytes
'\xd9C\x03\xe7\x1b\xe4I\xef\x92\xf2G+\xc4\xb4(m'
>>> len(u.bytes)
16
>>> 

16 случайных байтов являются очень неотгадываемыми, и нет никакой потребности использовать полный 21 байт, который позволяет Ваш API, если все, что Вы хотите, должно иметь неотгадываемый непрозрачный идентификатор.

Если Вы не можете использовать необработанные байты как этот, который является, вероятно, плохой идеей, потому что более трудно использовать в журналах и других сообщениях отладки и тяжелее выдержать сравнение глазом, то преобразуйте байты во что-то более читаемое, как использование кодировки Base 64, с результатом, срубленным к 21 (или безотносительно) байты:

>>> u.bytes.encode("base64")
'2UMD5xvkSe+S8kcrxLQobQ==\n'
>>> len(u.bytes.encode("base64")) 
25
>>> u.bytes.encode("base64")[:21]
'2UMD5xvkSe+S8kcrxLQob'
>>> 

Это дает Вам чрезвычайно высококачественную случайную строку длины 21.

Вам не могло бы понравиться '+' или '/', который может быть в основе 64 строками, с тех пор без надлежащего выхода, который мог бы вмешаться в URL. Так как Вы уже думаете для использования "случайных 3 символов", я не думаю, что это - ваше беспокойство. Если это, Вы могли бы заменить те символы чем-то еще ('-', и'.' мог бы работать), или удалите их если существующий.

Как другие указали, Вы могли использовать .encode ("шестнадцатеричное число") и получить шестнадцатеричный эквивалент, но это составляет только 4 бита случайности/символа *, 21 символ макс. дает Вам 84 бита случайности вместо дважды этого. Каждый бит удваивает Ваше ключевое пространство, делая теоретическое пространство поиска очень, намного меньшим. Фактором 2E24 меньший.

Ваше ключевое пространство все еще 2E24 в размере, даже с шестнадцатеричным кодированием, таким образом, я думаю, что это - больше теоретическое беспокойство. Я не волновался бы о людях, делающих атаки перебором против Вашей системы.

Править:

P.S.: функция uuid.uuid4 использует libuuid при наличии. Это получает его энтропию от os.urandom (при наличии) иначе с текущего времени и локального MAC-адреса Ethernet. Если libuuid не доступен затем, функция uuid.uuid4 получает байты непосредственно от os.urandom (при наличии) иначе, это использует случайный модуль. Случайный модуль использует семя по умолчанию на основе os.urandom (при наличии) иначе значение на основе текущего времени. Зондирование происходит для каждого вызова функции, поэтому если у Вас нет os.urandom затем, издержки немного больше, чем Вы могли бы ожидать.

Забрать домой сообщение? Если Вы знаете, что у Вас есть os.urandom затем, Вы могли бы сделать

os.urandom(16).encode("base64")[:21]

но если Вы не хотите волноваться о его доступности, затем используют uuid модуль.

23
ответ дан 6 December 2019 в 05:56
поделиться

Шестнадцатеричное представление MD5 имеет очень плохую случайность: Вы только получаете 4 бита энтропии на символ.

Используйте случайные символы, что-то как:

import random
import string
"".join([random.choice(string.ascii_letters + string.digits + ".-")
        for i in xrange(21)])

В выборе помещает все приемлемые символы.

В то время как использование реальной хеш-функции, такой как SHA1 также получит Вас, хорошие результаты, если используется правильно, добавленная сложность и потребление ресурсов ЦП кажутся не выровненными по ширине для Ваших потребностей. Вы только хотите случайную строку.

4
ответ дан 6 December 2019 в 05:56
поделиться

Символы или байты? Если это берет произвольные строки, можно просто использовать байты и не волноваться о расширении до читаемых символов (для которого base64 был бы лучше, чем шестнадцатеричное число так или иначе).

MD5 генерирует 16 символов, если Вы не используете шестнадцатеричное расширение его. SHA1 генерирует 20 при том же условии.

>>> import hashlib
>>> len(hashlib.md5('foobar').digest())
16
>>> len(hashlib.sha1('foobar').digest())
20

Немного дополнительных байтов необходимы после этого.

0
ответ дан 6 December 2019 в 05:56
поделиться

Почему бы не взять сначала 21 символ от хеша SHA1 или md5?

2
ответ дан 6 December 2019 в 05:56
поделиться

Модуль base64 может выполнять кодирование, безопасное для URL. Так что, при необходимости, вместо

u.bytes.encode("base64")

вы могли бы сделать

import base64

token = base64.urlsafe_b64encode(u.bytes)

и, для удобства, конвертировать обратно

u = uuid.UUID(bytes=base64.urlsafe_b64decode(token))
2
ответ дан 6 December 2019 в 05:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: