Skip to Content
New release 12 available 🎉
ObfuscatorCode EncryptionLicense-Bound Code Encryption

License-Bound Code Encryption

License-bound code encryption is a variation of Password Protected Code in which the password that unlocks an encrypted method is not a fixed constant baked into the build, but a value read from the customer’s license at runtime.

The protected method still ships inside the obfuscated assembly, but its code stays encrypted until a valid license supplies the correct password. This means a sensitive or premium feature only runs for users whose license authorizes it, while the rest of the application keeps working normally for everyone else.

This is the pattern Babel Obfuscator uses internally to gate its own licensed features. It layers on top of the regular code encryption you already know — there is nothing new to install, only a rule and a small hook to write.

How it works

  1. Mark the code to protect. An XML rule (or the Obfuscation attribute) selects the methods or types to encrypt and assigns them a source name and a password, keeping the encrypted code inside the assembly (Internal = true).
  2. Provide a get-password hook. A method marked [Obfuscation(Feature = "msil encryption get password")] receives the source name and returns the password for that source by reading a field of the loaded license.
  3. Run. When the protected method is first called, the Babel Virtual Machine (BVM) invokes the hook to obtain the password for the source. If the license carries the expected field, the method is decrypted and executed; if the field is missing or the value is wrong, decryption fails and the method cannot run — so the feature is effectively locked.

Only the methods matched by a rule with a <Source> are license-bound. Methods encrypted with plain --msilencryption (no source) are unlocked from the assembly itself and keep running without a license, so the unlicensed application continues to work — only the license-gated features are withheld.

Encrypting the code

Add a rule that encrypts the sensitive code and binds it to a named source and password:

<Rule name="encrypt premium" feature="msil encryption" exclude="false"> <Target>Methods</Target> <Pattern>ACME.Premium::*</Pattern> <Properties> <Source>premium</Source> <Password>Xa9!k2$LpQ7r</Password> <Internal>true</Internal> </Properties> <Description>Encrypt the premium feature, unlocked by the license.</Description> </Rule>

The same can be expressed inline with the Obfuscation attribute:

[Obfuscation(Feature = "msil encryption:internal=true;source=premium;password=Xa9!k2$LpQ7r", Exclude = false)] internal class Premium { public string Run() => "premium result"; }

The <Password> you set at build time must match the value the get-password hook returns for that source at runtime. In a license-bound design the hook reads that value from the license, so store the same value in the license field you issue to your customers.

Reading the password from the license

Declare a single hook that maps a source name to the password held in the license. The example below uses Babel Licensing to look up a licensed feature and return its value:

[Obfuscation(Feature = "msil encryption get password")] internal static string GetSourcePassword(string source) { var license = LicenseManager.Instance.License; var feature = license.Features.FirstOrDefault(f => f.Name == source); if (feature == null) throw new ApplicationException($"feature '{source}' is not licensed"); return Encoding.UTF8.GetString(feature.Data); }

At runtime the BVM calls GetSourcePassword("premium"); the hook returns the password stored in the customer’s license, and the premium method decrypts and runs.

The hook must be reachable by the code Babel injects, so declare it public or internal. If you leave it private or protected, Babel widens it to internal automatically during obfuscation (it is never made public), so the injected code can call it.

For a complete, runnable implementation — including the LicenseManager class and how to issue per-edition licenses — see the Feature Based Licenses example.

Works with every license delivery method

Because the hook simply reads from the loaded license object, license-bound code encryption is independent of how that license reaches the application. It works unchanged with all of Babel Licensing’s delivery methods:

Whichever mode you choose, once your licensing code has validated and loaded the license, the get-password hook can read the field it needs and the protected feature unlocks.

Prefer to keep the encrypted code out of the main assembly entirely? Combine this pattern with External Code Files to deploy the encrypted method alongside the license.

Last updated on