你的密码真的安全吗?
作者:Eric Hodges
在“你的密码真的安全吗?”的比赛中,参赛者必须编写一个脚本,根据提供的标准来判断密码的强度。
比赛场景
在当今时代,人们被鼓励在任何需要创建或更改密码的时候使用“强”密码。这是一个很好的建议,但它也引出了几个问题:1)究竟什么是强密码,以及 2)同样地,我们如何判断一个给定的密码是否安全?第五场比赛旨在帮助你回答这两个问题。
在本场比赛中,你将创建一个可以判断密码“强度”的脚本。密码强度将通过以下检查来确定。脚本必须完成以下所有操作
确保密码不是一个真实的单词。 密码 rhubarb 未通过此测试,因为 rhubarb 是一个真实的单词。要确定一个单词是否为真实单词,请始终使用 WordList.txt 文件,这是一个官方单词列表,作为脚本游戏参赛者包的一部分提供。(请确保将此文件放在 C:\Scripts 文件夹中。)请注意,此检查应区分大小写:rhubarb 是一个真实的单词,RHUBARB、rhUBArb 等也是如此。
确保密码去掉最后一个字母后不是一个真实的单词。 例如,密码 rhubarb5 未通过此测试,因为如果删除最后一个字母,则剩余的字符串值 - rhubarb - 是一个真实的单词。此检查应区分大小写。
确保密码去掉第一个字母后不是一个真实的单词。 例如,密码 @rhubarb 未通过此测试,因为如果删除第一个字母,则剩余的字符串值 - rhubarb - 是一个真实的单词。此检查应区分大小写。
确保密码不是简单地用 0(零)替换字母 o(大写字母 O 或小写字母 o)。 例如,密码 t00lb0x 未通过此测试。为什么?因为如果将每个零替换为字母 O,你将得到一个真实的单词:toolbox。
确保密码不是简单地用 1(一)替换字母 l(大写字母 L 或小写字母 l)。 例如,密码 f1oti11a 未通过此测试。为什么?因为如果将每个一替换为字母 L,你将得到一个真实的单词:flotilla。
确保密码长度至少为 10 个字符,但不超过 20 个字符。 密码 rhubarb 未通过此测试,因为它只有 7 个字符。
确保密码至少包含一个数字(0 到 9 之间的数字)。 密码 rhubarb%$qwC 未通过此测试,因为它不包含数字。
确保密码至少包含一个大写字母。 密码 rhubarb 未通过此测试,因为它没有大写字母。
确保密码至少包含一个小写字母。 密码 RHUBARB 未通过此测试,因为它没有小写字母。
确保密码至少包含一个符号。 这可以是任何既不是大写字母也不是小写字母或数字的字符;包括但不限于符号 ~、@、#、$、% 和 ^。
确保密码不包含四个(或更多)连续的小写字母。 密码 rhubARB 未通过此测试,因为它包含四个连续的小写字母 (rhub)。
确保密码不包含四个(或更多)连续的大写字母。 密码 rHUBArb 未通过此测试,因为它包含四个连续的大写字母 (HUBA)。
确保密码不包含任何重复字符。 密码 rhubarb 未通过此测试,因为它有两个 r 和两个 b。此检查应区分大小写:A 和 a 被视为不同的字母。因此,密码 Oboe 不会未通过此特定测试。
注意:是的,要记住的事情很多,不是吗?为了帮助您跟踪所有内容,我们在参赛者资料包中包含了一个清单 (Password_Checklist.doc)。
要成功完成此活动,您的脚本必须接受可能的密码作为命令行参数并对该密码进行评级。例如,如果您想评估密码 rhubarb33! 的强度,您可以使用类似于以下命令的命令启动脚本
myscript.pl rhubarb33!
您的脚本应以密码分数 13 开始;这意味着通过每项检查的密码的最终分数为 13。从参数集合中检索密码后(我们将一次只向脚本传递一个密码),您的脚本应该针对该密码运行前面提到的每项检查。如果密码通过了给定的检查(例如,检查密码是否是实际单词的测试),则脚本应该简单地继续进行下一个测试。这应该很容易。
现在,如果密码未通过给定的检查会发生什么?例如,密码 rhubarb 将未通过“密码不能有四个连续的小写字母”的测试。在这种情况下,脚本必须做两件事
从密码分数中减去 1。例如,如果密码分数为 11 并且脚本未通过四个连续小写字母的检查,则密码分数应降低到 10
回显一条消息,说明建议的密码未通过此测试。例如,在这种情况下,您将回显一条类似于以下内容的消息
Four consecutive lowercase letters in password.
完成所有检查后,脚本应使用以下等级对密码进行评级
6 分或更低的分数表示弱密码。
7、8、9 或 10 分表示中等强度的密码。
11 分或更高的分数表示强密码。
您应该回显分数和密码等级。例如
A password score of 4 indicates a weak password.
例如,以下是您在检查密码 rhubarb33! 时应该获得的输出类型
No uppercase letters in password. Four consecutive lowercase letters in password. Duplicate letters in password. A password score of 10 indicates a moderately-strong password.
这就是你需要做的全部。
use v6; sub MAIN(Str :$pw = "", Bool :$verbose = False) { my $password = $pw || prompt("Enter password to test: "); my $input-file = $*SPEC.catdir($*PROGRAM-NAME.IO.dirname, "wordlist.txt"); my %dict = (($input-file.IO.lines.grep: {.chars > 6}) X 1).flat; say "Testing strength of password '$password'" if $verbose; my $score = 13; if %dict{$password} :exists { $score--; say "Password matched dictionary"; } if %dict{$password.substr(0, $password.chars -1 )} :exists { $score--; say "Password minus last char is in dictionary"; } if %dict{$password.substr(1,$password.chars-1)} :exists { $score--; say "Password minus first char is in dictionary"; } my $test = $password; $test.subst(/0/, "o"); if %dict{$test} :exists { $score--; say "Password replaces 'o' with '0'"; } $test = $password; $test.subst(/1/, "i"); if %dict{$test} :exists { $score--; say "Password replaces 'i' with '1'"; } if $password.chars == none(10..20) { $score--; say "Password is too short (less than 10) or too long (more than 20)" } unless $password ~~ rx/<[A..Z]>/ { $score--; say "No uppercase letters in password."; } if $password ~~ rx/<[a..z]> ** 4..*/ { $score--; say "Four consecutive lowercase letters in password."; } my @chars = $password.split(''); my %letter-frequency; for @chars -> $char { if $char ~~ rx/<[a..zA..Z]>/ { %letter-frequency{$char} = %letter-frequency{$char}:exists ?? ++%letter-frequency{$char} !! 1; } } if %letter-frequency.values.any > 1 { $score--; say "Duplicate letters in password."; } say "'$password' scored $score" if $verbose; say ""; given $score { when $_ <= 6 { say "A password score of $score indicates a weak password."; } when 7 < $_ <= 10 { say "A password score of $score indicates a moderately-strong password."; } when $_ >= 11 { say "A password score of $score indicates a strong password."; } } }