String Encryption Enterprise
Literal strings in .NET assemblies are stored in plain text in the #US (User Strings) heap. Anyone with a hex editor can read your connection strings, API keys, error messages, and business logic. Demeanor encrypts every ldstr operand and injects a per-assembly decryptor that transparently restores them at runtime.
Usage
| CLI | MSBuild | Default |
|---|---|---|
| (enabled by default at Enterprise) | (enabled by default) | On |
--no-strings | <ObfuscateNoStrings>true</ObfuscateNoStrings> | Disable |
Before & After
public string FormatReceipt(int quantity, TaxRegion region)
{
decimal total = CalculateTotal(quantity, region);
return $"Receipt: {quantity}x {_currency} {_basePrice:F2} = {_currency} {total:F2}";
}
if (key.StartsWith("TRIAL-"))
Console.WriteLine("Trial expired — grace period active.");string a(int a, h a)
{
decimal value = k.a(this, a, a);
defaultInterpolatedStringHandler.AppendLiteral(
l.a("O\u000f]O\u00c3\u001e6\u0080\u00bf"));
...
}
if (a.StartsWith(l.a("\u00e8d\u0096\u001f\u00c3\u0017")))
Console.WriteLine(l.a(
"\u00f2\r\u00e5\u0011\u0097\u00e1..."));Real ILSpy output. Every string literal is replaced by a call to the injected decryptor l.a(). The encrypted bytes use a per-assembly key derived from the license. Strings are decrypted on first use and cached.
How It Works
Demeanor replaces every ldstr instruction with a call to an injected static decryptor method. The encrypted string bytes are stored inline as the argument. The decryptor uses a per-assembly key seeded from the license key hash — making the license a functional input, not just a gate.
When to Disable
- Performance-critical hot loops — the first call to each encrypted string has a small decryption overhead. Subsequent calls return the cached result. In practice this is negligible.
- Debugging — encrypted strings make debugging harder. Use
--no-stringsfor Debug builds (this is the default MSBuild configuration).
Ready to protect your .NET code?