LSY ODS License SDK
lsyods-license-sdk is the shared Python SDK for LSY ODS machine identity and
offline product licensing. It provides stable machine fingerprints,
installation IDs, Ed25519 license issuance, signature verification, and
license status evaluation.
- Author: 成都领数云科技有限公司
- Repository: https://github.com/9kl/lsyods_license_sdk
- License: MIT
Features
- Calculate a versioned, one-way machine fingerprint on Windows and Linux.
- Generate product-specific installation IDs.
- Issue Ed25519-signed offline license documents.
- Verify signatures against an explicit trusted-public-key set.
- Bind a license to a product, software version, product edition, installation ID, and machine fingerprint.
- Evaluate subscription, perpetual, expired, and not-yet-valid states.
- Keep renewal history through
supersedes_license_id.
The product edition represents a commercial level such as basic or
advanced. Individual feature/module decisions remain in the licensed
product. A perpetual license has no expiry date, but it still applies only to
the software version declared in its signed claims.
Installation
Install from PyPI:
pip install lsyods-license-sdk
Or with uv:
uv add lsyods-license-sdk
Python 3.10 or newer is required.
Generate Signing Keys
The SDK includes the lsyods-license-keygen command. By default it prompts for
a password and encrypts the generated Ed25519 private key:
$env:LSYODS_LICENSE_KEY_PASSWORD = Read-Host "Key password" -MaskInput
lsyods-license-keygen `
--private-key D:\secure\license-private.pem `
--public-key D:\secure\license-public.pem
The command prints the public key_id and public_key_base64 used by licensed
products. Only the controlled license issuer may access the private key. Never
ship the private key or its password with a client or licensed product.
--no-password is available for protected automated environments, but the key
file must then be secured with operating-system access controls.
Machine Fingerprint
from lsyods_license_sdk import calculate_machine_fingerprint
machine_fingerprint = calculate_machine_fingerprint()
print(machine_fingerprint) # sha256:<64 lowercase hexadecimal characters>
The SDK hashes a stable operating-system machine identifier with a versioned domain separator. It does not return the raw Windows MachineGuid or Linux machine-id.
Issue a License
License issuance belongs in a controlled server environment:
from datetime import datetime, timedelta, timezone
from pathlib import Path
from lsyods_license_sdk import (
generate_installation_id,
issue_license,
load_private_key,
)
now = datetime.now(timezone.utc).replace(microsecond=0)
private_key = load_private_key(
Path("D:/secure/license-private.pem"),
password="private-key-password",
)
claims = {
"license_id": "L260819000001",
"issuer": "LSY ODS",
"customer": "Example Customer",
"product": {
"code": "example-product",
"version": "V1.0",
"edition": "advanced",
},
"installation": {
"installation_id": generate_installation_id(),
"machine_fingerprint": "sha256:" + "a" * 64,
},
"license_type": "subscription",
"issued_at": now.isoformat(),
"not_before": now.isoformat(),
"expires_at": (now + timedelta(days=90)).isoformat(),
}
license_document = issue_license(claims, private_key)
For a perpetual license, use license_type="perpetual" and
expires_at=None.
Verify a License
Licensed products contain only trusted public keys and verify the local license against the running product and installation:
from lsyods_license_sdk import calculate_machine_fingerprint, verify_license
trusted_keys = {
"<key_id>": "<public_key_base64>",
}
result = verify_license(
license_document,
trusted_keys,
expected_product="example-product",
expected_installation_id=installation_id,
expected_machine_fingerprint=calculate_machine_fingerprint(),
)
if not result["valid"]:
raise RuntimeError(f"License is {result['status']}")
licensed_version = result["claims"]["product"]["version"]
licensed_edition = result["claims"]["product"]["edition"]
The product is responsible for comparing licensed_version and
licensed_edition with its compatibility and feature rules.
Renewal
Renewal creates a new signed document while retaining the existing installation ID and machine fingerprint. The previous document remains unchanged and verifiable. The new claims may include:
{
"supersedes_license_id": "L260819000001"
}
Security Model
- Security depends on protecting the Ed25519 private key, not hiding this SDK.
- Products must trust only explicitly configured public keys.
- License documents must be treated as immutable after signing.
- A machine fingerprint is an identifier, not an authentication secret.
- Offline licensing cannot prevent a customer from patching an application they fully control; products should enforce licensing at appropriate trust boundaries.
- Key rotation should add the new public key before issuing licenses with it.
Development
The project uses uv and the Aliyun PyPI mirror configured in pyproject.toml:
uv sync --locked
uv run pytest
uv run pyflakes src tests
uv build --no-sources
License
Copyright (c) 2026 成都领数云科技有限公司.
Released under the MIT License.
Release files for lsyods-license-sdk 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lsyods_license_sdk-0.1.0.tar.gz | 12.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lsyods_license_sdk-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:23.3 kB
Release files / lsyods_license_sdk-0.1.0.tar.gz
| Download URL | lsyods_license_sdk-0.1.0.tar.gz |
|---|---|
| Size | 12.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1011d9ce311532c68574c1ae8af7682df47527eabd997a9d2b0dbaa27cd701e8
|
|
BLAKE2b-256 checksum How to use checksums |
08c309dea7cf39db723ec88b1d04a1294d9089e51807b732e687be8564730d9e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / lsyods_license_sdk-0.1.0-py3-none-any.whl
| Download URL | lsyods_license_sdk-0.1.0-py3-none-any.whl |
|---|---|
| Size | 10.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e6c180c1adadceff02c5a0ad7562af1a77958083722b0197ca0b7daba5bee563
|
|
BLAKE2b-256 checksum How to use checksums |
6cbbf33fb0dfefde9fa974f79840f4d9dd737fc05873645b0a11d8005bf6ebc1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|