diff --git a/NuciText.Obfuscation.UnitTests/NuciTextObfuscatorTests.cs b/NuciText.Obfuscation.UnitTests/NuciTextObfuscatorTests.cs index 0ab65b5..9813cdd 100644 --- a/NuciText.Obfuscation.UnitTests/NuciTextObfuscatorTests.cs +++ b/NuciText.Obfuscation.UnitTests/NuciTextObfuscatorTests.cs @@ -6,7 +6,7 @@ public class NuciTextObfuscatorTests { static int TestSeed => 123456789; static string TestPlainString => "Test string!"; - static string TestObfuscatedString => "ꓔеst strіng!"; + static string TestObfuscatedString => "Ꭲеst strіng!"; static NuciTextObfuscatorOptions TestObfuscatorOptions => new() { UseApproximateReplacements = true @@ -59,5 +59,12 @@ public void GivenAValidString_WhenDeobfuscating_ThenTheResultHasBeenDeobfuscated [Test] public void GivenAValidString_WhenObfuscating_ThenTheResultHasBeenObfuscated() => Assert.That(obfuscator.Obfuscate(TestPlainString, TestObfuscatorOptions), Is.EqualTo(TestObfuscatedString)); + + [Test] + [TestCase("ciocolatǎ albă", "ciocolată albă")] + public void GivenAnObfuscatedString_WhenDeobfuscating_ThenTheResultIsTheDeobfuscatedString( + string obfuscatedString, + string deobfuscatedString) + => Assert.That(obfuscator.Deobfuscate(obfuscatedString), Is.EqualTo(deobfuscatedString)); } } \ No newline at end of file diff --git a/NuciText.Obfuscation/NuciText.Obfuscation.cs b/NuciText.Obfuscation/NuciText.Obfuscation.cs index 7d58660..4906656 100644 --- a/NuciText.Obfuscation/NuciText.Obfuscation.cs +++ b/NuciText.Obfuscation/NuciText.Obfuscation.cs @@ -76,8 +76,9 @@ public sealed class NuciTextObfuscator(int seed) : INuciTextObfuscator { ':', "։꞉" }, { ';', ";" }, { '\'', "′´ʹ‘’" }, - { '"', "”″" }, + { '\"', "”″" }, { '|', "ǀ" }, + { 'ǀ', "|" }, { '/', "⁄⧸" }, { '\\', "⧵⧹" }, { '-', "‐–" }, @@ -85,88 +86,157 @@ public sealed class NuciTextObfuscator(int seed) : INuciTextObfuscator { '<', "ᐸ𖫬ⵦ" }, { '>', "ᐳ" }, { '3', "З" }, + { 'Ʒ', "Ӡ" }, + { 'Ӡ', "Ʒ" }, + { 'Æ', "Ӕ" }, { 'æ', "ӕ" }, - { 'A', "АΑꓮ" }, - { 'B', "ВΒꓐ" }, - { 'C', "" }, // intentionally empty (JS had no identical C) - { 'D', "ᗞꓓ" }, - { 'E', "ЕΕꓰ" }, - { 'F', "ꓝ" }, - { 'G', "ꓖ" }, - { 'H', "НΗꓧ" }, + + { 'A', "АΑꓮ" }, // The following don't work in some fonts: 𝖠 + { 'Ă', "ӐǍ" }, + { 'Â', "Ȃ" }, + { 'B', "ВΒꓐ" }, // The following don't work in some fonts: 𝖡 + { 'D', "ᗞꓓ" }, // The following don't work in some fonts: 𝖣 + { 'Đ', "ÐƉ" }, + { 'Ð', "ĐƉ" }, + { 'Ɖ', "ÐĐ" }, + { 'E', "ЕΕꓰ" }, // The following don't work in some fonts: 𝖤 + { 'Ĕ', "Ӗ" }, + { 'Ë', "Ё" }, + { 'F', "ꓝ" }, // The following don't work in some fonts: 𝖥 + { 'G', "ꓖ" }, // The following don't work in some fonts: 𝖦 + { 'H', "НΗꓧ" }, // The following don't work in some fonts: 𝖧 { 'I', "ІΙӀӏ" }, - { 'J', "Јꓙ" }, - { 'K', "КKΚꓗ" }, - { 'L', "Ꮮꓡ" }, - { 'M', "МΜϺ" }, - { 'N', "Νꓠ" }, - { 'O', "ОΟՕꓳ" }, - { 'P', "РΡ" }, - { 'S', "Ѕჽ" }, - { 'T', "ТΤꓔ" }, - { 'U', "ꓴՍ" }, - { 'V', "ⴸꛟꓦ" }, - { 'W', "Ԝꓪ" }, - { 'X', "ХΧⵝꓫ" }, - { 'Y', "ΥҮꓬ" }, - { 'Z', "Ζꓜ" }, - - { 'a', "а" }, + { 'Î', "Ȋ" }, + { 'Ï', "ЇΪ" }, + { 'J', "Јꓙ" }, // The following don't work in some fonts: 𝖩 // The following look different in some fonts: Ϳ + { 'K', "КKΚꓗ" }, // The following don't work in some fonts: 𝖪 + { 'Ḱ', "Ќ" }, + { 'L', "Ꮮꓡ" }, // The following don't work in some fonts: 𝖫𐐛 + { 'M', "МΜϺ" }, // The following don't work in some fonts: 𝖬 + { 'N', "Νꓠ" }, // The following don't work in some fonts: 𝖭 + { 'O', "ОΟՕꓳ" }, // The following don't work in some fonts: 𝖮𐓂𖫩 + { 'Ö', "Ӧ" }, + { 'Ө', "Ѳθ" }, + { 'ϴ', "Ɵ" }, + { 'P', "РΡ" }, // The following don't work in some fonts: 𝖯 + { 'Q', "Ԛ" }, // The following don't work in some fonts: 𝖰 + { 'S', "Ѕჽ" }, // The following don't work in some fonts: 𖫖𝖲 + { 'Ṣ', "ȘŞ" }, + { 'Ş', "ȘṢ" }, + { 'Ș', "ȘṢ" }, + { 'Ţ', "ȚṬ" }, + { 'Ț', "ȚŢ" }, + { 'Ṭ', "ȚŢ" }, + { 'U', "ꓴՍ" }, // The following don't work in some fonts: 𝖴𐓎 + { 'V', "ⴸꛟꓦ" }, // The following don't work in some fonts: 𝖵 + { 'W', "Ԝꓪ" }, // The following don't work in some fonts: 𝖶 + { 'X', "ХΧⵝꓫ" }, // The following don't work in some fonts: 𝖷 + { 'Y', "ΥҮꓬ" }, // The following don't work in some fonts: 𝖸 + { 'Z', "Ζꓜ" }, // The following don't work in some fonts: 𝖹Ⴭꛉ + + { 'a', "а" }, // The following don't work in some fonts: 𝖺 + { 'ă', "ӑǎ" }, + { 'â', "ȃ" }, { 'c', "сϲᴄ" }, - { 'e', "е" }, + { 'e', "е" }, // The following don't work in some fonts: 𝖾 + { 'è', "ѐ" }, + { 'ë', "ё" }, + { 'ĕ', "ӗ" }, { 'i', "і" }, + { 'î', "ȋ" }, + { 'ï', "ї" }, { 'j', "ј" }, { 'k', "ĸк" }, - { 'o', "оօο" }, + { 'ɫ', "ɬᏐ" }, + { 'o', "оօο" }, // The following don't work in some fonts: 𐓪𐐬 // The following is looks too differnt in some fonts: ௦ + { 'ö', "ӧ" }, + { 'ó', "όό" }, + { 'ò', "ὸ" }, + { 'ө', "ɵꮎ" }, + { 'θ', "ӨѲ𖺀" }, { 'p', "р" }, { 'q', "ԛ" }, - { 's', "ѕ" }, + { 's', "ѕ" }, // The following don't work in some fonts: 𝗌 + { 'ș', "şṣ" }, + { 'ş', "șṣ" }, + { 'ṣ', "șş" }, + { 'ț', "ţṭ" }, + { 'ţ', "țṭ" }, + { 'ṭ', "țţ" }, { 'w', "ԝꮃ" }, { 'x', "х" }, { 'y', "уү" }, + { 'ÿ', "ӱ" }, { 'z', "ꮓ" } }; private static readonly Dictionary ApproximateReplacements = new() { { '\'', "ʹ" }, - { '3', "Ӡ" }, + + //"0": "߀", // This can turn the text left-to-right + { '3', "Ӡ" }, // The following look too different: Ʒ + { 'Ӡ', "3З" }, { '5', "Ƽ" }, { '6', "бᏮ" }, { 'A', "ᗅᎪ" }, + { 'Ă', "Ā" }, { 'B', "Ᏼᗷꕗ" }, - { 'C', "ᏟᑕⅭ" }, - { 'D', "ᎠⅮ" }, + { 'C', "ᏟᑕⅭ" }, // Ⅽ makes the next character uppercase on iOS + { 'D', "ᎠⅮ" }, // "Ⅾ" makes the next character uppercase on iOS { 'E', "Ꭼⴹ⋿ꗋ" }, + { 'F', "Ϝ" }, // Ϝ does not look identical in some fonts { 'G', "ᏀႺ" }, - { 'I', "ꓲⅠⵏߊꕯ" }, + { 'H', "Ꮋ" }, + { 'I', "ꓲⅠⵏߊꕯ" }, // Stretch // The following look different on some fonts: ꕯ // The following don't work on some fonts: 𝖨𞥑 𞠢 + // The following looks too different: Լ { 'J', "Ꭻ" }, { 'K', "Ꮶ" }, { 'L', "Ⅼ" }, { 'M', "ꓟᎷⅯ" }, + { 'O', "ⵔ" }, + { 'Ө', "ƟϴᎾ" }, { 'P', "ꓑᏢ" }, + { 'Q', "ǪႭ" }, { 'R', "ᎡꓣᏒ" }, { 'S', "ꓢᏚՏႽ" }, { 'T', "ㄒᎢꔋ" }, + { 'Ț', "Ҭ" }, + // { 'U', // The following don't work in some fonts: 𞤋 // The following look too different in some fonts: ᑌ⋃ { 'V', "ᐯᏙⅤ" }, { 'W', "ᎳᏔ" }, + // { 'X', "᙭Ꭓχ" { 'X', "Ⅹ" }, { 'Z', "Ꮓ" }, - { 'c', "ꮯⅽ" }, - { 'd', "ძⅾ" }, + { 'ă', "ā" }, + // { 'b', // The following are broken in some fonts: ხ // The following look different in some fonts: ᏏЬƅ + { 'c', "ꮯⅽ" }, // "ꮯ" has a weird top right at least on iOS and "ⅽ" makes the next character after it uppercase + { 'd', "ძⅾ" }, // The following don't work in some fonts: 𝖽. The following look too different in some fonts: ԁ. "ⅾ" makes the next character uppercase on iOS + { 'g', "ɡց" }, - { 'h', "ᏂႹ" }, - { 'i', "Ꭵⅰ" }, - { 'k', "κꮶ" }, - { 'm', "ⅿ" }, - { 'o', "ჿ" }, + //{ 'h', "հ" }, // "հ" looks like some arabic letter on iOS + { 'h', "ᏂႹ" }, // "һ", // Confirmed to look quite different in many fonts + { 'i', "Ꭵⅰ" }, // This might be a bit of a stretch + { 'ı', "ɪ" }, + { 'ɪ', "ı" }, + { 'ĭ', "ǐ" }, + { 'j', "ϳ" }, + { 'k', "κкκꮶ" }, + { 'ł', "ɫɬᏐ" }, + { 'ɫ', "ł" }, + { 'ɬ', "ł" }, + { 'm', "ⅿ" }, // The following don't work in some fonts: ՠ. ՠ also makes the next character uppercase on iOS + { 'o', "ഠჿ" }, // The following look different in some fonts: ೦. ჿ is broken in Instagram on Android { 'p', "ρƿ" }, - { 's', "ടꮪꜱ" }, + { 's', "ടꮪꜱ" }, // ꜱ looks ok but doesn't work on e.g. Apple Watch + // u // The following don't work in some fonts: 𐓶 { 'u', "υ" }, - { 'v', "ꮩνⅴ" }, + { 'ú', "ύ" }, + { 'v', "ꮩνⅴ" }, // The following have large paddings: ∨ + { 'w', "ꮤ" }, // The following look different in some fonts: ꮃ { 'x', "ⅹ" }, { 'y', "γʏ" } }; diff --git a/NuciText.Obfuscation/NuciText.Obfuscation.csproj b/NuciText.Obfuscation/NuciText.Obfuscation.csproj index 786f794..9121e48 100644 --- a/NuciText.Obfuscation/NuciText.Obfuscation.csproj +++ b/NuciText.Obfuscation/NuciText.Obfuscation.csproj @@ -3,7 +3,7 @@ net10.0 NuciText.Obfuscation - 1.0.0 + 1.1.0 NuciText Obfuscation Horațiu Mlendea Copyright 2026 © Horațiu Mlendea