使用内置校验和创建唯一ID?

时间:2012-02-02 19:59:12

标签: c# unique checksum

我想自动生成一个唯一的8-10个字符的ID字符串,其中包含某种校验和位,以防止数据录入时出现错字。我更喜欢没有连续数字的东西,数据输入人员会以“rut”结束,并习惯于一直输入相同的序列。

是否有与此类事情相关的最佳做法/陷阱?

更新:好的,我想我需要提供更多细节。

  1. 我想使用字母数字,而不仅仅是数字
  2. 我希望行为类似于信用卡校验和,除了8-10个字符而不是16位
  3. 我希望id是唯一的;不应该有碰撞的可能性。
  4. 第二次更新好的,我不明白这有什么令人困惑,但我会尝试进一步解释。我正在尝试创建将在表单上创建的跟踪号码,这些号码将在以后填写并输入数据。我将生成id并将其打在表单上; id需要是唯一的,它需要支持很多数字,并且它需要合理地防止数据输入。

    我不知道这是否已经完成,或者即使可以做到,但是问这个问题也没什么坏处。

4 个答案:

答案 0 :(得分:4)

您可以模仿航空预订系统:他们使用A-Z和0-9作为字符将数字转换为base-36。因此它们的上限为36 ^ 6。

如果您需要保证唯一性,并且您不希望它们是连续的,那么您必须将使用过的随机数保存在某个表格中。

获得随机ID或伪随机ID后,您只需计算您的checkdigit。

Use a CRC algorithm.它们可以适应任何所需的长度(在您的情况下,6位)。

修改

如果不清楚:即使你使用alpha代码,你也必须在生成checkdigit之前把它变成一个数字。

修改

  1. 校验和验证不是重量级的,它可以在javascript中实现客户端。
  2. 六个字符的字母数字(即航空公司记录定位符)= 10个 octillion 个数字。当然这够了吗? (有关确切结果,请参阅Wolfram Alpha。)

答案 1 :(得分:2)

大多数信用卡使用Luhn algorithm(也称为mod10算法)作为校验和算法来验证卡号。来自维基百科:

  

Luhn算法将检测任何单位错误,以及   几乎所有相邻数字的换位。但是,它不会   检测两位数序列09到90的转置(或反之   亦然)。

该算法是通用的,可以应用于任何识别号。

答案 2 :(得分:2)

你的问题很普遍 - 因此只是一些一般方面:

  • ID是否需要“不可饶恕”? 如果是的话,那么某种散列应该在混合中。

  • ID是否需要“安全”(例如激活密钥或其他内容)? 如果是,那么某种公钥加密应该是混合的。

  • ID /校验和计算需要快吗? 如果是,则可能需要一些非常简单的算法,如CRC32或Luhn(信用卡校验和算法)或soem条形码校验和算法。

  • ID生成是否集中? 如果没有,那么您可能需要查看GUID,当前时间,MAC地址和类似的东西。

更新 - 根据评论:

  • 使用DB中的序列
  • 获取该值并将其哈希,例如使用MD5
  • 获取该哈希的最不重要的40-48位
  • 将其编码为Base-36(0-9和A-Z),它为您提供8-10“数字”(字母数字)
  • 检查数据库的结果,如果ID已存在则丢弃(非常罕见的碰撞可能性)
  • 计算CRC-6-ITU(参见第3页的http://www.itu.int/rec/T-REC-G.704-199810-I/en
  • 将CRC结果附加为最后一个“数字”(也称为base-36)
  • 因此您拥有一个包含校验和的唯一ID

要检查输入的值,您只需从最后一位数字中重新计算CRC-6-ITU,然后将结果与最后一位数字进行比较。

上述内容相当“不可饶恕”,但绝对不是“高度安全”。

更新2 - 根据评论:

有关如何在javascript中计算CRC的一些灵感,请参阅this - 它包含CRC-8的javascript代码等。

您应该能够根据CRC-6-ITU多项式调整此代码。

答案 3 :(得分:1)

正如@BrokenGlass所说,你可以使用Luhn校验位算法。信用卡等使用Luhn算法 modulo 10. Luhn mod 10 计算从字母表中抽取的句子的校验位,仅由十进制数字组成(0-9 )。但是,它很容易适用于计算从任何大小的字母表中提取的句子的校验位(二进制,八进制,十六进制,字母数字等)

要做到这一点,您只需要两种方法和一种属性:

  • 正在使用的字母表中的代码点数量。

    这实际上是编号系统的 base 。例如,十六进制(基数为16)字母表由16个字符组成(忽略区分大小写的问题):'0123456789ABCDEF'。 '0' - '9'有其通常的含义; 'A' - 'F'是代表10-15的基数16位数。

  • 将字符从使用中的字母转换为相应的代码点的方法。

    例如,以十六进制表示,字符“0” - “9”代表代码点0-9;字符'A' - 'F'代表代码点10-15。

  • 将代码点转换为相应字符的方法。

    与上述相反。例如,在十六进制中,代码点12将转换为字符“C”。

如果字母表中不存在给定的代码点,您应该通过ArgumentException

维基百科的文章"Luhn mod N algorithm"在解释校验位的计算及其验证方面做得非常好。