如何在vaadin中检查密码强度

时间:2013-01-29 20:32:41

标签: java spring vaadin

我在我的项目中使用了vaadin,spring和jpa。我需要检查并通知用户他的密码有多强,并希望在纯java中完成。

你能推荐我最好的方法吗? 如果密码至少包含一个数字等,使用特殊库或仅使用正则表达式检查是否更好?您如何看待?

如果你有任何链接到这个和好的图书馆或教程,请发给我。

2 个答案:

答案 0 :(得分:5)

一般来说,某人的密码强度取决于它的可猜测程度。更复杂的密码不太可猜测。您可以通过将字典攻击或暴力算法猜测密码的可能性与其相关联来估计复杂性。一旦验证密码不是常见密码,您可以通过使用强力猜测密码所花费的时间来估计其复杂性。从这个意义上讲,您可以测量类似随机密码的熵的二进制位数。这可以粗略估计其可猜测性,尽管一位评论者指出,测量复杂性很困难。在我采取的一个安全类中,教师建议一个人应该瞄准至少40位熵,但60被认为是安全的(假设密码不能与随机选择的密码区分开)。因此,密码计的工作是猜测等效随机密码的熵。显然,这里存在很多陷阱,使用已建立的库可以节省大量时间。

每个字符是log10(number_possible_characters)/ log10(2),因此您可以将熵计算为pwd.length() * Math.log10(numPossibleCharacters)/Math.log10(2) - 并且使用26个字符来计算大约4.7位每个字符的熵。

以纯粹科学的方式测量熵并不总是对可猜测性的有效估计,因为密码" abc123"可能看起来和(#计算机,而不是人类)一样好,但人类可以很容易地看到第一个比第二个更容易被猜到。严格来说,熵是衡量真实随机性的标准;虽然我们知道人类不是随机的,但它们可能足够接近我们测量熵作为替代品的随机性,并希望我们的算法测量人类产生的随机性/创造性/不可思议性的类型。因此,这既是技术问题,也是人类行为问题。

如果我没记错的话,我曾经被告知,英文散文(页面上的文字)每个字符只有大约1.5位的熵 - 换句话说,它更容易预测,所以你可以这样做需要大约3倍的密码才能成为"强大的"如果你只输入英文单词,那么如果你输入随机小写的乱码。坦率地说,我认为REQUIRE符号/数字/大写的密码系统是愚蠢的,因此:如果我愿意,我应该能够输入更多的散文。 YMMV。

我们应该通过估算用户可以为他们输入的每个字符选择或可能选择的字符数来开始测量熵。

可能的字符数numPossibleCharacters取决于用户使用的字符集,或者您允许使用的字符集。例如,如果用户键入abc,那么您会假设他们只选择26个可能的字符(每个字符4.7个)。但是,如果他们键入aBc,您可以假设他们从52(小写和大写)中选择(每个字符5.7)。如果他们使用数字,则添加另外10个可能的字符(除非他们似乎只选择明显的数字)。

此外,添加号码作为事后补充的用户倾向于将它们放在密码的开头或结尾。因此,他们更改字符集的次数也可能是密码强度的一个很好的衡量标准。例如," word908"显然不如" w39或#34;当你这样做时,你走出简单的复杂性估计。

如果你使用这种更为宽松的复杂性定义,那么测量密码被任何类型的攻击猜测的可能性要困难得多,尽管你可能会尝试想象一种选择半随机的智能攻击密码以最可猜测和最可能的模式开头。你可能会说每个字符增加的复杂性(熵?)取决于它是否与前一个字符在同一个字符集中,是否与前一个字符相同,或者是否重复了一些明显的字符模式(序列如" 123"或" abc")。

你可能会说从一组字符到另一组字符的每个开关(小写到高位,或数字到符号)本身就是一个随机事件。我们假设我们定义了5个字符集:小写,大写,数字,common_symbols和uncommon_symbols。我们检测到有多少套正在使用中(例如,如果用户输入' 123abc'那么charSetsUsed是2)。然后,我们一次循环一个字符串中的字符。每次用户更改字符集时,我们都会说entropy += log(charSetsUsed)/log(2)。然后,对于每个字符,我们还添加entropy += log(charsInThisCharSet)/log(2)。 [编辑:这不是真正的熵,所以也许你应该把它看作估计的复杂性]

如果您真的想获得技术,可以衡量字符集更改的数量。我们假设密码长度为10个字符。它可以有1到9个设置更改,这是10个选项。然后我们说它们是作为插槽的组合分发的。所以我们这样做:

 log(numChanges)/log(2) + log(combination(totalSlots, usedSlots))/log(2).  

让我们说用户输入aoq35esm42。我们看到他们从一个字符集切换到另一个字符集的3个地方。它是一个10个字符的密码,因此设置更改有9个可能的位置(在两个字符中的任何一个之间出现位置),它们的顺序无关紧要(因此组合/二项式系数/ n选择r):

 log(numChanges)/log(2) + log(combination(9, 3))/log(2).  
 log(3         )/log(2) + log(    84           )/log(2). 
 1.5849625              + 6.3
 7.97727992

所以我们看到我们有近8位的熵基本上说'#34;在他们可以选择改变字符集的所有地方和时间中,有大约8个随机位或2 ^ 8他们本可以做什么的可能性"。如果我们然后根据每个字符的子集计算每个字符的熵,并选择每个变化使用的子集,那么我们可能会像这样添加熵(如果我在数学上犯了错误,请纠正我):

  • aoq35esm42有6个小写字母字符,6 * log(26)/ log(2),= 28.2026383
  • aoq35esm42有4个数字字符,用于4 * log(10)/ log(2),= 13.2877124
  • aoq35esm42有3个字符集更改和2个字符集,用于3 * log(2)/ log(2),= 3
  • 之前,我们计算了charset变化的位置为7.97727992位熵
  • 我们愚蠢地假设总得分大约为78,所以它是一个很好的密码。

使用apache commons MathUtils.binomialCoefficientDouble()函数计算组合。

此外,如果密码包含字典单词,则会将其视为弱密码。因此,如果您可以扫描字典,您可能会假设(猜测)这些字符应该被测量为英文散文,每个字符有1.5位熵。但是,您不希望将密码暴露给数据库查询(可能会记录在哪里),所以最好的办法是猜测是否有英文单词(祝你好运),就像假设(相当糟糕)任何包含元音的3-5个单个字母的字母组,是一个英文单词。或者,您可以构建一个最常见的英语音节字典,这可能更容易存储在内存中。或者,您可以放弃并假设您的用户无论如何都会对系统进行游戏,以使其密码更难忘。

但是,如果您确定准确无误,则可以在安全存储器中存储英文单词的内存数据库。

所有这些加起来相当复杂的算法仍然可能是不完整的。您可能应该使用相对简单的计算,或者使用其他人已经编写过的库。

''安全存储''

计算密码安全性的方法并没有真正解决一个完全不同的问题:保持密码安全,因为它通过网络或客户端内存。我不是这里的专家,但我已经读得足够知道要小心并做我的功课。至少,我会使用https并强烈考虑使用浏览器的本机密码输入字段。这是避免推出自己的技术,而是使用图书馆的另一个原因(只要你可以告诉他们他们做了比你能管理的更多的功课;我不知道我是否相信技术,除非我调查它)。此外,您绝不应以明文形式存储密码,而应使用单向加密/散列。给你的密码加盐,然后使用安全散列算法(不是MD5;或者更喜欢SHA2?)对它们进行哈希处理,可能会多次重新进行重新加沙和重新加盐(以增加字典攻击的成本)。通常情况下,图书馆会为您处理此类事情,即使他们没有测量密码强度;我知道C#或.NET有专门针对salting,散列和迭代的库;我可能还没有提到其他问题 - 请记住密码强度只是安全链中的一个链接。

答案 1 :(得分:4)

在纯java中,您可以使用VT Password来检查密码强度。可从Maven Central获得:

<dependencies>
  <dependency>
      <groupId>edu.vt.middleware</groupId>
      <artifactId>vt-password</artifactId>
      <version>3.1.1</version>
  </dependency>
<dependencies>