Идеи создания небольшого (<10 цифр), не очень (очень) безопасного "хеша" - PullRequest
15 голосов
/ 21 мая 2009

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

  • каждый «код билета» должен быть достаточно отличным друг от друга (т.е. не иметь последовательной нумерации)
  • в идеале билет будет проверен в центральной БД для предотвращения повторного использования, но НУЖНО иметь возможность работать и в автономном режиме, и в этом случае система должна проверить «действительный» код билета, и что он не был используется в этом вентиле.
  • «код билета» должен быть достаточно маленьким, чтобы при необходимости его можно было набрать
  • владельцу билета нужен только билет для входа (т.е. без проверки личности)

Диапазон данных очень мал, в течение 4 дней будет проведено всего около 20 мероприятий с около 5000 билетов на событие (около 100 000 различных кодов билетов)

Теперь у меня есть несколько полей, которые не напечатаны в заявке и не известны пользователю, которые я могу использовать для кодирования части «кода заявки», поэтому я могу использовать EventId, OrderId, EventDate и некоторую соль для создания небольшой «хэш» для части кода (идеи?), но я все еще застрял с идентификатором тикета, который является последовательным или GUID (будет слишком длинным)

Так какие-нибудь идеи или указатели о том, как это сделать?

Ответы [ 7 ]

12 голосов
/ 21 мая 2009

Зачем изобретать велосипед? Просто сделайте что-то вроде этого (Python Code, спросите меня, если вам нужно пояснение):

import hashlib

secretpassword = "blah"

def createticket(eventnum, ticketnum):
    m = hashlib.md5() # or any crypto hash you like
    m.update("%s%s%s" % (eventnum, ticketnum, secretpassword))
    return m.hexdigest()[:10]

Пример:

Событие № 1

Билет № 123

createticket(1,123)
# output: 2d7f242597

Мистер билетер приходит со своим верификатором и вводит номер события / билета и хэш:

def verifier(eventnum, ticketnum, hash):
    return hash == createticket(eventnum, ticketnum)

verifier(1,123, "2d7f242597")
# ouput: True
5 голосов
/ 21 мая 2009

Я предлагаю вам попробовать Verhoeff алгоритм .

3 голосов
/ 21 мая 2009

Два способа увидеть:

  1. Создайте случайное число или хотя бы случайную часть числа и сохраните его в центральной базе данных. Затем загрузите базу данных во все системы шлюзов для проверки.
  2. Номер должен быть самодостаточным. Другими словами, номер должен быть в состоянии проверить без сохраненного списка. Это звучит как какая-то система контрольных сумм. Например, вы можете выдавать цифры от 1 и выше, делать из них 5 цифр (00000-99999 = 100 000 цифр) и добавлять 1-3 буквы, чтобы в итоге вы получили контрольную сумму, которая проверяла бы.
1 голос
/ 21 мая 2009

Рассмотрим очень простую схему, основанную на сети Фейстеля, для преобразования, скажем, идентификационного номера билета. Это сообщение (которое находится в списках PostgreSQL, но на самом деле не имеет ничего общего с PostgreSQL) описывает простую сеть Фейстеля . На каждом билете вы можете напечатать идентификационный номер билета (выбранный последовательно), а затем «секретный код билета», который является результатом ввода идентификационного номера через сеть Feistel. Возможные варианты включают добавление контрольной цифры к секретному коду и основание ввода в сети Фейстеля не только на сгенерированном последовательно номере (число + 10 000 * идентификационный номер события и т. Д.).

0 голосов
/ 21 мая 2009

Вот схема, которая имеет преимущество, заключающееся в том, что она позволяет вам вычислять следующий хэш тикета из предыдущего (так что вы можете проверить, отсутствует ли один), но не позволяет посторонним вычислять следующий:

Ticket.0 = substring(HASH(SALT + IV        ), 0, LENGTH)
Ticket.i = substring(HASH(SALT + Ticket.i-1), 0, LENGTH)

, где

  • HASH - любая хеш-функция, которая равномерно распределяет свою энтропию по выходной строке
  • SALT - это константа, которую вы держите в секрете; Рекомендуется использовать разные для каждого события
  • IV это еще одна константа, которую вы держите в секрете
  • ДЛИНА - это длина нужного вам идентификатора билета (10 в вашем вопросе, но 12 не исключено и дает вам в 256 раз больше идентификаторов билетов)
0 голосов
/ 21 мая 2009

Вы можете сделать расчет CRC.

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

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

Это будет два целых или восемь байтов.

0 голосов
/ 21 мая 2009

Для проверки в автономном режиме я вижу только одно простое решение.

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

Это позволяет вам ограничить размер идентификатора билета и иметь четко пропорциональную защиту по отношению к размеру идентификатора билета.

...