-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstrength.sh
More file actions
executable file
·143 lines (119 loc) · 4.54 KB
/
strength.sh
File metadata and controls
executable file
·143 lines (119 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env bash
# -*- coding: utf-8 -*-
# Calculate password entropy based on character pool size
# Arguments: $1 - password string
# Returns: Entropy in bits, calculated as log2(pool_size ^ length)
calculate_entropy() {
local password="$1"
local length=${#password}
local pool_size=0
# Calculate character pool size based on types present
[[ "$password" =~ [a-z] ]] && pool_size=$((pool_size + 26)) # Lowercase letters
[[ "$password" =~ [A-Z] ]] && pool_size=$((pool_size + 26)) # Uppercase letters
[[ "$password" =~ [0-9] ]] && pool_size=$((pool_size + 10)) # Digits
[[ "$password" =~ [[:punct:]] ]] && pool_size=$((pool_size + 32)) # Special characters
# Compute entropy using log2(pool_size^length) with bc for precision
if [ "$pool_size" -gt 0 ]; then
entropy=$(echo "l($pool_size^$length)/l(2)" | bc -l)
printf "%.2f" "$entropy"
else
echo "0.00"
fi
}
# Evaluate password strength and assign a score
# Arguments: $1 - password string
# Outputs: Detailed strength analysis and score
evaluate_password_strength() {
local password="$1"
local length=${#password}
local score=0
local entropy=$(calculate_entropy "$password")
# Base score from entropy, normalized to 50 points max
# Assumes 80 bits entropy as a strong baseline
score=$(echo "($entropy / 80) * 50" | bc -l)
[ "$(echo "$score > 50" | bc)" -eq 1 ] && score=50
# Length bonus using an exponential decay model: 25 * (1 - e^(-length/12))
# Rewards longer passwords with diminishing returns
length_bonus=$(echo "25 * (1 - e(-$length / 12))" | bc -l)
score=$(echo "$score + $length_bonus" | bc -l)
# Character variety bonus, up to 25 points
local variety_bonus=0
[[ "$password" =~ [A-Z] ]] && variety_bonus=$((variety_bonus + 6)) # Uppercase bonus
[[ "$password" =~ [a-z] ]] && variety_bonus=$((variety_bonus + 6)) # Lowercase bonus
[[ "$password" =~ [0-9] ]] && variety_bonus=$((variety_bonus + 6)) # Digit bonus
[[ "$password" =~ [[:punct:]] ]] && variety_bonus=$((variety_bonus + 7)) # Special char bonus
score=$(echo "$score + $variety_bonus" | bc -l)
# Penalty for repetitive patterns (e.g., aaa or 111)
if [[ "$password" =~ (.).*\1.*\1 ]]; then
score=$(echo "$score - 15" | bc -l)
fi
# Load common passwords from `~/common_passwords.txt` into an array
if [ -f "$HOME/common_passwords.txt" ]; then
mapfile -t common_passwords < "$HOME/common_passwords.txt"
else
echo "Error: $HOME/common_passwords.txt file not found!"
exit 1
fi
# Penalty for common passwords
for word in "${common_passwords[@]}"; do
if [[ "$password" =~ $word ]]; then
score=$(echo "$score - 20" | bc -l)
break
fi
done
# Clamp score between 0 and 100
score=$(printf "%.0f" "$score")
[ "$score" -gt 100 ] && score=100
[ "$score" -lt 0 ] && score=0
# Display analysis results
echo "Password length: $length characters"
echo "Entropy: $entropy bits"
echo "Security score: $score/100"
# Assign strength level based on score
if [ "$score" -ge 90 ]; then
echo "Strength level: Very Strong"
elif [ "$score" -ge 70 ]; then
echo "Strength level: Strong"
elif [ "$score" -ge 50 ]; then
echo "Strength level: Moderate"
elif [ "$score" -ge 30 ]; then
echo "Strength level: Weak"
else
echo "Strength level: Very Weak"
fi
# Provide improvement suggestions based on weaknesses
echo -e "\nImprovement suggestions:"
[ "$length" -lt 12 ] && echo "- Increase password length (minimum 12 characters)"
[[ ! "$password" =~ [A-Z] ]] && echo "- Add uppercase letters"
[[ ! "$password" =~ [a-z] ]] && echo "- Add lowercase letters"
[[ ! "$password" =~ [0-9] ]] && echo "- Add numbers"
[[ ! "$password" =~ [[:punct:]] ]] && echo "- Add special characters"
[[ "$password" =~ (.).*\1.*\1 ]] && echo "- Avoid repeating characters"
}
if [[ "${1,,}" == "--uninstall" ]]; then
read -rp "Do you want to continue? (yes/No) > " answer
if [[ ${answer,,} != "yes" ]]; then
exit 1
fi
echo -e "\n[#] Uninstaling..."
if [[ $(uname -o) == "Android" ]]; then # Termux
rm -rf "/data/data/com.termux/files/usr/bin/pse"
rm -rf "$HOME/common_passwords.txt"
else
sudo rm -rf "/usr/local/bin/pse"
sudo rm -rf "$HOME/common_passwords.txt"
fi
wait
echo -e "\n[#] Done."
exit;
fi
# Prompt user for password input securely (no echo)
read -s -p "Please enter your password: " password
echo -e "\n"
# Validate that password is not empty
if [ -z "$password" ]; then
echo "Error: Password cannot be empty!"
exit 1
fi
# Run the password strength evaluation
evaluate_password_strength "$password"