我写了这个脚本,但是[:alnum:]
不起作用。有人能帮忙吗?
echo -n "Enter a password : "
read password
LEN=$(echo ${#password})
if [ $LEN -lt 10 ]; then
echo "$password is smaller than 10 characters"
else
if ! [ -z `echo $password | tr -d "[:alnum:]"` ]; then
echo "$password is a weak password"
else
echo "$password is a strong password"
fi
fi
echo
答案1
如果您确实想检查密码强度,您应该使用包cracklib-check
中的cracklib-runtime
功能(应该默认安装):
$ echo foo | cracklib-check
foo: it is WAY too short
$ echo foobar | cracklib-check
foobar: it is based on a dictionary word
$ echo foobared | cracklib-check
foobared: it is based on a dictionary word
$ echo foobared123 | cracklib-check
foobared123: it is too simplistic/systematic
$ echo '!'foobared123 | cracklib-check
!foobared123: OK
答案2
表面问题
您的脚本存在一些问题。如果密码包含多个特殊字符,它会中断。尝试输入以下内容:
a space
two spaces
a * star ← try this one in different directories
bbbbbbbbbb ← try this one in a directory containing a file called a
endswithabackslash\
读为什么我的 shell 脚本会因空格或其他特殊字符而阻塞?. 全部。除非您完全理解,否则不要编写与安全有丝毫关系的任何 shell 脚本。
哦,[:alnum:]
效果很好。您可能想用if [ -z …
或if ! [ -n …
来代替if ! [ -z …
。
密码强度无所谓
“密码强度”这个概念是一个神话。这个神话被很多网站传播,但它仍然是一个神话。密码强度根本就不存在,只有密码生成过程。
密码中包含特殊字符并不会增加密码强度。密码是在易记性和易破解性之间的折衷,并且特殊字符会使密码更难记住,但不会更难破解,正如分析的那样Security Stack Exchange 上的这个主题(短篇小说,数学,一些补充— 练习:这个错误答案,哪些部分完全忽略了事实?)。特殊字符使密码更强大的想法是基于这样的假设:编写密码破解程序的人都是白痴。猜猜看:他们不是。破解密码可以赚钱,所以你可以打赌有人会投资破解密码。
那么我应该如何选择密码呢?
随机如果您选择密码的方法不包含随机源(使用计算机,或者如果您喜欢老式方法,可以使用掷骰子),那么它是不行的。
骰子软件是一种流行的选择,但任何遵循XKCD 模式— 从某本字典中随机挑选多个“单词” — 很好。
正确的脚本
#!/bin/sh
echo -n "Enter a password : "
IFS= read -r password
LEN=${#password}
if [ "$LEN" -lt 10 ]; then
printf "%s is smaller than 10 characters\n" "$password"
fi
if [ -z "$(printf %s "$password" | tr -d "[:alnum:]")" ]; then
printf "%s only contains ASCII letters and digits\n" "$password"
else
printf "%s contains characters other than ASCII letters and digits\n" "$password"
fi
这种方式使用tr
会让事情变得过于复杂。shell 完全能够检查字符串是否包含某个特定集合中的字符。
#!/bin/sh
echo -n "Enter a password : "
IFS= read -r password
LEN=${#password}
if [ "$LEN" -lt 10 ]; then
printf "%s is smaller than 10 characters\n" "$password"
fi
case "$password" in
*[![:alnum:]]*)
printf "%s contains characters other than ASCII letters and digits\n" "$password";;
*)
printf "%s only contains ASCII letters and digits\n" "$password";;
esac
(请注意ASCII字母和数字对于 Ubuntu 来说是正确的/bin/sh
,但在 bash 中[:alnum:]
包含当前语言环境的所有字母和数字,而不仅仅是 ASCII 字母和数字。)
答案3
对我来说,这很像 XY 问题。永远不要编写自己的密码处理工具。至少您在这里没有处理密码存储,但您的代码首先让我想到的是,我可以输入一个全数字密码,并将其视为“强密码”(而实际上它比全字母密码弱得多)。如果您继续采用这种安全/密码处理方法,您迟早会失败,而且一旦失败,后果将不堪设想。
正确的解决方案是使用外部库或辅助应用程序来确定密码强度(并执行其他与密码相关的任务)。如今,大多数 Linux 系统都具有 PAM,可以为您以安全的方式执行所有与身份验证相关的任务(作为奖励,除了密码之外,您还可以获得对其他身份验证方法的支持,具体取决于用户的系统配置方式),并且 muru 已经建议使用辅助应用程序来确定密码强度。
答案4
如果你想要一个好的方法来创建密码
看
您的问题:如何检查密码强度?
您可以只检查密码的某些方面,或者使用针对每种方法的特定工具来创建密码或使用一般的暴力破解方法(如果攻击者不知道该方法)。
Shellscriptpwdcheck
使用cracklib-check
#!/bin/bash
# setting variables
usage="Use 4 words chosen randomly, see this link:
https://security.stackexchange.com/questions/6095/xkcd-936-short-complex-password-or-long-dictionary-passphrase"
minlen=20 # can be modified here
short="is shorter than $minlen characters"
goodmix="is long enough"
badmix="is too short
$usage"
separator="-------"
# checking parameter
if [ "$1" == "-h" ] || [ "$1" == "--help" ] || [ $# -gt 1 ]; then
echo "${0##*/} uses 'cracklib-check'"
echo "----------------------------------------------------------------"
echo "Usage: $0 CandidateContaining4DifferentWords"
echo "Example: $0 At-least-$minlen-char"
echo " $0 'Should.be.selected.via.*random*.process'"
echo " $0 'Single-quote-for-1-special-character!'"
echo " $0 'FindPatternByDigitalTest123'"
echo " $0 'Provoke1pattern2search3by4separating5words'"
echo "$usage"
exit
elif [ $# -eq 0 ]; then
echo "$usage"
echo "----------------------------------------------------------------"
read -p "Enter a password : " password
elif [ $# -eq 1 ]; then
password="$1"
fi
# checking and installing if necessary
which cracklib-check > /dev/null
if [ $? -eq 1 ]; then
read -p "Do you want to install 'cracklib-runtime' to get 'cracklib-check'? (y/N) " ans
if [ "$ans" == "y" ]; then
sudo apt-get update && sudo apt-get install cracklib-runtime
fi
fi
if [ ${#password} -lt $minlen ]; then
result="$short"
else
result="$goodmix"
case "$password" in
*[![:alnum:]]*)
alnm="'$password' contains characters other than ASCII letters and digits";;
# result="$badmix";;
*)
alnm="$password contains only ASCII letters and digits";;
esac
fi
echo "Test 1 - size&mix: '$password' $result"
test ${#password} -lt $minlen || echo "$alnm"
if [ "$result" == "$badmix" ] || [ "$result" == "$short" ]; then
total="is bad"
else
total='is good'
fi
echo "$separator"
echo "Test 2 - lexicon: '$password'"
sed -e 's/[0-9]/123\n/g' -e 's/$//' -e 's/[§!@£$€#¤%/()=?*,;.:_-~ ]/123\n/g' -e 's/$/123/g' \
<<< "$password" | LANG=C cracklib-check |sed 's/123: /: /'| \
grep 'it is based on a dictionary word'
if [ $? -ne 0 ]; then
echo 'no comment'
fi
echo "$separator"
echo "Test 3 - digital: '$password'"
sed -e 's/[[:alpha:]]//g' -e 's/[§!@£$€#¤%/()=?*,;.:_-~ ]//g' -e 's/$/xyz/' \
<<< "$password" | LANG=C cracklib-check |sed 's/xyz: /: /'| \
grep 'it is too simplistic/systematic'
if [ $? -eq 0 ]; then
total='is bad'
else
echo 'is good'
fi
echo "$separator"
echo "Test 4 - cracklib-check: '$password'"
LANG=C cracklib-check <<< "$password" | tee /dev/stderr | grep ': OK' > /dev/null
if [ $? -eq 0 ]; then
echo='is good'
else
total='is bad'
fi
if [ "$total" == "is good" ]; then
echo "$separator"
ans=
while [ "$ans" != "g" ] && [ "$ans" != "b" ]
do
read -p "Test 5 - manual: Is '$password' a good or bad password? (g/b) " ans
if [ "$ans" == "g" ]; then
echo 'is good'
elif [ "$ans" == "b" ]; then
total='is bad'
echo "$total"
fi
done
fi
echo "$separator"
if [ "$total" == "is good" ]; then
echo "Every test result for '$password' $total: No weakness found :-)"
else
echo "Some test result for '$password' $total: Some weakness found :-("
fi
帮助文本
在当前目录中运行,即测试目录。其中有 shellscript 文件,
$ ./pwdcheck -h
pwdcheck uses 'cracklib-check'
----------------------------------------------------------------
Usage: ./pwdcheck CandidateContaining4DifferentWords
Example: ./pwdcheck At-least-20-char
./pwdcheck 'Should.be.selected.via.*random*.process'
./pwdcheck 'Single-quote-for-1-special-character!'
./pwdcheck 'FindPatternByDigitalTest123'
./pwdcheck 'Provoke1pattern2search3by4separating5words'
Use 4 words chosen randomly, see this link:
https://security.stackexchange.com/questions/6095/xkcd-936-short-complex-password-or-long-dictionary-passphrase
cracklib 程序包
$ apt-cache policy cracklib-runtime
cracklib-runtime:
Installerad: 2.9.2-1ubuntu1
Kandidat: 2.9.2-1ubuntu1
Versionstabell:
*** 2.9.2-1ubuntu1 500
500 http://se.archive.ubuntu.com/ubuntu xenial-updates/main i386 Packages
100 /var/lib/dpkg/status
2.9.2-1build2 500
500 http://se.archive.ubuntu.com/ubuntu xenial/main i386 Packages
测试帮助文本中的不同示例
手动测试很重要,但要明智使用
手动检查和“测试”可能对避免使用糟糕的密码很重要,但是如果你使用了信誉良好的自动随机方法,你应该信赖它并避免篡改结果,因为您可能会使密码更容易被破解。
$ ./pwdcheck CandidateContaining4DifferentWords
Test 1 - size&mix: 'CandidateContaining4DifferentWords' is long enough
CandidateContaining4DifferentWords contains only ASCII letters and digits
-------
Test 2 - lexicon: 'CandidateContaining4DifferentWords'
no comment
-------
Test 3 - digital: 'CandidateContaining4DifferentWords'
is good
-------
Test 4 - cracklib-check: 'CandidateContaining4DifferentWords'
CandidateContaining4DifferentWords: OK
-------
Test 5 - manual: Is 'CandidateContaining4DifferentWords' a good or bad password? (g/b) b
is bad
-------
Some test result for 'CandidateContaining4DifferentWords' is bad: Some weakness found :-(
# comment: This password is published here!
##### Short password #####
$ ./pwdcheck At-least-20-char
Test 1 - size&mix: 'At-least-20-char' is shorter than 20 characters
-------
Test 2 - lexicon: 'At-least-20-char'
least: it is based on a dictionary word
char: it is based on a dictionary word
-------
Test 3 - digital: 'At-least-20-char'
is good
-------
Test 4 - cracklib-check: 'At-least-20-char'
At-least-20-char: OK
-------
Some test result for 'At-least-20-char' is bad: Some weakness found :-(
##### Reminder about random process #####
$ ./pwdcheck 'Should.be.selected.via.*random*.process'
Test 1 - size&mix: 'Should.be.selected.via.*random*.process' is long enough
'Should.be.selected.via.*random*.process' contains characters other than ASCII letters and digits
-------
Test 2 - lexicon: 'Should.be.selected.via.*random*.process'
Should: it is based on a dictionary word
selected: it is based on a dictionary word
via: it is based on a dictionary word
random: it is based on a dictionary word
process: it is based on a dictionary word
-------
Test 3 - digital: 'Should.be.selected.via.*random*.process'
is good
-------
Test 4 - cracklib-check: 'Should.be.selected.via.*random*.process'
Should.be.selected.via.*random*.process: OK
-------
Test 5 - manual: Is 'Should.be.selected.via.*random*.process' a good or bad password? (g/b) g
is good
-------
Every test result for 'Should.be.selected.via.*random*.process' is good: No weakness found :-)
# comment: Do not use the password literally ;-)
##### Single quote the password, if you intend to use special characters #####
##### Words are found by lexicon test (using cracklib-check), and accepted #####
$ ./pwdcheck 'Single-quote-for-1-special-character!'
Test 1 - size&mix: 'Single-quote-for-1-special-character!' is long enough
'Single-quote-for-1-special-character!' contains characters other than ASCII letters and digits
-------
Test 2 - lexicon: 'Single-quote-for-1-special-character!'
Single: it is based on a dictionary word
quote: it is based on a dictionary word
for: it is based on a dictionary word
special: it is based on a dictionary word
character: it is based on a dictionary word
-------
Test 3 - digital: 'Single-quote-for-1-special-character!'
is good
-------
Test 4 - cracklib-check: 'Single-quote-for-1-special-character!'
Single-quote-for-1-special-character!: OK
-------
Test 5 - manual: Is 'Single-quote-for-1-special-character!' a good or bad password? (g/b) b
is bad
-------
Some test result for 'Single-quote-for-1-special-character!' is bad: Some weakness found :-(
##### Showing how the digital test works (it uses cracklib-check) #####
$ ./pwdcheck 'FindPatternByDigitalTest123'
Test 1 - size&mix: 'FindPatternByDigitalTest123' is long enough
FindPatternByDigitalTest123 contains only ASCII letters and digits
-------
Test 2 - lexicon: 'FindPatternByDigitalTest123'
no comment
-------
Test 3 - digital: 'FindPatternByDigitalTest123'
123: it is too simplistic/systematic
-------
Test 4 - cracklib-check: 'FindPatternByDigitalTest123'
FindPatternByDigitalTest123: OK
-------
Some test result for 'FindPatternByDigitalTest123' is bad: Some weakness found :-(
##### Showing the lexicon test and the digital test #####
$ ./pwdcheck 'Provoke1pattern2search3by4separating5words'
Test 1 - size&mix: 'Provoke1pattern2search3by4separating5words' is long enough
Provoke1pattern2search3by4separating5words contains only ASCII letters and digits
-------
Test 2 - lexicon: 'Provoke1pattern2search3by4separating5words'
Provoke: it is based on a dictionary word
pattern: it is based on a dictionary word
search: it is based on a dictionary word
separating: it is based on a dictionary word
words: it is based on a dictionary word
-------
Test 3 - digital: 'Provoke1pattern2search3by4separating5words'
12345: it is too simplistic/systematic
-------
Test 4 - cracklib-check: 'Provoke1pattern2search3by4separating5words'
Provoke1pattern2search3by4separating5words: OK
-------
Some test result for 'Provoke1pattern2search3by4separating5words' is bad: Some weakness found :-(
##### Run interactively without any parameter #####
$ ./pwdcheck
Use 4 words chosen randomly, see this link:
https://security.stackexchange.com/questions/6095/xkcd-936-short-complex-password-or-long-dictionary-passphrase
----------------------------------------------------------------
Enter a password : CandidateContaining4DifferentWords
Test 1 - size&mix: 'CandidateContaining4DifferentWords' is long enough
CandidateContaining4DifferentWords contains only ASCII letters and digits
-------
Test 2 - lexicon: 'CandidateContaining4DifferentWords'
no comment
-------
Test 3 - digital: 'CandidateContaining4DifferentWords'
is good
-------
Test 4 - cracklib-check: 'CandidateContaining4DifferentWords'
CandidateContaining4DifferentWords: OK
-------
Test 5 - manual: Is 'CandidateContaining4DifferentWords' a good or bad password? (g/b) g
is good
-------
Every test result for 'CandidateContaining4DifferentWords' is good: No weakness found :-)
sudodus@xenial32 /media/multimed-2/test/test0/pwdstrength $