| | | 1 | | using System.Text.RegularExpressions; |
| | | 2 | | |
| | | 3 | | namespace LOCKnet.Core.Services; |
| | | 4 | | |
| | | 5 | | /// <summary> |
| | | 6 | | /// Standardimplementierung fuer <see cref="IPasswordStrengthService"/>. |
| | | 7 | | /// </summary> |
| | | 8 | | public sealed partial class PasswordStrengthService : IPasswordStrengthService |
| | | 9 | | { |
| | | 10 | | private const string LabelVeryWeak = "Sehr schwach"; |
| | | 11 | | private const string LabelWeak = "Schwach"; |
| | | 12 | | private const string LabelMedium = "Mittel"; |
| | | 13 | | private const string LabelStrong = "Stark"; |
| | | 14 | | private const string LabelVeryStrong = "Sehr stark"; |
| | | 15 | | |
| | | 16 | | /// <inheritdoc/> |
| | | 17 | | public PasswordStrength Evaluate(string password) |
| | 17 | 18 | | { |
| | 17 | 19 | | if (string.IsNullOrEmpty(password)) |
| | 7 | 20 | | { |
| | 7 | 21 | | return new PasswordStrength(0, LabelVeryWeak, "#FF4757"); |
| | | 22 | | } |
| | | 23 | | |
| | 10 | 24 | | var hasUpper = password.Any(char.IsUpper); |
| | 10 | 25 | | var hasLower = password.Any(char.IsLower); |
| | 10 | 26 | | var hasDigit = password.Any(char.IsDigit); |
| | 10 | 27 | | var hasSpecial = SpecialCharacterRegex().IsMatch(password); |
| | 50 | 28 | | var variety = new[] { hasUpper, hasLower, hasDigit, hasSpecial }.Count(v => v); |
| | | 29 | | |
| | 10 | 30 | | var points = 0; |
| | 10 | 31 | | if (password.Length >= 8) |
| | 9 | 32 | | { |
| | 9 | 33 | | points++; |
| | 9 | 34 | | } |
| | | 35 | | |
| | 10 | 36 | | if (password.Length >= 12) |
| | 4 | 37 | | { |
| | 4 | 38 | | points++; |
| | 4 | 39 | | } |
| | | 40 | | |
| | 10 | 41 | | if (hasUpper) |
| | 5 | 42 | | { |
| | 5 | 43 | | points++; |
| | 5 | 44 | | } |
| | | 45 | | |
| | 10 | 46 | | if (hasLower) |
| | 10 | 47 | | { |
| | 10 | 48 | | points++; |
| | 10 | 49 | | } |
| | | 50 | | |
| | 10 | 51 | | if (hasDigit) |
| | 7 | 52 | | { |
| | 7 | 53 | | points++; |
| | 7 | 54 | | } |
| | | 55 | | |
| | 10 | 56 | | if (hasSpecial) |
| | 6 | 57 | | { |
| | 6 | 58 | | points++; |
| | 6 | 59 | | } |
| | | 60 | | |
| | 10 | 61 | | if (variety >= 3) |
| | 5 | 62 | | { |
| | 5 | 63 | | points++; |
| | 5 | 64 | | } |
| | | 65 | | |
| | 10 | 66 | | if (variety == 4) |
| | 4 | 67 | | { |
| | 4 | 68 | | points++; |
| | 4 | 69 | | } |
| | | 70 | | |
| | 10 | 71 | | var score = points switch |
| | 10 | 72 | | { |
| | 1 | 73 | | <= 1 => 0, |
| | 3 | 74 | | <= 3 => 1, |
| | 2 | 75 | | <= 5 => 2, |
| | 1 | 76 | | <= 7 => 3, |
| | 3 | 77 | | _ => 4 |
| | 10 | 78 | | }; |
| | | 79 | | |
| | 10 | 80 | | return score switch |
| | 10 | 81 | | { |
| | 1 | 82 | | 0 => new PasswordStrength(0, LabelVeryWeak, "#FF4757"), |
| | 3 | 83 | | 1 => new PasswordStrength(1, LabelWeak, "#FF6B35"), |
| | 2 | 84 | | 2 => new PasswordStrength(2, LabelMedium, "#FFB347"), |
| | 1 | 85 | | 3 => new PasswordStrength(3, LabelStrong, "#2ED573B3"), |
| | 3 | 86 | | _ => new PasswordStrength(4, LabelVeryStrong, "#2ED573") |
| | 10 | 87 | | }; |
| | 17 | 88 | | } |
| | | 89 | | |
| | | 90 | | [GeneratedRegex("[^a-zA-Z0-9]")] |
| | | 91 | | private static partial Regex SpecialCharacterRegex(); |
| | | 92 | | } |