diff --git a/ArchiSteamFarm.Tests/Utilities.cs b/ArchiSteamFarm.Tests/Utilities.cs index f4c1276ee..f261cfed1 100644 --- a/ArchiSteamFarm.Tests/Utilities.cs +++ b/ArchiSteamFarm.Tests/Utilities.cs @@ -19,6 +19,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; using static ArchiSteamFarm.Core.Utilities; @@ -34,9 +35,28 @@ public sealed class Utilities { [TestMethod] public void ContextSpecificWordsWeakenPassphrases() => Assert.IsTrue(TestPasswordStrength("archisteamfarmpassword").IsWeak); + [TestMethod] + public void EasyPasswordsHaveMeaningfulReason() { + (bool isWeak, string? reason) = TestPasswordStrength("CorrectHorse"); + + Assert.IsTrue(isWeak); + Assert.IsTrue(reason?.Contains("Capitalization doesn't help very much", StringComparison.OrdinalIgnoreCase)); + } + [TestMethod] public void LongPassphraseIsNotWeak() => Assert.IsFalse(TestPasswordStrength("10charsasdf").IsWeak); + [TestMethod] + public void MemePasswordIsNotWeak() => Assert.IsFalse(TestPasswordStrength("correcthorsebatterystaple").IsWeak); + + [TestMethod] + public void RepeatedPasswordsHaveMeaningfulReason() { + (bool isWeak, string? reason) = TestPasswordStrength("abcabcabc"); + + Assert.IsTrue(isWeak); + Assert.IsTrue(reason?.Contains("Avoid repeated words and characters", StringComparison.OrdinalIgnoreCase)); + } + [TestMethod] public void RepetitiveCharactersWeakenPassphrases() => Assert.IsTrue(TestPasswordStrength("testaaaatest").IsWeak); @@ -48,5 +68,13 @@ public sealed class Utilities { [TestMethod] public void ShortPassphraseIsWeak() => Assert.IsTrue(TestPasswordStrength("four").IsWeak); + + [TestMethod] + public void StraightRowsPasswordsHaveMeaningfulReason() { + (bool isWeak, string? reason) = TestPasswordStrength("`1234567890-="); + + Assert.IsTrue(isWeak); + Assert.IsTrue(reason?.Contains("Straight rows of keys are easy to guess", StringComparison.OrdinalIgnoreCase)); + } } #pragma warning restore CA1724 // We don't care about the potential conflict, as ASF class name has a priority diff --git a/ArchiSteamFarm/Core/Utilities.cs b/ArchiSteamFarm/Core/Utilities.cs index 3d4f8a814..bdb9911f1 100644 --- a/ArchiSteamFarm/Core/Utilities.cs +++ b/ArchiSteamFarm/Core/Utilities.cs @@ -279,9 +279,28 @@ public static class Utilities { } Result result = Zxcvbn.Core.EvaluatePassword(password, forbiddenPhrases); - FeedbackItem feedback = result.Feedback; - return (result.Score < 4, string.IsNullOrEmpty(feedback.Warning) ? feedback.Suggestions.FirstOrDefault() : feedback.Warning); + IList? suggestions = result.Feedback.Suggestions; + + if (!string.IsNullOrEmpty(result.Feedback.Warning)) { + suggestions ??= new List(1); + + suggestions.Insert(0, result.Feedback.Warning); + } + + if (suggestions != null) { + for (byte i = 0; i < suggestions.Count; i++) { + string suggestion = suggestions[i]; + + if (suggestion.EndsWith('.')) { + continue; + } + + suggestions[i] = $"{suggestion}."; + } + } + + return (result.Score < 4, suggestions is { Count: > 0 } ? string.Join(" ", suggestions) : null); } internal static void WarnAboutIncompleteTranslation(ResourceManager resourceManager) {