Skip to content

Protection ​

A license check alone is one if statement: anyone with the code, or an AI editor, can delete it. Protection makes that pointless and makes leaks visible:

PartWhat it doesPlans
Core unlockA small part of your app only runs with a valid license. Remove the check and that part is missing.All
Ownership noticeEvery copy says whose product it is: a header comment and one start-up log line.All
Tamper reportsA modified copy is reported to Sentinel with its next license check.All
Protected filesData files only licensed copies may have stay on SunLicense; the app downloads them after a valid check.Standard
Download watermarkEach buyer's copy carries their key and a mark that names them if it leaks.Standard
Obfuscated releasesRelease builds are obfuscated, so the code is hard to read and patch.All (runs per month)

Set it up ​

Open Products → your product → Setup, leave the parts you want switched on and choose Copy prompt. Paste it into your AI coding agent (Claude Code, Cursor, Codex, Copilot, Windsurf, Gemini CLI…): it works out what your project is (a plugin, mod, bot, script, desktop or web app), adds each part, proves it works with a test license and reports back. The Setup tab ticks each part off by itself once your app shows it working. Re-running the prompt is safe: it skips what's done.

By hand: Setup → Set up by hand has the snippets per part, and the sections below show the calls.

Core unlock ​

You pick something small your paid features can't work without (a core class or module, default rules, a lookup table; at most 512 KB) and seal it. The sealed copy ships with your app; the plain one doesn't. At start-up, after a valid license check, the SDK unseals it and your app loads it.

bash
sunlicense seal build/core.jar --product my-plugin -o src/main/resources/core.sealed
java
ValidationResult r = client.validate(licenseKey, machineId);   // a valid answer carries the unlock
byte[] core = client.unseal(SEALED_CORE);                       // throws Locked when there's no valid unlock
ClassLoader coreClasses = SunLicenseProtection.classLoader(core, getClass().getClassLoader());

The Java templates do this in their release build (./gradlew build -PsunlicenseProduct=<code>); the other SDKs have the same calls in their own idiom (SDKs).

  • The key never ships. Sealing happens on SunLicense's servers (POST /api/v1/products/{id}/seal), with a key per product that never leaves them. A license check returns the unlock only when the license is valid and the product has sealed something. Suspended, expired and revoked licenses, and blocked customers, get no unlock.
  • Outages don't lock anyone out. The SDK keeps the unlock from the last valid check for 7 days, bound to that machine. If SunLicense can't be reached, the core still loads for up to 7 days; an offline license file carries the unlock too, for customers who stay offline longer.
  • Turning it off is safe. Switching Core unlock off in Setup only changes the prompt. Builds you already shipped keep unlocking: SunLicense keeps answering for every product that has sealed data.
  • Members never see the key, and it's never logged.

Unseal without an SDK ​

For a language without an official SDK: when a check is valid and the product has sealed data, the validation answer carries unlock, the product's key in base64. A sealed string is SLS1. followed by base64url of a 12-byte nonce, the AES-256-GCM ciphertext and its 16-byte tag. Decrypt it with the unlock key and the additional data SLS1; the plaintext is JSON {"v": 1, "digests": {"<file>": "<sha256 hex>"}, "data": "<base64>"}, where data is what you sealed and digests the hashes for tamper reports. Keep the unlock in memory, or encrypted on disk and bound to the machine id for the 7-day grace. Test vectors: protection-test-vectors.json.

Ownership notice ​

Every copy carries a short header comment (your organization, the product and your terms link) and logs one line at start-up with the product, the owner, the masked license key and your terms link (the line client.notice() returns). Nothing personal is sent to SunLicense for it. "Licensed to buyer's name" is written only into downloaded copies, through the download placeholders (Standard).

The agent records the notice as done with sunlicense setup report, since SunLicense can't see it from outside.

Tamper reports ​

Your release build seals the expected hashes of the code you ship along with the core (sunlicense seal … --digest 'build/classes/java/main/**/*.class'). After unsealing, the app compares them with what's running (client.integrity(getClass().getClassLoader()), or a jar or folder) and sends OK or MODIFIED, with up to 200 characters naming the changed files, with its next license check. The app never stops itself because of it: you decide.

A license with modified copies becomes a Sentinel finding (License AX8P-XXXX-XXXX-XXXX runs a modified copy), with Suspend as the fix:

  • Free and Lite: a suggestion with one-click Suspend.
  • Standard: in automatic mode Sentinel suspends the license by itself, and you can undo it.

Sentinel never revokes for this. A server host's own patches can look like tampering; if a license is legitimately modified, ignore the finding for that license. The finding's text stays generic: it doesn't say how the check works.

Protected files ​

On Standard, data only licensed copies may have (premium rule sets, presets, models, assets) stays on SunLicense, and the app downloads it after a valid check: sunlicense files push rules.dat --product my-plugin, then client.protectedFile("rules.dat") in the app. Suspended, expired and revoked licenses get nothing. Everything about it: Protected files.

What protection can't stop ​

Be clear-eyed about it: nothing makes code uncrackable. Someone who holds a valid license can still extract the unlock and patch their own copy. What protection does:

  • Raises the cost. Deleting the license check is no longer enough; a cracker needs a valid license and real work, per release, and obfuscation makes that work harder.
  • Makes leaks visible. A patched copy fails its integrity check and is reported to Sentinel with the license that ran it; downloaded copies carry a watermark that names the buyer.
  • Lets you act. Suspend the license and the next copy can't unlock anything new; once the 7-day grace runs out, the core stops loading.

It never stops paying customers: outages, a few days offline and a switched-off part don't lock them out.

Send feedback

Found something broken, or have an idea? It goes straight to our board.

The first line becomes the title.
Images (optional, up to 5: paste, drop or capture)
Check each image before sending, and remove any that show something private.

We also receive this page's address and your browser version.

Ctrl Enter to send