16

我正在开发一个在线活动票务系统,用户将能够自行打印他的门票并出现在将被扫描(条形码)的活动中,理想情况下该人将进入。我的问题是如何创建一个满足以下要求的“机票代码”:

  • 每个“票号”需要彼此充分不同(即不按顺序编号)
  • 理想情况下,票证将根据中央数据库进行检查以防止重用,但它也需要能够离线工作,在这种情况下,系统必须检查“有效”票证代码并且它尚未用于门。
  • “票证代码”必须足够小,以便在需要时方便键入
  • 持票人只需要门票即可进入(即无需身份检查)

数据的范围非常小,4 天内只有大约 20 个活动,每个活动大约 5,000 张门票(大约 100,000 个不同的门票代码)

现在我有几个字段没有打印在票上并且用户不知道我可以用来编码部分“票代码”,所以我可以使用 EventId、OrderId、EventDate 和一些盐来创建一个小的“ hash" 用于部分代码(想法?),但我仍然坚持使用顺序的票证 ID 或 GUID(会太长)

那么关于如何做到这一点的任何想法或指示?

4

7 回答 7

13

为什么要重新发明轮子?做这样的事情(Python代码,问我是否需要澄清):

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
于 2009-05-21T03:16:10.390 回答
5

我建议你试试Verhoeff 算法

于 2009-05-21T00:35:35.177 回答
3

我可以看到两种方式:

  1. 生成一个随机数,或者至少是一个数字的随机部分,并将其存储在中央数据库中。然后将数据库下载到所有门禁系统中进行检查。
  2. 数量必须自给自足。换句话说,该号码必须能够在没有保存列表的情况下签出。这听起来像是某种校验和系统。例如,您可以发出 1 及以上的数字,将它们设为 5 位数字(00000-99999 = 100.000 个数字),并在前面加上 1-3 个字母,以确保您最终得到一个可以检查的校验和。
于 2009-05-21T00:37:16.547 回答
1

考虑一个基于 Feistel 网络的非常简单的方案来置换票证 ID 号。这条消息(恰好在 PostgreSQL 列表中,但与 PostgreSQL 没有太大关系)描述了一个简单的Feistel 网络。在每张票上,您可以打印一个票号(按顺序选择),然后是一个“票号密码”,这是通过 Feistel 网络输入 ID 号的结果。可能的变化包括在密码上附加一个校验位,以及将 Feistel 网络的输入不仅仅基于顺序生成的数字(数字 + 10,000 * 事件 ID 号等)。

于 2009-05-21T01:27:49.657 回答
0

对于离线验证,我只看到一个简单的解决方案..

将票证 ID 的哈希值和每个事件的盐附加到票证 ID。您可以将任何加密哈希截断为所需的大小。除了基本票证 ID 本身的随机数之外,我想不出有什么特别的理由。

这允许您限制票证 ID 的大小,并具有与票证 ID 大小相关的明确比例的安全性。

于 2009-05-21T01:14:40.247 回答
0

你可以做一个CRC计算。

基本上,只需开始在字符串中添加每个字符,并将长度限制为长整数。

您可以从一个已知的随机数开始并将其存储在前 4 个字节中,并让后四个作为我之前描述的计算。

这将是两个整数或八个字节。

于 2009-05-21T02:19:41.953 回答
0

这是一个方案,它的优点是可以让您从上一个票证哈希计算下一个(因此您可以验证是否缺少一个),但不允许外人计算下一个票证:

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

在哪里

  • HASH是在输出字符串中相对均匀分布其熵的任何散列函数
  • SALT是一个你保守秘密的常数;为每个事件使用不同的事件是个好主意
  • IV是另一个你保密的常数
  • LENGTH 是您想要的票证 ID 的长度(您的问题中有 10 个,但 12 不是不可能的,它给您的票证 ID 是 256 倍)
于 2009-05-21T02:48:21.087 回答