diff --git a/NuciText.Obfuscation.UnitTests/NuciTextObfuscatorTests.cs b/NuciText.Obfuscation.UnitTests/NuciTextObfuscatorTests.cs index df81973..079883c 100644 --- a/NuciText.Obfuscation.UnitTests/NuciTextObfuscatorTests.cs +++ b/NuciText.Obfuscation.UnitTests/NuciTextObfuscatorTests.cs @@ -4,35 +4,56 @@ namespace NuciText.Obfuscation.UnitTests { public class NuciTextObfuscatorTests { - static int StaticTestSeed => 123456789; - static string StaticTestString => "Test string!"; + static int TestSeed => 123456789; + static string TestPlainString => "Test string!"; + static string TestObfuscatedString => "ꓔеst strіng!"; INuciTextObfuscator obfuscator; [SetUp] public void Setup() { - obfuscator = new NuciTextObfuscator(StaticTestSeed); + obfuscator = new NuciTextObfuscator(TestSeed); } + [Test] + public void GivenAnEmptyString_WhenDebfuscating_ThenTheResultIsEmpty() + => Assert.That(obfuscator.Deobfuscate(string.Empty), Is.Empty); + [Test] public void GivenAnEmptyString_WhenObfuscating_ThenTheResultIsEmpty() => Assert.That(obfuscator.Obfuscate(string.Empty), Is.Empty); + [Test] + public void GivenANullString_WhenDeobfuscating_ThenTheResultIsNull() + => Assert.That(obfuscator.Deobfuscate(null), Is.Null); + [Test] public void GivenANullString_WhenObfuscating_ThenTheResultIsNull() => Assert.That(obfuscator.Obfuscate(null), Is.Null); + [Test] + public void GivenAValidString_WhenDeobfuscating_ThenTheResultIsNotNull() + => Assert.That(obfuscator.Deobfuscate(TestObfuscatedString), Is.Not.Null); + [Test] public void GivenAValidString_WhenObfuscating_ThenTheResultIsNotNull() - => Assert.That(obfuscator.Obfuscate(StaticTestString), Is.Not.Null); + => Assert.That(obfuscator.Obfuscate(TestPlainString), Is.Not.Null); + + [Test] + public void GivenAValidString_WhenDeobfuscating_ThenTheResultIsNotEmpty() + => Assert.That(obfuscator.Deobfuscate(TestObfuscatedString), Is.Not.Empty); [Test] public void GivenAValidString_WhenObfuscating_ThenTheResultIsNotEmpty() - => Assert.That(obfuscator.Obfuscate(StaticTestString), Is.Not.Empty); + => Assert.That(obfuscator.Obfuscate(TestPlainString), Is.Not.Empty); + + [Test] + public void GivenAValidString_WhenDeobfuscating_ThenTheResultHasBeenDeobfuscated() + => Assert.That(obfuscator.Deobfuscate(TestObfuscatedString), Is.EqualTo(TestPlainString)); [Test] public void GivenAValidString_WhenObfuscating_ThenTheResultHasBeenObfuscated() - => Assert.That(obfuscator.Obfuscate(StaticTestString), Is.Not.EqualTo(StaticTestString)); + => Assert.That(obfuscator.Obfuscate(TestPlainString), Is.EqualTo(TestObfuscatedString)); } } \ No newline at end of file diff --git a/NuciText.Obfuscation/INuciText.Obfuscation.cs b/NuciText.Obfuscation/INuciText.Obfuscation.cs index 97b7da8..89a8773 100644 --- a/NuciText.Obfuscation/INuciText.Obfuscation.cs +++ b/NuciText.Obfuscation/INuciText.Obfuscation.cs @@ -2,6 +2,8 @@ namespace NuciText.Obfuscation { public interface INuciTextObfuscator { + string Deobfuscate(string text); + string Obfuscate(string text); } } diff --git a/NuciText.Obfuscation/NuciText.Obfuscation.cs b/NuciText.Obfuscation/NuciText.Obfuscation.cs index 34d3631..a39dfc3 100644 --- a/NuciText.Obfuscation/NuciText.Obfuscation.cs +++ b/NuciText.Obfuscation/NuciText.Obfuscation.cs @@ -175,6 +175,88 @@ public NuciTextObfuscator(string seed) : this(seed.GetHashCode()) { } public NuciTextObfuscator() : this(Environment.TickCount) { } + public string Deobfuscate(string text) + { + if (text is null) + { + return null; + } + + if (text.Equals(string.Empty)) + { + return string.Empty; + } + + string input = text; + + foreach (KeyValuePair entry in IdenticalGroupReplacements) + { + string originalGroup = entry.Key; + string candidates = entry.Value; + + if (!string.IsNullOrEmpty(candidates)) + { + foreach (char candidate in candidates) + { + input = input.Replace(candidate.ToString(), originalGroup); + } + } + } + + foreach (KeyValuePair entry in ApproximateGroupReplacements) + { + string originalGroup = entry.Key; + string candidates = entry.Value; + + if (!string.IsNullOrEmpty(candidates)) + { + foreach (char candidate in candidates) + { + input = input.Replace(candidate.ToString(), originalGroup); + } + } + } + + StringBuilder builder = new StringBuilder(input.Length); + + foreach (char character in input) + { + bool wasReplaced = false; + + foreach (KeyValuePair entry in IdenticalReplacements) + { + if (!string.IsNullOrEmpty(entry.Value) && entry.Value.Contains(character)) + { + builder.Append(entry.Key); + wasReplaced = true; + break; + } + } + + if (wasReplaced) + { + continue; + } + + foreach (KeyValuePair entry in ApproximateReplacements) + { + if (!string.IsNullOrEmpty(entry.Value) && entry.Value.Contains(character)) + { + builder.Append(entry.Key); + wasReplaced = true; + break; + } + } + + if (!wasReplaced) + { + builder.Append(character); + } + } + + return builder.ToString(); + } + public string Obfuscate(string text) { if (text is null)