Skip to content

Software License Dongle for Lua

Lua is rarely the language a product is written in. It is the language a product is extended in: a CAD package, a simulator, an instrument’s scripting host, a game engine. That makes it the natural place to license a paid plugin or add-on — and the place where a licence check is most exposed, because the script usually ships as readable source alongside the application.

The binding is one file using LuaJIT’s ffi module, so there is nothing to compile: install the rock, or copy the one file into your project. Plain Lua 5.x has no FFI and would need a C extension module, which defeats the point.

LuaRocks version badge

luarocks install keynub-licdongleCode language: Bash (bash)

Reading a License

local keynub = require('keynub_licdongle')

local ctx = keynub.Context()
local dongle = ctx:open()                    -- first dongle, or ctx:open(serial)
dongle:verifyGenuine()                       -- errors unless genuine

local session = dongle:openSession()
local license = session:readRecord('license')

session:close(); dongle:close(); ctx:close()Code language: Lua (lua)

Why the Boolean Is Worst Here

In a compiled product, removing a licence check means patching a binary. In a Lua add-on it means opening a file in a text editor:

-- Anyone who bought your add-on can delete this line.
if not licensed then os.exit() endCode language: Lua (lua)

So do not write it. Encrypt what the add-on needs — its geometry kernels, rule tables, post-processor definitions, the parameters that make it worth paying for — and decrypt them through the dongle when the plugin loads:

local rules = session:appDecrypt(blob)   -- shipped encrypted with the add-onCode language: Lua (lua)

Two Practical Notes

Byte data is a Lua string throughout, which is what ffi.string produces and what #s measures correctly for binary. And progress callbacks are freed explicitly after use: LuaJIT allocates a machine-code trampoline per ffi.cast of a function and they are a finite resource, so a long-running host that never freed them would eventually run out. The binding handles that for you.

Shipping the Native Library with a Lua Application

The binding is one Lua file over the LuaJIT FFI, installed as the keynub-licdongle rock or copied into the project. It declares the core library’s functions and loads keynub_licdongle at run time, so an embedded LuaJIT (a game, a plugin host, an automation controller) needs the platform’s library where the host process finds shared libraries.

The prebuilt libraries for every platform are in the SDK repository’s natives/<platform>/ folder, with a SHA-256 manifest: Windows x64, x86 and ARM64, Linux x86_64 and aarch64, and universal macOS binaries for Intel and Apple silicon. On Linux, install the udev rule from NATIVES.md once, so that ordinary users may open the device.

Questions Lua Developers Ask

Does the Binding Need LuaJIT, or Does Plain Lua Work?

LuaJIT, or another Lua with the LuaJIT FFI library: the binding declares the C functions through ffi.cdef and calls them directly, which PUC Lua has no way to do without a C module.

Can a Game or Plugin Scripted in Lua Be Protected with a Dongle?

Yes, from the host or from the script: the script asks the dongle for the data it needs (a level table, parameters, a key) and receives nothing without it. A script file is plain text, so a boolean check in it is the weakest form.

Does a Lua Application Need Administrator Rights to Talk to the Dongle?

No, and no driver either: the dongle is a USB HID device that the operating systems handle with their built-in class drivers. On Linux, install the shipped udev rule once so that ordinary users may open it; without the rule the SDK reports access denied and names the cause in its error detail.

Does a Lua License Check Need an Internet Connection?

No. Verification is a local exchange between your program and the dongle over USB: the SDK checks the dongle’s certificate chain to KeyNub’s root and runs a live challenge-response. There is no activation server and no account, so the check works on air-gapped machines.

Who Can Read the License Records on a Dongle?

Anyone holding the dongle: a program opens a session and reads records, and can decrypt data sealed for that dongle. Writing records, erasing them and incrementing counters need your write key. What the dongle guarantees is that none of it is available without the dongle present.

Can a License Written from Lua Be Read by a Program in Another Language?

Yes. Every binding drives the same core library and the same dongle, and records and sealed data are language-neutral bytes. Your issuing tool can be written in one language and your product in another.

Code

Runnable sample: lua/verify_and_read.lua. Binding source: bindings/lua. Both are Apache-2.0, in the public SDK repository; the prebuilt native libraries are in the repository’s natives/ folder, one per platform.

All supported languages · All industries · Buy a KeyNub · Ask us something