Repository: archlinux/archinstall

Issue:
Suggestion: babysitting password strength is not a necessary step?
Arch itself does not do it, unlike some other distros that by default force requirements on you.

Just maybe the script should skip judging the password and not ask for additional input of yes/no, if you are aware your password is not very secure.

Arent even actually secure passwords ridiculously long? Like 15 chars? So its more of a show of security unless it stops yelling at you after really strong password only.


Suggestion: babysitting password strength is not a necessary step?
Arch itself does not do it, unlike some other distros that by default force requirements on you.

Just maybe the script should skip judging the password and not ask for additional input of yes/no, if you are aware your password is not very secure.

Arent even actually secure passwords ridiculously long? Like 15 chars? So its more of a show of security unless it stops yelling at you after really strong password only.




Discussion:
Personally I wouldn't mind removing the `yes/no` question, and just have a color coded (or verbose) sign that it's weak.
But then again, the number one security issue still 2022 is weak passwords wherever I've been.. So there's that too.

*Edit: And yes, I know it's not our job to educate people in best practices, although I'm conflicted because if no one does it, who will?*
I really like the color coding idea! 
I fully agree that weak passwords are a venerability, but to me the strength validation kind of feels a bit intrusive, especially when people are trying to install it on a vm :)



Personally I wouldn't mind removing the `yes/no` question, and just have a color coded (or verbose) sign that it's weak.
But then again, the number one security issue still 2022 is weak passwords wherever I've been.. So there's that too.

*Edit: And yes, I know it's not our job to educate people in best practices, although I'm conflicted because if no one does it, who will?*
I really like the color coding idea! 
I fully agree that weak passwords are a venerability, but to me the strength validation kind of feels a bit intrusive, especially when people are trying to install it on a vm :)




Resolving patch:
diff --git a/archinstall/lib/models/password_strength.py b/archinstall/lib/models/password_strength.py
new file mode 100644
--- /dev/null
+++ b/archinstall/lib/models/password_strength.py
@@ -0,0 +1,85 @@
+from enum import Enum
+
+
+class PasswordStrength(Enum):
+	VERY_WEAK = 'very weak'
+	WEAK = 'weak'
+	MODERATE = 'moderate'
+	STRONG = 'strong'
+
+	@property
+	def value(self):
+		match self:
+			case PasswordStrength.VERY_WEAK: return str(_('very weak'))
+			case PasswordStrength.WEAK: return str(_('weak'))
+			case PasswordStrength.MODERATE: return str(_('moderate'))
+			case PasswordStrength.STRONG: return str(_('strong'))
+
+	def color(self):
+		match self:
+			case PasswordStrength.VERY_WEAK: return 'red'
+			case PasswordStrength.WEAK: return 'red'
+			case PasswordStrength.MODERATE: return 'yellow'
+			case PasswordStrength.STRONG: return 'green'
+
+	@classmethod
+	def strength(cls, password: str) -> 'PasswordStrength':
+		digit = any(character.isdigit() for character in password)
+		upper = any(character.isupper() for character in password)
+		lower = any(character.islower() for character in password)
+		symbol = any(not character.isalnum() for character in password)
+		return cls._check_password_strength(digit, upper, lower, symbol, len(password))
+
+	@classmethod
+	def _check_password_strength(
+		cls,
+		digit: bool,
+		upper: bool,
+		lower: bool,
+		symbol: bool,
+		length: int
+	) -> 'PasswordStrength':
+		# suggested evaluation
+		# https://github.com/archlinux/archinstall/issues/1304#issuecomment-1146768163
+		if digit and upper and lower and symbol:
+			match length:
+				case num if 13 <= num:
+					return PasswordStrength.STRONG
+				case num if 11 <= num <= 12:
+					return PasswordStrength.MODERATE
+				case num if 7 <= num <= 10:
+					return PasswordStrength.WEAK
+				case num if num <= 6:
+					return PasswordStrength.VERY_WEAK
+		elif digit and upper and lower:
+			match length:
+				case num if 14 <= num:
+					return PasswordStrength.STRONG
+				case num if 11 <= num <= 13:
+					return PasswordStrength.MODERATE
+				case num if 7 <= num <= 10:
+					return PasswordStrength.WEAK
+				case num if num <= 6:
+					return PasswordStrength.VERY_WEAK
+		elif upper and lower:
+			match length:
+				case num if 15 <= num:
+					return PasswordStrength.STRONG
+				case num if 12 <= num <= 14:
+					return PasswordStrength.MODERATE
+				case num if 7 <= num <= 11:
+					return PasswordStrength.WEAK
+				case num if num <= 6:
+					return PasswordStrength.VERY_WEAK
+		elif lower or upper:
+			match length:
+				case num if 18 <= num:
+					return PasswordStrength.STRONG
+				case num if 14 <= num <= 17:
+					return PasswordStrength.MODERATE
+				case num if 9 <= num <= 13:
+					return PasswordStrength.WEAK
+				case num if num <= 8:
+					return PasswordStrength.VERY_WEAK
+
+		return PasswordStrength.VERY_WEAK
diff --git a/archinstall/lib/models/users.py b/archinstall/lib/models/users.py
--- a/archinstall/lib/models/users.py
+++ b/archinstall/lib/models/users.py
@@ -1,6 +1,8 @@
 from dataclasses import dataclass
 from typing import Dict, List, Union, Any, TYPE_CHECKING
 
+from .password_strength import PasswordStrength
+
 if TYPE_CHECKING:
 	_: Any
 
@@ -25,8 +27,9 @@ def json(self) -> Dict[str, Any]:
 		}
 
 	def display(self) -> str:
-		password = '*' * len(self.password)
-		return f'{_("Username")}: {self.username:16} {_("Password")}: {password:16} sudo: {str(self.sudo)}'
+		strength = PasswordStrength.strength(self.password)
+		password = '*' * len(self.password) + f' ({strength.value})'
+		return f'{_("Username")}: {self.username:16} {_("Password")}: {password:20} sudo: {str(self.sudo)}'
 
 	@classmethod
 	def _parse(cls, config_users: List[Dict[str, Any]]) -> List['User']:
diff --git a/archinstall/lib/user_interaction/utils.py b/archinstall/lib/user_interaction/utils.py
--- a/archinstall/lib/user_interaction/utils.py
+++ b/archinstall/lib/user_interaction/utils.py
@@ -7,6 +7,7 @@
 from typing import Any, Optional, TYPE_CHECKING
 
 from ..menu import Menu
+from ..models.password_strength import PasswordStrength
 from ..output import log
 
 if TYPE_CHECKING:
@@ -16,42 +17,23 @@
 SIG_TRIGGER = None
 
 
-def check_password_strong(passwd: str) -> bool:
-	symbol_count = 0
-	if any(character.isdigit() for character in passwd):
-		symbol_count += 10
-	if any(character.isupper() for character in passwd):
-		symbol_count += 26
-	if any(character.islower() for character in passwd):
-		symbol_count += 26
-	if any(not character.isalnum() for character in passwd):
-		symbol_count += 40
-
-	if symbol_count**len(passwd) < 10e20:
-		prompt = str(_("The password you are using seems to be weak, are you sure you want to use it?"))
-		choice = Menu(prompt, Menu.yes_no(), default_option=Menu.yes()).run()
-		return choice.value == Menu.yes()
-
-	return True
-
-
 def get_password(prompt: str = '') -> Optional[str]:
 	if not prompt:
 		prompt = _("Enter a password: ")
 
-	while passwd := getpass.getpass(prompt):
-		if len(passwd.strip()) <= 0:
+	while password := getpass.getpass(prompt):
+		if len(password.strip()) <= 0:
 			break
 
-		if not check_password_strong(passwd):
-			continue
+		strength = PasswordStrength.strength(password)
+		log(f'Password strength: {strength.value}', fg=strength.color())
 
 		passwd_verification = getpass.getpass(prompt=_('And one more time for verification: '))
-		if passwd != passwd_verification:
+		if password != passwd_verification:
 			log(' * Passwords did not match * ', fg='red')
 			continue
 
-		return passwd
+		return password
 
 	return None
 


Test patch: