17

我正在寻求开发一个系统,我需要为每个用户分配一个唯一的密码以确保安全。用户只会输入此 PIN 码作为识别自己的一种方式。因此,我不希望用户能够猜测其他用户的密码。假设我将拥有的最大用户数是 100000,这个密码应该是多长时间?

例如 1234 4532 3423

我应该通过某种算法生成此代码吗?还是我应该随机生成它?

基本上我不希望人们能够猜测其他人的密码,它应该支持足够数量的用户。

很抱歉,如果我的问题听起来有点令人困惑,但很乐意澄清任何疑问。

非常感谢你。

更新

在阅读了下面的所有帖子之后,我想添加更多细节。

  1. 我想要实现的是与刮刮卡非常相似的东西。
  2. 给用户一张卡,他/她必须刮擦才能找到密码。
  3. 现在使用此密码,用户必须能够访问我的系统。

我无法添加额外的安全性(例如用户名和密码),因为它会阻止用户使用刮刮卡。我想让在限制范围内猜测密码变得尽可能困难。

再次感谢大家的精彩回复。

4

11 回答 11

9

如果将 4 个随机数字附加到唯一的已知用户 ID(仍然可以是数字)[starblue 推荐],则应该足够了

伪随机数生成器也应该没问题。您可以使用可逆加密 (AES) 或单向哈希将这些存储在数据库中

您主要担心的是一个人在被锁定之前可能错误地输入了多少次密码。这应该很低,比如说大约三个......这将阻止人们猜测其他人的数字。

任何超过 6 位数字的人都会忘记它们,或者更糟的是,将它们写在显示器上的便利贴上。

假设一个帐户因 3 次错误尝试而被锁定,那么拥有一个 4 位密码加上一个用户 ID 组件 UserId (999999) + Pin (1234) 会给您 3/10000 的机会让您猜测。这可以接受吗?如果不使引脚长度为 5 并获得 3/100000

于 2009-01-01T10:10:43.810 回答
8

我可以建议一种替代方法吗?看看Perfect Paper Passwords及其提示的派生词

您可以使用此“原样”来生成一次性 PIN,或者只是为每个用户生成一个 PIN。

还要记住,重复的 PIN 本身并不是问题:任何攻击都只需要尝试多个用户 ID。

(里程警告:我绝对不是安全专家。)


这是第二个答案:通过重新阅读,我假设您不想要这样的用户 ID - 您只是在验证一组已发行的刮刮卡。我还假设您不想使用字母 PIN。

您需要选择一个 PIN 长度,以使猜测有效 PIN 的概率小于 1/(您可以防止的尝试次数)。因此,例如,如果您有 100 万个有效 PIN,并且想要防止 10000 次猜测,您将需要一个 10 位数的 PIN。

如果您使用 John Graham-Cumming 的Perfect Paper Passwords系统版本,您可以:

  1. 为(比如说)10 位十进制引脚配置这个
  2. 选择一个秘密 IV/关键短语
  3. 生成(比如说)前一百万个密码(/PIN)

我怀疑这是一个通用过程,例如,也可以用于生成 25 个字母数字的产品 ID。

很抱歉通过逐次逼近来做到这一点;我希望这更接近你正在寻找的东西。

于 2009-01-01T11:01:23.083 回答
5

如果我们假设最多有 100,000 个用户,那么他们可以拥有 0-99,999 的唯一 PIN,即。5位数。

但是,这将更容易猜测具有最大用户数的 PIN。如果您可以限制 PIN 的尝试次数,那么您可以使用更短的 PIN。例如。每个 IP 每天最多 10 次失败尝试。

这还取决于你所保护的东西的价值,以及如果奇怪的人真的出去了,那将是多么灾难性的。

如果您想保持简短,我会选择 9 位数字,如果您想从自动猜测中获得更多安全性,我会选择 12 位数字。

为了生成 PIN,我会采用高分辨率版本的时间以及一些和可能的伪随机数,生成哈希并使用前 9 或 12 位数字。确保新 PIN 生成之间存在合理且随机的延迟,因此不要循环生成它们,如果可能,请让它们由用户启动。

例如。左(Sha1(日期时间 + 盐 + 伪随机),9)

于 2009-01-01T13:30:02.580 回答
5

到目前为止有很多很棒的答案:简单、有效、优雅!

我猜这个应用程序有点像彩票,因为每个用户都会得到一张刮刮卡,并用它来询问你的应用程序是否“他已经中奖了!” 因此,从这个角度来看,我想到了一些新问题:

War-dialing,或者它的互联网等价物:一个流氓用户可以反复点击你的应用程序,比如连续猜测每个 10 位数字吗?如果有可能,请考虑限制来自特定位置的尝试次数。一种有效的方法可能是简单地拒绝回答,例如,从同一 IP 地址每 5 秒尝试一次以上。这使得机器驱动的攻击效率低下并避免了锁定问题

锁定问题:如果您在多次尝试失败后永久锁定帐户,您很容易受到拒绝服务攻击。除非您在一段时间后重新激活帐户,否则上述攻击者可以有效地锁定每个用户。但是,只有当您的 PIN 包含用户 ID + 密钥的明显串联时,这才是一个问题,因为攻击者可以尝试给定用户 ID 的每个密钥。该技术还大大减少了您的密钥空间,因为只有少数 PIN 数字是真正随机的。另一方面,如果 PIN 只是一个随机数字序列,则锁定只需要应用于源 IP 地址。(如果尝试失败,则不会影响有效帐户,那么您会“锁定”什么?)

数据存储:如果您真的在构建某种类似彩票的系统,您只需要存储中奖 PIN 码!当用户输入 PIN 时,您可以搜索相对较小的 PIN/奖品(或您的等价物)列表。如果经济情况正确,您可以将“丢失”和无效 PIN 与“抱歉,下次好运”消息或“默认”奖品一视同仁。

祝你好运!

于 2009-01-02T05:39:51.857 回答
2

问题应该是,“与攻击者的猜测次数相比,平均需要多少次猜测才能找到有效的 PIN 码?”

如果您生成 100 000 个 5 位代码,那么显然需要 1 次猜测。这不太可能足够好。

如果您生成 100 000 个 n 位代码,则需要 (n-5)^10 次猜测。要确定这是否足够好,您需要考虑您的系统如何响应错误的猜测。

如果一个攻击者(或所有攻击者的组合)每秒可以进行 1000 次猜测,那么显然 n 必须非常大才能阻止一个坚定的攻击者。如果您在 3 次错误猜测后永久锁定他们的 IP 地址,那么由于给定的攻击者不太可能访问超过 1000 个 IP 地址,因此 n=9 足以阻止几乎所有攻击者。显然,如果您将面临分布式攻击或来自僵尸网络的攻击,那么每个攻击者 1000 个 IP 地址不再是一个安全的假设。

如果将来您需要发布更多代码(超过 100 000 个),那么显然您可以更轻松地猜测有效代码。因此,现在可能值得花一些时间来确定您未来的扩展需求,然后再确定大小。

鉴于您的刮刮卡用例,如果用户要长时间使用系统,我建议允许他们(或强迫他们)在第一次使用后将他们的 PIN 码“升级”为他们选择的用户名和密码系统的。然后,您将获得用户名/密码的通常优势,而无需放弃仅在卡上输入数字的易用性。

至于如何生成数字-大概您生成的每个数字都会存储,在这种情况下,我会说随机生成它们并丢弃重复项。如果您使用任何一种算法生成它们,并且有人找出了算法,那么他们就可以找出有效的 PIN 码。如果您选择的算法使得某人无法弄清楚该算法,那么这几乎一个伪随机数生成器(PRNG 的另一个属性是它们是均匀分布的,这在这里也有帮助,因为它使得它更难猜测代码),在这种情况下,您不妨随机生成它们。

于 2009-01-01T12:33:36.877 回答
2

如果您使用随机数生成器算法,那么您永远不会有像 "00038384882" 这样的 PIN,以 0(零)开头,因为整数永远不会以“0”开头。您的 PIN 必须以 1-9 数字开头,但 0 除外。

我已经看到许多 PIN 号码包含并开始许多零,因此您消除了前一百万个数字。置换需要计算消除了多少个数。

我认为您需要将 0-9 个数字放入哈希中,并从哈希中随机获取,并制作您的字符串 PIN 号。

于 2012-03-08T11:24:42.443 回答
1

如果要生成刮刮卡类型的密码,则必须使用大数字,大约 13 位长;而且,它们必须类似于信用卡号码,在号码本身中嵌入校验和或验证数字。您必须有一个算法来根据一些初始数据生成一个 pin,这些初始数据可以是一个数字序列。生成的 pin 对于序列中的每个数字必须是唯一的,因此如果您生成 100,000 个 pin 码,它们都必须不同。这样,您不仅可以通过对照数据库检查数字来验证数字,还可以先验证它。

我曾经为此目的写过一些东西,我不能给你代码,但总体思路是这样的:

  • 准备一个12位数的空格
  • 将数字格式化为五位数字(00000 到 99999),并以某种方式沿空间分布。例如,数字 12345 可以扩展为 __3_5_2_4__1。您可以根据它是偶数还是奇数,或 3 的倍数等来改变分配数字的方式。
  • 根据某些数字的值,生成更多的数字(例如,如果第三个数字是偶数,则创建一个奇数并将其放入第一个空位,否则创建一个偶数并将其放入第二个空位,例如_83_5_2_4__1
  • 生成 6 位数字后,您将只有一个空位。您应该始终保留相同的开放空间(例如倒数第二个空间)。您将在该位置放置验证码。
  • 要生成验证数字,您必须对生成的数字执行一些算术运算,例如将奇数位置的所有数字相加并乘以其他数字,然后减去偶数位置的所有数字,最后将所有数字相加数字在一起(您必须根据某些数字的值稍微改变算法)。最后,您有一个验证数字,您将其包含在生成的密码中。

所以现在您可以验证您生成的密码。对于给定的密码,您生成验证数字并与密码中包含的数字进行核对。如果没问题,那么您可以通过执行相反的操作来提取原始数字。

这听起来不太好,因为它看起来像是通过默默无闻的安全性,但这是您可以使用它的唯一方法。有人猜出密码并非不可能,但作为带有验证码的 12 位密码,这将非常困难,因为您必须尝试 1,000,000,000,000 种组合,而您只有 100,000 个有效密码,因此对于那里的每个有效密码是 10,000,000 个无效的。

我应该提一下,这对于一次性密码很有用;一个人只使用一次这些代码之一,例如为预付费电话充电。将这些引脚用作身份验证令牌不是一个好主意,尤其是如果这是对某人进行身份验证的唯一方法(您永远不应该仅通过一条数据对某人进行身份验证;最低要求是用户名+密码)

于 2009-01-21T17:27:49.487 回答
0

您似乎想使用 PIN 码作为用户识别的唯一手段。一个可行的解决方案是使用前五位数字来识别用户,并附加四位数字作为 PIN 码。

如果您不想存储 PIN,可以通过将加密安全哈希(SHA1 或更好)应用于用户编号以及系统范围的密码来计算它们。

于 2009-01-01T10:18:10.267 回答
0

我应该通过某种算法生成此代码吗?

不,这将是可预测的。

还是我应该随机生成它?

是的。使用加密随机生成器,或让用户选择自己的 PIN。

理论上 4 位数字就足够了,因为 ATM 卡发行商设法支持一个非常大的社区(显然,它们不能也不需要是唯一的)。但是,在这种情况下,您应该限制输入 PIN 码的尝试次数,并在银行进行多次尝试后将其锁定。您还应该让用户提供一个用户 ID(在 ATM 的情况下,这实际上是在卡上)。

如果您不想以这种方式限制它们,最好放弃 PIN 的想法并使用标准密码(本质上就是您的 PIN,只是长度非常短且字符集有限)。如果您绝对必须将其限制为数字(因为您有密码键盘或其他东西),那么请考虑将 4 设为(可配置的)最小长度而不是固定长度。

您不应该将 PIN 明文存储在任何地方(例如,加盐并像密码一样对其进行哈希处理),但是鉴于长度短且字符集有限,只要提供一种简单的验证方法,它总是容易受到暴力搜索的攻击.

如果您可以告诉我们更多有关您的要求的信息(这是一个网络应用程序吗?嵌入式系统?等),也可以使用各种其他方案。

于 2009-01-01T10:52:09.607 回答
0

猜测目标用户的 PIN 码与任何有效用户的 PIN 码是有区别的。从您的用例来看,PIN 似乎用于获取对某些资源的访问权限,攻击者可能会使用该资源,而不是特定的用户身份。如果确实如此,您将需要使有效的 PIN 号码在相同数字的所有可能数字中足够稀疏。

正如一些答案中提到的,您需要使您的 PIN 足够随机,无论您是否想从算法生成它。随机性通常通过PIN的熵来衡量。

现在,假设您的 PIN 的熵为N,并且您的系统中有2^M用户(M < N),随机猜测产生有效 PIN 的概率为2^{MN}。(对不起乳胶符号,我希望它足够直观)。然后从那里您可以确定在给定NM的情况下该概率是否足够低,或者根据所需的概率和M计算所需的N。

有多种方法可以生成 PIN,这样您就不必记住生成的每个 PIN。但是您需要一个很长的 PIN 码才能确保其安全。这可能不是你想要的。

于 2009-01-01T13:09:13.573 回答
0

我以前用 PHP 和 MySQL 数据库做过这个。我有一个排列函数,它首先确保能够在开始生成过程之前创建所需代码的数量 - $n,长度为 $l,字符数量为 $c。

然后,我会将每个新代码存储到数据库中,并让它通过 UNIQUE KEY 错误告诉我存在冲突(重复)。然后继续,直到我成功创建了 $n 个代码。您当然可以在内存中执行此操作,但我想保留在 MS Word 邮件合并中使用的代码。所以...然后我将它们导出为 CSV 文件。

于 2009-01-02T05:58:12.493 回答