关于算法:如何生成验证码/号码?

关于算法:如何生成验证码/号码?

How to generate a verification code/number?

我正在开发一个应用程序,其中用户必须拨打电话并用手机的键盘输入验证码。

我希望能够检测到他们键入的数字是否正确。电话系统无法访问有效号码列表,但会根据算法(例如信用卡号)验证号码。

以下是一些要求:

  • 键入有效的随机码一定很困难
  • 输入错字(数字换位,数字错误)一定很难获得有效的代码
  • 我必须有合理数量的可能组合(比如说1M)
  • 该代码必须尽可能短,以避免用户输入错误

鉴于这些要求,您将如何生成这样的数字?

编辑:

@Haaked:该代码必须为数字,因为用户使用其手机进行了键入。

@matt b:第一步,代码显示在网页上,第二步是调用并键入代码。我不知道用户的电话号码。

后续:我发现了几种算法来检查数字的有效性(请参阅此有趣的Google Code项目:checkDigits)。


经过研究,我认为我将采用ISO 7064 Mod 97,10公式。由于它用于验证IBAN(国际银行帐号),因此看起来非常可靠。

公式很简单:

  • 取一个数字:123456
  • 应用以下公式来获得2位数的校验和:mod(98 - mod(number * 100, 97), 97) => 76
  • Concat编号和校验和以获得代码=> 12345676
  • 要验证代码,请验证mod(code, 97) == 1
  • 测试:

    • mod(12345676, 97) = 1 =>良好
    • mod(21345676, 97) = 50 =>不好!
    • mod(12345678, 97) = 10 =>不好!

    显然,该算法捕获了大多数错误。

    另一个有趣的选择是Verhoeff算法。它只有一个验证码,并且更难以实现(与上面的简单公式相比)。


    对于1M组合,您需要6位数字。为了确保没有任何意外有效的代码,我建议使用9位数字,并且有1/1000的机会使用随机代码。我还建议使用另一个数字(共10个数字)执行完整性检查。就分发方式而言,随机就足够了,校验位将确保单个错误不会导致正确的代码。

    编辑:显然我没有完全阅读您的请求。使用信用卡号,您可以对其进行哈希处理(MD5或SHA1或类似的名称)。然后,您在适当的位置截断(例如9个字符)并将其转换为10。然后添加校验位,这或多或少会适合您的目的。


    您想对代码进行分段。它的一部分应该是其余代码的16位CRC。

    如果您只需要一个验证号,则只需使用一个序列号(假设您有一个生成点)。这样,您就知道不会重复。

    然后,为该序列添加该序列号的CRC-16前缀和一些私钥。您可以将任何东西用作私钥,只要您将其保持私密即可。使它变大,至少要有一个GUID,但这可以是古腾堡项目给《战争与和平》写的文字。只是需要保持秘密和不断。拥有私钥会阻止人们伪造密钥,但是使用16位CR使其更容易破解。

    要进行验证,您只需将数字分为两部分,然后对序列号和私钥进行CRC-16校验。

    如果要进一步遮掩顺序部分,则将CRC分为两部分。将3位数字放在序列的前面,再将2位放在序列的后面(零填充,因此CRC的长度是一致的)。

    此方法还允许您从较小的键开始。前10个键将是6位数字。


    一定只是数字吗?您可以创建一个介于1到1M之间的随机数(尽管我建议更高),然后Base32对其进行编码。您需要做的下一件事是对值(使用秘密盐值)进行哈希处理,然后base32对哈希进行编码。然后将两个字符串附加在一起,也许用短划线隔开。

    这样,您可以通过算法验证传入的代码。您只需使用代码的左侧,使用您的秘密盐对其进行哈希处理,然后将该值与代码的右侧进行比较即可。


    您已链接到支票号码项目,并且使用"编码"功能似乎是一个不错的解决方案。它说:

    encode may throw an exception if 'bad' data (e.g. non-numeric) is passed to it, while verify only returns true or false. The idea here is that encode normally gets it's data from 'trusted' internal sources (a database key for instance), so it should be pretty usual, in fact, exceptional that bad data is being passed in.

    因此,听起来您可以将编码函数传递给数据库密钥(例如5位数字),并且可以得到一个满足您要求的数字。


    听起来您有一个不言而喻的要求,即必须通过算法快速确定该代码有效。这将排除您仅分发一个时区号码列表的可能性。

    过去人们有几种方法可以做到这一点。

  • 制作公用密钥和专用密钥。使用私钥对数字0-999,999进行编码,然后分发结果。您需要输入一些随机数以使结果出现在更长的版本中,并且必须将结果从64转换为10。输入数字后,将其转换回base64,应用私钥,并查看有趣的数字是否低于1,000,000(丢弃随机数字)。
  • 使用可逆哈希函数
  • 使用以特定值播种的PRN中的前一百万个数字。"检查"功能可以获取种子,并且知道接下来的一百万个值是好的。它既可以每次生成它们,并在收到代码时一一检查,也可以在程序启动时将它们全部存储在一个表中,进行排序,然后使用二进制搜索(最大比较数),因为一百万个整数不是整数空间。
  • 还有很多其他选项,但是这些选项很常见且易于实现。

    -亚当


    假设您已经知道如何检测用户按下了哪个键,那么应该可以轻松地做到这一点。在安全领域中,存在"一次性"密码的概念。有时将其称为"一次性密码"。通常,这些值仅限于(易于键入的)ASCII值。因此,[a-zA-z0-9]和一堆易于键入的符号。如逗号,句号,半冒号和括号。不过,就您而言,您可能希望将范围限制为[0-9],并可能包括*和#。

    我无法解释如何充分生成(或工作)这些一次性代码的所有技术细节。它背后有一些中级数学,我会亲自屠夫而无需先对其进行复习。可以说您使用一种算法来生成一次密码流。无论您之前知道的代码多么简单,后面的代码都应该是不可能的!就您而言,您只需将列表中的每个密码用作用户的随机代码。

    除了直接自己解释实现的细节外,我还将带您转到9页的文章,您可以自己自己阅读该文章:https://www.grc.com/ppp.htm


    创建验证码时,您可以访问呼叫者的电话号码吗?

    如果是这样,我将使用呼叫者的电话号码并通过某种哈希函数运行它,以便您可以确保在步骤1中提供给呼叫者的验证码与他们在步骤2中输入的验证码相同(以确保他们没有使用朋友的验证码,或者只是做出了非常幸运的猜测)。

    关于哈希,我不确定是否可以采用10位数字并得出小于10位的哈希结果(我想您必须承受一定的冲突),但是我认为这将有助于确保用户就是他们所说的。

    当然,如果步骤1中使用的电话号码不同于他们在步骤2中呼叫的电话号码,则此方法将无效。


    • I must have a reasonnable number of possible combinations (let's say 1M)
    • The code must be as short as possible, to avoid errors from the user

    好吧,如果您希望它具有至少一百万个组合,那么您至少需要六位数字。够短吗?


    推荐阅读

      查看linux用户命令行?

      查看linux用户命令行?,信息,系统,时间,名称,密码,用户,命令,地址,状态,设备,L

      linux所有用户命令行?

      linux所有用户命令行?,系统,信息,地址,工作,密码,命令,用户,时间,电脑,管理,L

      linux看用户信息命令?

      linux看用户信息命令?,系统,密码,信息,状态,软件,情况,命令,用户,网络,时间,l

      linux下删除用户命令?

      linux下删除用户命令?,系统,代码,邮箱,用户组,命令,用户,名称,管理,电脑,账

      用户id的linux命令?

      用户id的linux命令?,系统,密码,信息,联系方式,地址,位置,用户,命令,用户名,

      linux删除用户组命令?

      linux删除用户组命令?,管理,系统,密码,电脑,名称,用户,用户组,名字,信息,工

      linux下用户权限命令?

      linux下用户权限命令?,管理,系统,密码,地址,权限,时间,基础,信息,基本知识,

      linux登陆用户命令?

      linux登陆用户命令?,系统,工具,信息,地址,软件,工作,命令,数字,服务,名称,Lin

      linux用户名改名命令?

      linux用户名改名命令?,系统,密码,命令,代码,名称,用户名,用户,终端,主机名,

      linux用户分组命令?

      linux用户分组命令?,系统,命令,电脑,信息,时间,标准,资料,用户,文件,用户组,L

      linux命令改用户所属?

      linux命令改用户所属?,系统,文件,名称,用户组,命令,用户,名录,基本知识,所

      linux系统用户组命令?

      linux系统用户组命令?,系统,管理,密码,代码,用户组,用户,命令,邮箱,电脑,名

      linux用户管理的命令?

      linux用户管理的命令?,系统,管理,信息,地址,工作,用户,单位,基础,数据,命令,L

      linux用户退出命令行?

      linux用户退出命令行?,状态,档案,标准,系统,命令,文件,模式,编辑,指令,主机,l

      linux排序数字命令?

      linux排序数字命令?,标准,数字,单位,情况,系统,信息,命令,文件,顺序,参数,lin

      linux命令不能打数字?

      linux命令不能打数字?,工作,密码,数字,地址,电脑,系统,命令,设备,下来,预期,

      linux用户自定义命令?

      linux用户自定义命令?,系统,时间,标准,软件,项目,电脑,服务,工具,基本知识,

      linux用户组命令设置?

      linux用户组命令设置?,管理,系统,密码,代码,电脑,用户组,用户,软件,新增,命

      linux进入用户命令行?

      linux进入用户命令行?,系统,地址,工作,服务,信息,命令,首页,电脑,密码,终端,L

      linux用户用不了命令?

      linux用户用不了命令?,系统,档案,不了,命令,网络,密码,信息,情况,用户,权限,l