rymga ← Back to Lock Master

Tracing & retrace

Two post-build tools that both rest on the same idea: the information needed to read a protected build is yours, and only yours. rymga hands you the files and keeps nothing — so nobody, us included, can undo your obfuscation or forge your watermarks.

Retrace

Obfuscation renames everything, so a crash report from a user comes back unreadable — at a.a.b(...) instead of at app.EventDispatcher.foo(...). Retrace turns it back, offline, using the name mapping your build produced. No upload, no key, no server — just a text lookup.

The mapping file

Every build that renames emits a mapping file — a small text file that ties your original names to the obfuscated ones. The CLI downloads it next to your output (app-obf.map beside app-obf.jar), or wherever --mapping-out points.

Keep it, per release. Treat the .map like a build artifact: commit it or archive it with each version you ship. Lose it and you can't retrace crash reports from that build — and because rymga never stores it, we can't hand you another copy. (It's the same discipline as ProGuard's mapping.txt.)

We don't keep it for a reason: the mapping is the key to reading your obfuscated code. Holding it would make us a single place to breach and undo everyone's protection — so we deliver it and forget it.

Stable names across releases (incremental)

Point the CLI at the same file with --mapping rymga.map and it does both at once: it uploads your previous mapping so unchanged classes and methods keep their obfuscated names, and writes the updated mapping back to that file for next time. Commit rymga.map with each release and a renamed public API stays stable version to version — anything that compiled against it keeps linking. (This is the "incremental obfuscation" a seed alone can't give you.)

Running retrace

Point it at the build's mapping and feed it the stack trace — from a file or a pipe:

# from a file
java -jar rymga-cli.jar retrace --mapping app-obf.map --trace crash.txt

# or straight from a pipe
cat crash.txt | java -jar rymga-cli.jar retrace --mapping app-obf.map

The obfuscated trace on the left becomes the readable one on the right:

What your user sent
Exception in thread "main" java.lang.IllegalStateException: boom
	at a.a.b(EventDispatcher.java:4)
	at a.a.a(EventDispatcher.java:3)
	at app.Main.main(Main.java:2)
After retrace
Exception in thread "main" java.lang.IllegalStateException: boom
	at app.EventDispatcher.foo(EventDispatcher.java:4)
	at app.EventDispatcher.launchSomething(EventDispatcher.java:3)
	at app.Main.main(Main.java:2)
Match the mapping to the build. Names shift between releases (they're assigned in order, so adding a class reshuffles them). Retrace a trace with the same build's mapping — that's why you keep one per release. For a public API whose names must stay put across versions, keep it instead of renaming it.

Per-buyer watermark

If you sell your plugin, you can stamp each copy you hand out with the buyer's id, invisibly. When a copy leaks, you recover that id and know exactly whose it was. It's redundant across the jar, so it survives re-jarring and even deleting some classes.

It's the same CLI — one tool, nothing extra to install or manage. The stamping and tracing run in our cloud; each license has its own secret that never leaves our servers and never ships in any jar. You don't handle a key file — you just point the CLI at a jar.

How it works

  1. Obfuscate once. A normal build produces your protected app-obf.jar.
  2. Stamp per sale. For each buyer, watermark stamp the obfuscated jar with their id. No re-obfuscation — it's a light edit, and costs 1 token.
  3. Trace on a leak. Run watermark trace on the leaked copy to recover the id. Free.
The secret is ours to keep, so you can't lose it. We hold one secret per license, server-side; you never see or manage it, and the same license always traces its own stamps. Honest limit: the watermark is tracing, not tamper-proofing — the secret keeps it unforgeable, but a determined attacker who diffs two differently-stamped copies can spot and scrub the carrier fields. It raises the effort and gives you attribution; it isn't unremovable.

Commands

# per sale, stamp the obfuscated jar with that buyer's id (1 token, no re-obfuscation)
java -jar rymga-cli.jar watermark stamp \
  --in app-obf.jar --id "order-8842-jane" --out app-jane.jar
# a copy leaks → recover the id (free)
java -jar rymga-cli.jar watermark trace --in leaked.jar
# → order-8842-jane

Same auth as everything else — your seat key (--key or OBF_KEY). The CLI only makes the call; none of the watermark logic or the secret is ever in the client.