基于规则评分的密码强度检测算法分析及实现(Javascript) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
iFat3
V2EX    Javascript

基于规则评分的密码强度检测算法分析及实现(Javascript)

  •  1
     
  •   iFat3 2018-03-20 18:56:27 +08:00 2670 次点击
    这是一个创建于 2840 天前的主题,其中的信息可能已经有所发展或是发生改变。

    简言

    用正则表达式做用户密码强度的通过性判定,过于简单粗暴,不但用户体验差,而且用户帐号安全性也差。那么如何准确评价用户密码的强度,保护用户帐号安全呢?本文分析介绍了几种基于规则评分的密码强度检测算法,并给出了相应的演示程序。大家可以根据自己项目安全性需要,做最适合于自己的方案选择。

    密码强度检测算法

    1 方案 1 (简单)

    方案 1 算法通过密码构成分析,结合权重分派,统计得出密码强度得分。得分越高,表示密码强度越大,也就越安全。方案 1 算法思想简单,实现容易。

    1.1 方案 1 评分标准

    一、密码长度:

    • 5 分: 小于等于 4 个字符
    • 10 分: 5 到 7 字符
    • 25 分: 大于等于 8 个字符

    二、字母:

    • 0 分: 没有字母
    • 10 分: 全都是小(大)写字母
    • 20 分: 大小写混合字母

    三、数字:

    • 0 分: 没有数字
    • 10 分: 1 个数字
    • 20 分: 大于 1 个数字

    四、符号:

    • 0 分: 没有符号
    • 10 分: 1 个符号
    • 25 分: 大于 1 个符号

    五、奖励:

    • 2 分: 字母和数字
    • 3 分: 字母、数字和符号
    • 5 分: 大小写字母、数字和符号

    1.2 方案 1 等级划分

    根据密码评分,将密码划分成以下 7 个等级:

    • >= 90: 非常安全( VERY_SECURE )
    • >= 80: 安全( SECURE )
    • >= 70: 非常强( VERY_STRONG )
    • >= 60: 强( STRONG )
    • >= 50: 一般( AVERAGE )
    • >= 25: 弱( WEAK )
    • >= 0: 非常弱( VERY_WEAK )

    该评分标准及等级划分,实际使用时,可小做调整,但不建议做大的变动。

    1.3 方案 1 演示程序

    演示程序

    1.4 方案 1 测试分析

    // 评分 25,纯小写字母无法通过验证 console.log("aaaaaaaa".score()); // 评分 45,纯数字无法通过验证 console.log("11111111".score()); // 评分 47,小写+数字无法通过验证 console.log("aa111111".score()); // 评分 45,小写+大写无法通过验证 console.log("aaaaAAAA".score()); // 评分 50,4 位密码不可能通过验证 console.log("11!!".score()); // 评分 70,5 位密码可通过验证 console.log("0aA!!".score()); // 评分 67,小写+大写+数字可通过验证( 8 位) console.log("aA000000".score()); // 评分 70,数字+符号可通过验证 console.log("000000!!".score()); 

    从以上测试结果中,我们可以看出算法是十分的有效的,基本能够保证密码具有一定的安全性。但是存在的问题也很明显,其中最主要的问题是对重复或连续的字符评分过高。以测试用例中最后一个为例: 000000!! 可以得到 70 分,但显然并不是一个非常强壮的密码。

    另外,方案 1 最高可以得到 95 分,也就是说没有 100 分(绝对安全)的密码,这一点也是很有智慧的设计。

    2 方案 2

    针对方案 1 中的不足,方案 2 中引入了减分机制。对于重复出现,连续出现的字符给予适当的减分,以使得密码评分更准确。同时在方案 2 中密码的评分基数及计算过程都十分的复杂,要想理解其中每一步的含义,请保持足够的耐心。

    2.1 方案 2 加分项

    一、密码长度:

    • 公式 :+(n*4),其中 n 表示密码长度

    二、大写字母:

    • 公式:+((len-n)*2),其中 n 表示大写字母个数,len 表示密码长度

    三、小写字母:

    • 公式:+((len-n)*2),其中 n 表示小写字母个数,len 表示密码长度

    四、数字:

    • 公式:+(n*4),其中 n 表示数字个数
    • 条件:满足 n < len,才能得到加分,len 表示密码长度

    五、符号:

    • 公式:+(n*6),其中 n 表示符号个数

    六、位于中间的数字或符号:

    • 公式:+(n*2),其中 n 表示位于中间的数字或符号个数

    七、最低条件得分:

    • 公式:+(n*2),其中 n 表示满足的最低条件条目数
    • 条件:只有满足最低条件,才能得到加分

    其中最低条件的条目如下:

    • 1.密码长度不小于 8 位
    • 2.包含大写字母
    • 3.包含小写字母
    • 4.包含数字
    • 5.包含符号

    最低条件要求满足条目 1 并至少满足条目 2-5 中的任意三条。

    2.2 方案 2 减分项

    一、只有字母:

    • 公式:-n,其中 n 表示字母个数

    二、只有数字:

    • 公式:-n,其中 n 表示数字个数

    三、重复字符数(大小写敏感):

    该项描述复杂,具体计算方法见如下示例程序:

    var pass = "1111aaDD"; //示意密码 var repChar = 0; var repCharBOnus= 0; //得分 var len = pass.length; for(var i = 0; i < len; i++) { var exists = false; for (var j = 0; j < len; j++) { if (pass[i] == pass[j] && i != j) { exists = true; repCharBonus += Math.abs(len/(j-i)); } } if (exists) { repChar++; var unqChar = len - repChar; repCharBOnus= (unqChar) ? Math.ceil(repCharBonus/unqChar) : Math.ceil(repCharBonus); } } 

    四、连续大写字母:

    • 公式:-(n*2),其中 n 表示连续大写字母出现的次数
    • 举例:如输入 AUB,则 n=2

    五、连续小写字母:

    • 公式:-(n*2),其中 n 表示连续小写字母出现的次数
    • 举例:如输入 aub,则 n=2

    六、连续数字:

    • 公式:-(n*2),其中 n 表示连续数字出现的次数
    • 举例:如输入 381,则 n=2

    七、正序或逆序字母:

    • 公式:-(n*3),其中 n 表示连续发生的次数
      • 正序或逆序是指字母表中的顺序
      • 不区分大小写
    • 条件:只有连续 3 个字母或以上,才会减分,
    • 例 1:如输入 ABC,则 n=1
    • 例 2:如输入 dcBA,则 n=2

    八、正序或逆序数字:

    • 公式:-(n*3),其中 n 表示连续发生的次数
    • 条件:只有连续 3 个数字或以上,才会减分
    • 例 1:如输入 123,则 n=1,
    • 例 2:如输入 4321,则 n=2
    • 例 3:如输入 12,则不会减分

    九、正序或逆序符号:

    • 公式:-(n*3),其中 n 表示连续发生的次数
    • 条件:只有连续 3 个符号或以上,才会减分

    2.3 方案 2 等级划分

    根据密码评分,将密码划分成以下 5 个等级:

    • >= 80: 非常强( VERY_STRONG )
    • >= 60: 强( STRONG )
    • >= 40: 好( GOOD )
    • >= 20: 弱( WEAK )
    • >= 0: 非常弱( VERY_WEAK )

    2.4 方案 2 演示程序

    演示程序

    2.5 方案 2 测试分析

    // 评分 0 console.log("11111111".score()); // 评分 2 console.log("aa111111".score()); // 评分 38 console.log("000000!!".score()); // 评分 76 console.log("Asdf2468".score()); // 评分 76 console.log("Mary2468".score()); // 评分 60 console.log("@dmin246".score()); 

    从以上测试可以看出方案 2 较方案 1 有了比较大的改进和提升,尤其是对连续或重复字符上表现出色。但是方案 2 也存在明显的不足,主要缺点包括对人名( Mary )、单词( Story )、键盘上相连的键( Asdf )、L33T (@dmin )没法识别。

    L33T:是指把拉丁字母换成数字或是特殊符号的书写形式。例如把 E 写成 3、A 写成 @ 、to 写成 2、for 写成 4。

    3 方案 3 zxcvbn

    3.1 简要说明

    针对方案 2 中的不足,引入了方案 3,进一步的提长密码强度。方案 3 完全引入一个第三方检验工具 zxcvbn。

    zxcvbn 是一个受密码破解启发而来的密码强度估算器。它通过模式匹配和保守估计,大概可以识别大约 30K 左右的常规密码。主要基于美国人口普查数据,维基,美国电影,电视流行词以及其它一些常用模式,像日期,重复字符,序列字符,键盘模式和 L33T 会话等。

    从算法的设计思想上,该方案完全秒杀基于构成的统计分析方法(前两种方法)。同时 zxcvbn 支持多种开发语言。因其模式的复杂及字典的存在,当前版本的 zxcvbn.js 大约有 800 多 K。

    要了解项目的详情及算法见 zxcvbn 官网:

    github zxcvbn

    3.2 方案 3 演示程序

    演示程序

    以上是三胖对密码强度检测算法和方案的理解和分析,不足之处还请大家多多指正!

    原文链接

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3425 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 05:03 PVG 13:03 LAX 21:03 JFK 00:03
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86