Tutorial 02 — Bindings (machine + password + TOTP)
Objectif — tie a licence to three independent pieces of evidence so a leaked file is useless without all of them. Concepts — AND semantics ·
WithMachineID·WithPassword·WithTOTPCodeAttendu — client succeeds only when all three evidences match; drop one or change the machine ID → exit 1.
In the TUI
2→ Licences.n→ wizard.- Step 3 (Machine): type
host-alpha→Enter. - Step 5 (Validity):
Enterfor defaults. - Step 6 (FreeFields): type
subject=alice@example.com→Enter. - Step 7 (TOTP): toggle ON →
Enter. - Step 8 (Review):
Enterto sign. - The post-issue overlay shows the TOTP secret and a 6-digit sanity code. Copy both — the secret goes to the licensee out of band.
Eon the licence row → save/tmp/alice.license.3→ Issuers →E→ save/tmp/issuer.pub.
The wizard captures the password evidence inline before
step 8 — type hunter2 when it asks.

In your program
package main
import (
"log"
"os"
license "github.com/oioio-space/maldev/license"
)
func main() {
licPEM, _ := os.ReadFile("/tmp/alice.license")
pubPEM, _ := os.ReadFile("/tmp/issuer.pub")
pub, kid, _ := license.ParsePublicKey(pubPEM)
trusted := license.Trusted{Keys: license.SingleKey(kid, pub)}
// Collect all three pieces of evidence from your runtime.
machine := []byte("host-alpha") // hostid.Composite() in production
password := "hunter2" // prompt the user
totpCode := "123456" // also prompted; from Google Authenticator etc.
v, err := license.Verify(licPEM, trusted,
license.WithMachineID(machine),
license.WithPassword(password),
license.WithTOTPCode(totpCode),
)
if err != nil {
log.Fatalf("license check failed: %v", err)
}
log.Printf("running for %s", v.Subject)
}
Missing or wrong evidence on ANY of the three → err != nil.
That's the security property — a leaked licence on a different
machine doesn't start.
Runnable client:
examples/.../02-bindings-and-verify/client.
Test it together
go test ./examples/license-manager/tutorials/02-bindings-and-verify
The test issues a real bound licence and runs the client with full, missing, and wrong evidence — proving the "AND" semantics.