参考 - 密码验证

ctw*_*els 33 regex authentication passwords validation

很多时候,问题(特别是标记)会询问验证密码的方法.用户通常会寻求密码验证方法,包括确保密码包含特定字符,匹配特定模式和/或遵守最小字符数.这篇文章旨在帮助用户找到适当的密码验证方法,而不会大大降低安全性.

所以问题是:如何正确验证密码?

ctw*_*els 61

为什么密码验证规则不好?

我们自己的Jeff Atwood(Coding Horror的博主和Stack Overflow和Stack Exchange的联合创始人)在2017年3月写了一篇关于密码规​​则的博客,题为密码规则是废话.如果您还没有阅读这篇文章,我会敦促您这样做,因为它极大地反映了这篇文章的意图.

如果您从未听说过NIST(美国国家标准与技术研究院),那么您可能没有对您的项目使用正确的网络安全方法.在这种情况下,请查看他们的数字身份指南.您还应该及时了解网络安全的最佳实践.NIST特刊800-63B(修订版3)提到了以下有关密码规则的内容:

验证者不应该对记忆的秘密施加其他组成规则(例如,要求不同字符类型的混合或禁止连续重复的字符).

甚至Mozilla关于表单数据验证的文档也很有趣于密码规则(这里的页面存档):

"您的密码长度必须介于8到30个字符之间,并且包含一个大写字母,一个符号和一个数字"(严肃地说?)

如果您为密码强加组合规则会发生什么?您限制了潜在密码的数量并删除了与您的规则不符的密码排列.这允许黑客确保他们的攻击也一样!"雅但是有一个千万亿(1,000,000,000,000,000或1x10 15)密码排列":25-GPU集群在<6小时内破解每个标准Windows密码(95 8 = 6,634,204,312,890,625~6.6x10 15密码).

XKCD

如何验证密码?

1.不要创建自己的身份验证

停止完全要求密码,让人们使用Google,Facebook,Twitter,Yahoo或任何其他有效的互联网驱动程序许可证登录.最好的密码是您不必存储的密码.

资料来源:杰夫阿特伍德的密码太短了.

2.创建自己的身份验证

如果您真的必须创建自己的身份验证方法,至少应遵循经过验证的网络安全方法.以下两节(2.1和2.2)取自当前的NIST出版物,第5.1.1.2记忆秘密验证器.

2.1.遵循PROVEN网络安全方法

NIST说你应该:

  • 要求用户选择的记忆秘密长度至少为8个字符.
    • Jeff Atwood建议密码对于普通用户应至少为10个字符,对于具有更高权限的用户(即管理员和版主)至少应为15个字符.
  • 允许用户选择的记忆密码长度最多64个字符或更多.
    • 理想情况下,你甚至不应该对此加上限制.
  • 允许所有打印ASCII(包括空格字符)和Unicode.
    • 出于长度要求的目的,每个Unicode代码点应计为单个字符.
  • 将预期机密与包含已知常用,预期或受损的值的列表进行比较.例如:
    • 从先前的违规语料库获得的密码.
    • 字典单词.
    • 重复或连续字符(例如aaaaaa,1234abcd)
    • 特定于上下文的单词,例如服务名称,用户名及其派生词.
  • 向订户提供指导,例如密码强度计.
  • 实施速率限制机制,有效地限制可以在订户帐户上进行的失败认证尝试次数(请参阅速率限制(限制)).
  • 如果有证据证明验证者妥协,则强制进行更改.
  • 允许索赔人在输入记忆秘密时使用粘贴功能(便于使用密码管理器,这通常会增加用户选择更强记忆秘密的可能性).

2.2.请勿使用本节中的任何方法!

同一出版物还指出你不应该:

  • 截断这个秘密.
  • 允许订户存储未经身份验证的索赔人可以访问的提示.
  • 在选择记忆的秘密时,提示订阅者使用特定类型的信息(例如"您的第一只宠物的名字是什么?").
  • 对记忆的秘密施加其他组成规则(例如,要求不同字符类型的混合或禁止连续重复的字符).
  • 要求记忆的秘密可以任意改变(例如定期).

有很多网站在那里解释如何创建"正确的"密码验证表格:其中大多数都已过时,不应使用.

3.使用密码熵

在继续阅读本节之前,请注意本节的目的不是为您提供推出自己的安全方案所需的工具,而是为您提供有关当前安全方法如何验证密码的信息.如果您正在考虑创建自己的安全方案,那么您应该三思而后行,并从StackExchange的安全社区阅读本文.

3.1.密码熵概述

在最基本的级别,密码熵可以使用以下公式计算:

E = log2(R ^ L)

在上面的公式中:

  • Ë 代表密码熵
  • [R是唯一字符池中的字符数
  • 大号 是密码中的字符数

这意味着 R 1大号代表可能的密码数量; 或者,就熵而言,耗尽所有可能性所需的尝试次数.

不幸的是,这个公式没有考虑的是:

  • 通用密码:即Password1,admin
  • 名称:即John,Mary
  • 常用词:即在英语中the,I
  • 反转/反转词:即drowssap(密码反向)
  • 字母替换(又名leet):即 P@$$w0rd

为这些额外考虑添加逻辑提出了巨大挑战.有关可添加到项目中的现有包,请参阅3.2.

3.2.现有密码熵项目

在撰写本文时,用于估计密码强度的最着名的现有库是Dropbox(GitHub上的一个开源项目)的zxcvbn.它已被改编为支持


做错了

但是,我知道每个人都有不同的要求,有时候人们想要做错事.对于那些符合此标准的人(或者没有选择并且已经向本节提供了更多内容以及更多内容但他们拒绝更新其方法)至少允许使用Unicode字符.将密码字符限制为特定字符集的那一刻(即确保存在小写ASCII字符a-z或指定用户可以输入或不能输入的字符!@#$%^&*()),您只是在寻找麻烦!

PS永远不要相信客户端验证,因为它很容易被禁用.这意味着对于那些尝试使用 STOP验证密码的人.有关详细信息,请参阅JavaScript:客户端与服务器端验证.

以下正则表达式模式在所有编程语言中都不起作用,但它在许多主要编程语言中都有效().请注意,以下正则表达式可能无法使用您的语言(甚至语言版本),您可能需要使用替代方法(即:请参阅匹配Unicode属性的Python正则表达式).有些编程语言甚至有更好的方法来检查这样的事情(即使用密码验证插件用于),而不是另起炉灶.使用,如果在Javascript + Unicode正则表达式中讨论使用XRegExp插件或其他一些Unicode类转换工具,则以下内容有效.

如果您需要阻止输入控制字符,则可以在使用该模式发生正则表达式匹配时提示用户[^\P{C}\s].这将仅匹配不是空格字符的控制字符 - 即水平制表符,换行符,垂直制表符.

以下正则表达式确保8个字符长度的密码中至少存在一个小写,大写,数字和符号:

^(?=\P{Ll}*\p{Ll})(?=\P{Lu}*\p{Lu})(?=\P{N}*\p{N})(?=[\p{L}\p{N}]*[^\p{L}\p{N}])[\s\S]{8,}$
Run Code Online (Sandbox Code Playgroud)
  • ^ 在行的开头断言位置.
  • (?=\P{Ll}*\p{Ll}) 确保至少存在一个小写字母(在任何脚本中).
  • (?=\P{Lu}*\p{Lu}) 确保至少存在一个大写字母(在任何脚本中).
  • (?=\P{N}*\p{N}) 确保至少存在一个数字字符(在任何脚本中).
  • (?=[\p{L}\p{N}]*[^\p{L}\p{N}]) 确保存在至少一个不是字母或数字的字符(在任何脚本中).
  • [\s\S]{8,} 匹配任何字符8次或更多次.
  • $ 断言该行末尾的位置.

请自行决定使用上述正则表达式.你被警告了!