Skip to content

Software License Dongle for Elixir

Elixir reaches the dongle through the SDK’s flat C API with a NIF of two hundred lines that loads the native library at run time and resolves the functions by name, so nothing is linked and nothing sits in the path of the check that a customer could substitute for something more agreeable. The NIF is compiled with the package (elixir_make), every dongle call runs on a dirty I/O scheduler. keynub_licdongle from Hex, Elixir 1.13 or later, on Windows, Linux and macOS.

Hex version badge

# mix.exs
def deps do
  [{:keynub_licdongle, "~> 1.1"}]
endCode language: Elixir (elixir)

Reading a license

alias KeyNub.LicDongle

{:ok, license} =
  LicDongle.with_dongle(fn d ->              # first dongle, or with_dongle("serial", fn ...)
    LicDongle.verify_genuine!(d)             # raises unless genuine
    LicDongle.with_session!(d, fn ->
      LicDongle.read_record!(d, "license")
    end)
  end)Code language: Elixir (elixir)

What you are actually protecting

Elixir software that is sold is usually the kind whose value is in what it does for a customer on their own premises: a telemetry backend, a trading gateway, a message broker, an industrial supervisor. The release ships as BEAM bytecode, which decompiles well, and a check that returns a boolean is still one conditional branch, and patching one of those is a beginner exercise.

So the strong pattern is the one to reach for: the data the program needs only exists when the dongle is present.

# Weak: one patched branch.
unless LicDongle.genuine?(d), do: System.halt(1)

# Strong: the parameters only exist with the dongle present.
{:ok, parameters} =
  LicDongle.with_session(d, fn ->
    d |> LicDongle.app_decrypt!(sealed_blob_shipped_with_your_program) |> decode_parameters()
  end)Code language: Elixir (elixir)

Every call returns {:ok, value} or {:error, %KeyNub.LicDongle.Error{}} with the status (:no_device, :not_genuine, :auth_required, …), the operation and the library’s detail; the ! variants raise instead, and genuine?/1 fails closed. with_dongle and with_session release the dongle and the session on every exit path. The package calls the SDK’s flat companion API, the one designed for foreign function interfaces: integer handles and buffers, no hand-written structure layouts.

Code

Runnable sample: elixir/verify_and_read.exs. Binding source: bindings/elixir. 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