el fuego


A standalone easy-to-plug license issuer.

Key features:


System setup

License creation code snippets

License check code snippets


You need to have keyengine.json configuration file in the current directory.

  "httpPort": 80,
  "secret": "1234567890",
  "key": "test.key",
  "pwd": "qazwsx",
  "driver": "sqlite3",
  "connString": "file:test.db?cache=shared&mode=memory",
  "allowTokens": true,
  "license": "ey...0ifX0="


Sets up a port where the built-in HTTP listens.


Specifies a secret key to access /upload/ page.


A path of a private key file. The key should be in an OpenSSH format, as generated by ssh-keygen.


The private key password, or an empty string, if the key isn't encrypted.


Database driver, one of postgres, mysql, sqlite3.


Database connection string.

For postgres it should be as follows:


or see the docs here.

For mysql it should be as follows:


or see the docs here.

For sqlite3 it should be as follows:


or see the docs here.


If true, unblocks /license/ page processing.


keyengine itself is a shareware so it requires license to be used. Use your license key or empty quotes for trial period. After the 30-day trial period you should buy a license at https://elfuego.biz.


Command line


This command runs command line license generator, you may use it as follows:

keyengine gen -prod=PRODID -type=personal -name="Johnny Walker" [-start=2019-01-01] [-dur=1y]


This command runs the built-in HTTP server, you may use it as follows:

keyengine daemon

HTTP queries

keyengine has a built-in HTTP server and it is ready to be run as a linux service. The HTTP service processes 2 queries:

1. POST query to /upload/

The upload query is usually called from a successful payment page. Querying it you should specify licensing product info and, optionally, payer info (for informational purposes).

Authorization: Secret <secret>

where <secret> is secret value from keyengine.json,

Variables encoded into license

productId [mandatory] product id the license is generated for, used to be checked in licensed stuff to check if the license permits using a particular program

licensedto [mandatory] personal or company name the product is licensed to

lictype [mandatory] license type: personal, enterprise, or whatever you want, any text string

licduration license duration including years, months, and/or days, like: 1m15d, or 1y6m; empty means infinite license

test true/false, for test purposes: 1) test flag is stored to DB, 2) productId written to license is actually productId-test, just to avoid redundant checks

Variables only stored to DB

productName product name, informational field

name payer's name, informational field

addrLine1 payer's address, informational field

city payer's city, informational field

state payer's state, informational field

zipCode payer's zip code, informational field

country payer's country, informational field

email payer's email, informational field

phoneNumber payer's phone number, informational field


token a license record token (should be used in license query to retrieve license)

hash a license record hash (should be used in license query to retrieve license)

license a license itself

2. GET query to /license/

license query is used to retrieve a previously generated license (for example, you may send a link in email to a user). It is built by template as follows: http://<license.server>/license/hash-token. For hash == a7873a910691c2594117998bdad3a9cf and token == bc7f80c1-46b5-11e9-a11c-f430b9a6e499 from the previous query example it should be http://<license.server>/license/a7873a910691c2594117998bdad3a9cf-bc7f80c1-46b5-11e9-a11c-f430b9a6e499.


Reply of this query is the same as for the previous query.

System setup


Description=Keyengine Service

ExecStart=/usr/local/bin/keyengine daemon &
ExecStop=killall keyengine


License creation code snippets


(tested on version 7.3)

$keHost = 'lic.example.com';
$keSecret = '12345';
$keTest = false;
$productDescr = 'Acme program';
$productId = 'ACME1';
$licType = 'enterprise';

function gen_license() {
    global $keHost, $keSecret, $keTest;
    global $productDescr, $productId, $licType;
    $data = array();
    $data['productId'] = $productId;
    $data['productName'] = $productDescr;
    $data['test'] = $keTest ? "true" : "false";
    $data['licensedto'] = $_POST['licensedto'];
    $data['lictype'] = $licType;
    $data['licduration'] = null;
    $data['name'] = $_POST['name'];
    $data['addrLine1'] = $_POST['addrLine1'];
    $data['city'] = $_POST['city'];
    $data['state'] = $_POST['state'];
    $data['zipCode'] = $_POST['zipCode'];
    $data['country'] = $_POST['country'];
    $data['email'] = $_POST['email'];
    $data['phoneNumber'] = $_POST['phoneNumber'];

    $url = $keHost;

    $options = array(
        'http' => array(
            'header'  => "Content-type: application/x-www-form-urlencoded\r\nAuthorization: Secret $keSecret\r\n",
            'method'  => 'POST',
            'content' => http_build_query($data)
    $context  = stream_context_create($options);
    $result = file_get_contents($url . '/upload/', false, $context);
    $error = error_get_last();
    if ($result === false)
        return array(false, $error['message']);
    return array(json_decode($result));

License check code snippets


(tested on version 1.11.5)

package main

import (

var pubKey = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC4dK1cTSWe/6IkGpB8Xqc8YEFUKPLDFvl37Or4WacQhIhH+yb7dKAae0t866/ViZHf6qjwuWD4iXhmmQm5hDS9yiGGjEzmovhW8PiuJ7qhdkuliBbWmn5knOT9A4b9QSNubsVhk5qGExbK9hoFLR/97fqeCsuy67jvhXABPh7fBQ==`
var lic = "eyJsaWNlbnNlIjoie1wibmFtZVwiOlwiSm9obm55IFdhbGtlclwiLFwidHlwZVwiOlwicGVyc29uYWxcIixcInN0YXJ0XCI6XCIyMDE5LTAyLTI2VDEzOjUxOjIzKzAyOjAwXCIsXCJlbmRcIjpudWxsLFwiYXJ0aWNsZXNcIjpbe1wibmFtZVwiOlwiUFJPRElELXRlc3RcIixcInBheWxvYWRcIjpudWxsfV19Iiwic2lnbmF0dXJlIjp7IkZvcm1hdCI6InNzaC1yc2EiLCJCbG9iIjoiSFhqejE5bThuZktOMGtrMitkMHFFcGRWcUtDbWgvQytBdXNkMTJWditITE54YitiUWcwS1gvUndpaFA3WUdDRUlrNHlLbEZCZUl6Umk3VlQvaU1xNEFkaWY4Q3VQVzBUQWJLcGN4TDg1RS94YVFlM2ZJT0pteUNSSEFIbXIxdk56TUs2eDR2SC9DbFRuZVlveEhlTndNV2hmWG0yUURBUy85NHMrekgxLzhJPSJ9fQ=="

type signed struct {
	License   string        `json:"license"`
	Signature ssh.Signature `json:"signature"`

type article struct {
	Name string `json:"name"`

type license struct {
	LicensedTo string     `json:"name"`
	LicType    string     `json:"type"`
	Start      time.Time  `json:"start"`
	End        *time.Time `json:"end"`
	Articles   []article  `json:"articles"`

func checkLicense(prodId, pubKey, licString string) *license {
	pub, _, _, _, e := ssh.ParseAuthorizedKey([]byte(pubKey))
	var sl signed
	bytes, e := base64.StdEncoding.DecodeString(licString)
	e = json.Unmarshal(bytes, &sl)
	e = pub.Verify([]byte(sl.License), &sl.Signature)
	var lic1 license
	e = json.Unmarshal([]byte(sl.License), &lic1)
	if e == nil {
		if time.Now().After(lic1.Start) {
			if lic1.End == nil || time.Now().Before(*lic1.End) {
				for _, a := range lic1.Articles {
					if prodId == a.Name {
						return &lic1
	return nil

func main() {
	const prodId = "PRODID-test"
	lic1 := checkLicense(prodId, pubKey, lic)
	fmt.Printf("License verified: %t\n", lic1 != nil)
	if lic1 != nil {
		fmt.Printf("You have %s license for product \"%s\" registered to %s.\n", lic1.LicType, prodId, lic1.LicensedTo)

func die(e error) {
	if e != nil {

python 3

(tested on version 3.6.4)

import base64
import json
import re
from datetime import datetime, timezone

# pycryptodome
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5

pub_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC4dK1cTSWe/6IkGpB8Xqc8YEFUKPLDFvl37Or4WacQhIhH+yb7dKAae0t866/ViZHf6qjwuWD4iXhmmQm5hDS9yiGGjEzmovhW8PiuJ7qhdkuliBbWmn5knOT9A4b9QSNubsVhk5qGExbK9hoFLR/97fqeCsuy67jvhXABPh7fBQ=='
lic_str = 'eyJsaWNlbnNlIjoie1wibmFtZVwiOlwiSm9obm55IFdhbGtlclwiLFwidHlwZVwiOlwicGVyc29uYWxcIixcInN0YXJ0XCI6XCIyMDE5LTAyLTI2VDEzOjUxOjIzKzAyOjAwXCIsXCJlbmRcIjpudWxsLFwiYXJ0aWNsZXNcIjpbe1wibmFtZVwiOlwiUFJPRElELXRlc3RcIixcInBheWxvYWRcIjpudWxsfV19Iiwic2lnbmF0dXJlIjp7IkZvcm1hdCI6InNzaC1yc2EiLCJCbG9iIjoiSFhqejE5bThuZktOMGtrMitkMHFFcGRWcUtDbWgvQytBdXNkMTJWditITE54YitiUWcwS1gvUndpaFA3WUdDRUlrNHlLbEZCZUl6Umk3VlQvaU1xNEFkaWY4Q3VQVzBUQWJLcGN4TDg1RS94YVFlM2ZJT0pteUNSSEFIbXIxdk56TUs2eDR2SC9DbFRuZVlveEhlTndNV2hmWG0yUURBUy85NHMrekgxLzhJPSJ9fQ=='

def date_decode(s):
    if s is None:
        return None
    pat = re.compile(r'^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}):(\d{2})$', re.M | re.I)
    m = pat.match(s)
    if m is not None:
        s = m.group(1) + m.group(2)
        return datetime.strptime(s, "%Y-%m-%dT%H:%M:%S%z")
    return s

def check_license(prod_id, pub_key, lic_string):
    sl = json.loads(base64.b64decode(lic_string))
    rsakey = RSA.importKey(pub_key)
    signer = PKCS1_v1_5.new(rsakey)
    digest = SHA256.new()
    digest.update(bytes(sl['license'], 'utf8'))
    sign = sl['signature']['Blob']
        signer.verify(digest, bytes(sign, 'utf8'))
    except ValueError:
        return None
    lic = json.loads(sl['license'])
    now = datetime.now(tz=timezone.utc)
    if now > date_decode(lic['start']):
        if lic['end'] is None or now < date_decode(lic['end']):
            arts = lic['articles']
            for i in range(len(arts)):
                a = arts[i]
                if prod_id == a['name']:
                    return lic
    return None

prod_id = "PRODID-test"
lic = check_license(prod_id, pub_key, lic_str)
print("License verified: %s" % (lic is not None))
if lic is not None:
    print("You have %s license for product \"%s\" registered to %s.\n" % (lic['type'], prod_id, lic['name']))


(tested on version 7.3)

// phpseclib 1.0

$pub_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC4dK1cTSWe/6IkGpB8Xqc8YEFUKPLDFvl37Or4WacQhIhH+yb7dKAae0t866/ViZHf6qjwuWD4iXhmmQm5hDS9yiGGjEzmovhW8PiuJ7qhdkuliBbWmn5knOT9A4b9QSNubsVhk5qGExbK9hoFLR/97fqeCsuy67jvhXABPh7fBQ==";
$lic_str = "eyJsaWNlbnNlIjoie1wibmFtZVwiOlwiSm9obm55IFdhbGtlclwiLFwidHlwZVwiOlwicGVyc29uYWxcIixcInN0YXJ0XCI6XCIyMDE5LTAyLTI2VDEzOjUxOjIzKzAyOjAwXCIsXCJlbmRcIjpudWxsLFwiYXJ0aWNsZXNcIjpbe1wibmFtZVwiOlwiUFJPRElELXRlc3RcIixcInBheWxvYWRcIjpudWxsfV19Iiwic2lnbmF0dXJlIjp7IkZvcm1hdCI6InNzaC1yc2EiLCJCbG9iIjoiSFhqejE5bThuZktOMGtrMitkMHFFcGRWcUtDbWgvQytBdXNkMTJWditITE54YitiUWcwS1gvUndpaFA3WUdDRUlrNHlLbEZCZUl6Umk3VlQvaU1xNEFkaWY4Q3VQVzBUQWJLcGN4TDg1RS94YVFlM2ZJT0pteUNSSEFIbXIxdk56TUs2eDR2SC9DbFRuZVlveEhlTndNV2hmWG0yUURBUy85NHMrekgxLzhJPSJ9fQ==";

function check_license($prod_id, $pub_key, $lic_string) {
    $sl = json_decode(base64_decode($lic_string));
    $rsa = new Crypt_RSA();
    $key_created = $rsa->loadKey($pub_key);
    if (!$key_created)
	return null;
    $signature = base64_decode($sl->signature->Blob);
    $verified = $rsa->verify($sl->license, $signature);
    if (!$verified)
	return null;
    $lic = json_decode($sl->license);
    $now = time();
    if ($now > strtotime($lic->start)) {
        if ($lic->end === null || $now < strtotime($lic->end)) {
            $arts = $lic->articles;
            foreach($arts as $a) {
                if ($prod_id == $a->name)
                    return $lic;
    return null;

$prod_id = "PRODID-test";
$lic = check_license($prod_id, $pub_key, $lic_str);
echo "License verified: " . ($lic !== null ? "true" : "false") . "\n";
if ($lic !== null)
    echo "You have " . $lic->type . " license for product \"$prod_id\" registered to " . $lic->name . ".\n";