带条件的随机密码生成

5
我正在开发一个随机密码生成器,以创建符合特定条件的密码,包括但不限于以下内容:
  • 最小长度:必须至少包含8个字符
  • 小写字母:必须包含小写字母(从一组中选择,以避免出现可以被误认为是数字的字符)
  • 大写字母:必须包含大写字母(同样是从一组中选择的)
  • 数字:必须包含数字
什么是确保生成的密码满足所有这些条件的最佳算法方法?
我不需要完整的解决方案,只需要一些好的想法和指导。

http://www.texamples.com/how-to-generate-random-passwords-in-java/ 这可能会有所帮助。 - brainless
不确定这是否是个好主意。强制规定像“2+”位数的限制,可能会使密码变得不那么“随机”,而不是更随机/更好。 - EML
3个回答

6

1) 随机生成一个数字L,它将是您的密码的确切长度。也就是说,生成的数字应大于8。
2) 随机生成一个数字LL,它将是小写字母的数量。LL必须在[1..L-2]范围内。
3) 随机生成一个数字LU,它将是大写字母的数量。必须在[L-LL-1..1]范围内。
4) LD = L-LL-LU是大写数字的数量。
5) 随机生成LL个小写字母,LU个大写字母和LD个数字,并将它们保存在列表(数组)中。
6) 随机洗牌数组。

希望对您有所帮助。


1
+1 我会补充一下,一个好的洗牌算法并不是简单的。这是一个链接,其中包含了一个很好的带伪代码的算法:http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle - xanatos
@xantos:或者,如果使用C ++,我们可以使用std :: random_shuffle()方法 :) - Armen Tsirunyan
我喜欢它。但为什么不将L固定在8上?这是最容易记住的长度,同时也满足要求。 - dana
5
“随机生成”背后隐藏着一些复杂性。如果使用均匀分布的随机数,生成的密码将不能在符合要求的所有密码集中均匀分布。例如,在一个8字符的密码中,平均会得到2.25个数字,而使用@dana的解决方案,则会得到1.69个数字。 - aaz

4
  • 创建一个包含a-z、A-Z、0-9字符数组(减去可能会引起混淆的字符)
  • 从数组中随机选择8个字符进行连接
  • 测试结果以查看是否满足要求
  • 如果不满足条件,重新开始

该算法通常在前几次迭代中就可以成功,并且无需实现洗牌算法。


2
当然可以!它也没有隐藏的偏见。值得注意的是,这个算法以很高的概率迅速终止(在找到可接受解决方案之前的预期尝试次数为1.4)。很傻,我在编写我的代码时没有注意到你的解决方案(相同的解决方案,但我假设随机函数生成0x00-0xFF的随机字节,并没有费心去修复范围)。 - Thomas M. DuBuisson

1

有一种替代方案可以取代Armen提出的精确构建方法。如果您的条件可以高概率地满足,则:

  • 获取一个无限长度的随机字符串(流)
  • 惰性过滤可接受的字符(例如:大写字母||小写字母||数字)
  • 在流上移动所需长度的窗口,当窗口属性符合要求时接受。

在惰性语言中,这只需要大约6行非样板代码,不需要任何洗牌。

编辑:是的,步进窗口就像评论中所说的那样,而不是滑动窗口。谢谢!


2
滑动窗口还是步进窗口?如果你滑动,会导致密码分布偏向于结尾较少出现的字符类别。比如你想要2个字符的密码。数字比字母出现频率低,所以一个典型的流看起来像abcd5efg...。当你滑动窗口时,你会拒绝abbccd并接受d5。数字更可能出现在第二个位置,因为一旦它滑到该位置,密码就变得可接受了。 - aaz
你不应该滑动窗口,而是测试所需长度的离散块:loop input = let (s,r) = splitAt len input in if strProp s then s else loop r。根据草稿计算,您应该期望测试1.4个可能的密码才能获得有效密码(对于8个字符,因此生成密码平均消耗47个随机字节)。 - Thomas M. DuBuisson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接