代码之家  ›  专栏  ›  技术社区  ›  Jaime

创建一个小的(<10位),而不是(非常)安全的“哈希”的想法

  •  15
  • Jaime  · 技术社区  · 16 年前

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

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

    数据范围很小,4天内只有20个活动,每个活动大约5000张门票(大约100000个不同的门票代码)

    现在,我有几个字段没有打印在票据上,用户也不知道我可以用来编码部分“票据代码”,所以我可以使用eventid、orderid、eventdate和一些salt为部分代码创建一个小的“哈希”(ideas?),但我仍然坚持使用顺序的票据ID或guid(太长)

    关于如何做到这一点有什么想法或建议吗?

    7 回复  |  直到 14 年前
        1
  •  1
  •   Alix Axel    15 年前

    考虑一个基于Feistel网络的非常简单的方案来排列,例如,票据ID号。 This message (这恰好在PostgreSQL列表中,但与PostgreSQL没有太多关系)描述了一个简单的 Feistel network . 在每张票上,您可以打印一个票ID号(按顺序选择),然后打印一个“票密码”,这是通过Feistel网络输入ID号的结果。可能的变化包括在密码上附加一个校验位,并将输入建立在Feistel网络的基础上,而不仅仅是顺序生成的数字(数字+10000*事件ID号,等等)。

        2
  •  12
  •   Unknown    16 年前

    为什么要重新发明轮子?只需这样做(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
    

    Ticketman先生带着他的验证器过来,输入事件/票号和散列:

    def verifier(eventnum, ticketnum, hash):
        return hash == createticket(eventnum, ticketnum)
    
    verifier(1,123, "2d7f242597")
    # ouput: True
    
        3
  •  5
  •   Alix Axel    16 年前

    我建议你给 Verhoeff algorithm 尝试一下。

        4
  •  3
  •   Lasse V. Karlsen    16 年前

    我可以看到两种方式:

    1. 生成一个随机数,或者至少为一个数字生成一个随机部分,并将其存储在中央数据库中。然后将数据库下载到所有闸门系统中进行检查。
    2. 这个数字必须是自给自足的。换句话说,该号码必须能够在没有保存列表的情况下签出。这听起来像是某种校验和系统。例如,您可以从1开始并向上发出数字,使它们成为5个数字(00000-99999=100.000个数字),并预付1-3个字母,确保您最终得到一个校验和,该校验和将签出。
        5
  •  0
  •   chuck    16 年前

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

    在票据ID后面附加一个票据ID的散列值和一个每个事件的salt。您可以将任何加密哈希截断到所需的大小。我想不出一个特殊的原因来使用任何东西,除了一个随机数作为基票ID本身。

    这允许您限制票据ID的大小,并具有与票据ID大小明显成比例的安全性。

        6
  •  0
  •   James Black    16 年前

    你可以做一个CRC计算。

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

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

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

        7
  •  0
  •   James A. Rosen    16 年前

    这里有一个方案,它的优点是允许您从上一个计算下一个票散列(这样您就可以验证是否缺少一个票散列),但不允许外部人员计算下一个票散列:

    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个不在问题中,它给了您256倍的票ID)