Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion NuciText.Obfuscation.UnitTests/NuciTextObfuscatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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));
}
}
154 changes: 112 additions & 42 deletions NuciText.Obfuscation/NuciText.Obfuscation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,97 +76,167 @@ 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<char, string> 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', "γʏ" }
};
Expand Down
2 changes: 1 addition & 1 deletion NuciText.Obfuscation/NuciText.Obfuscation.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>NuciText.Obfuscation</RootNamespace>
<Version>1.0.0</Version>
<Version>1.1.0</Version>
<Description>NuciText Obfuscation</Description>
<Authors>Horațiu Mlendea</Authors>
<Copyright>Copyright 2026 © Horațiu Mlendea</Copyright>
Expand Down
Loading