LSY ODS 授权 SDK
lsyods-license-sdk 是 LSY ODS 提供的 Python 公用 SDK,用于机器身份识别、离线软件授权以及部署制品签名。SDK 提供稳定的机器指纹、安装实例 ID、Ed25519 许可证签发与校验、部署 ZIP 签名与验签,以及许可证状态判断等能力。
- 作者:成都领数云科技有限公司
- 项目地址:https://github.com/9kl/lsyods_license_sdk
- 开源许可:MIT
功能特性
- 在 Windows 和 Linux 上计算带版本标识、不可逆的机器指纹。
- 为不同产品生成独立的安装实例 ID。
- 签发采用 Ed25519 数字签名的离线许可证。
- 使用显式配置的可信公钥集合校验许可证和部署制品签名。
- 将许可证与产品、软件版本、产品版本、安装实例 ID 和机器指纹绑定。
- 判断订阅授权、永久授权、授权已过期和授权尚未生效等状态。
- 通过
supersedes_license_id保留许可证续期关系。 - 将服务端确认的部署方式与 ZIP 摘要一起签名,供客户端独立验签。
产品版本表示 basic、advanced 等商业版本。具体功能或模块是否可用,由被授权产品根据商业版本自行判断。永久授权没有到期时间,但仍然只适用于签名声明中指定的软件版本。
安装
从 PyPI 安装:
pip install lsyods-license-sdk
使用 uv 安装:
uv add lsyods-license-sdk
SDK 要求 Python 3.10 或更高版本。
生成许可证签名密钥
SDK 提供 lsyods-license-keygen 命令,用于生成软件许可证专用的 Ed25519 密钥对。默认情况下,命令会要求输入密码,并使用该密码加密生成的私钥。
PowerShell 示例:
$env:LSYODS_LICENSE_KEY_PASSWORD = Read-Host "请输入密钥密码" -MaskInput
lsyods-license-keygen `
--private-key D:\secure\license-private.pem `
--public-key D:\secure\license-public.pem
命令执行成功后会输出公开的 key_id 和 public_key_base64,供被授权产品配置可信公钥。私钥只能由受控的许可证签发服务访问,禁止将私钥或私钥密码分发到客户端或被授权产品中。
在具备可靠系统访问控制的自动化环境中,可以使用 --no-password 生成不加密的私钥。此时必须通过操作系统文件权限严格保护私钥文件。
机器指纹
from lsyods_license_sdk import calculate_machine_fingerprint
machine_fingerprint = calculate_machine_fingerprint()
print(machine_fingerprint) # sha256:<64位小写十六进制字符>
SDK 使用带版本标识的域分隔符,对操作系统中相对稳定的机器标识进行哈希计算。返回结果不会包含原始的 Windows MachineGuid 或 Linux machine-id。
部署制品签名
许可证签名和部署制品签名必须使用不同的密钥对。请使用 lsyods-artifact-keygen 为部署服务端生成专用的制品签名密钥,不要复用许可证签名密钥。
lsyods-artifact-keygen --private-key artifact-private.pem --public-key artifact-public.pem
该命令默认从 LSYODS_ARTIFACT_KEY_PASSWORD 环境变量读取私钥密码,并输出客户端配置所需的 key_id 和 public_key_base64。
服务端只会对已经通过安全审计和超级管理员审批的 ZIP 文件进行签名。部署方式由服务端审批记录提供,ZIP 中不需要额外的部署清单文件。
部署服务端和客户端通过 SDK 使用同一套制品签名协议:
from pathlib import Path
from lsyods_license_sdk import (
create_artifact_signature,
load_artifact_private_key,
verify_artifact_signature,
)
package = Path("deployment.zip")
private_key = load_artifact_private_key(Path("artifact-private.pem"))
signature = create_artifact_signature(package, private_key, "powershell_deploy")
verified = verify_artifact_signature(
package,
signature,
"powershell_deploy",
{signature["key_id"]: "<public_key_base64>"},
signature["sha256"],
)
许可证签名协议和部署制品签名协议使用不同的域分隔符。生产环境还必须为两类签名分别使用独立私钥,以便单独控制权限、轮换和吊销密钥。
签发许可证
许可证只能在受控的服务端环境中签发:
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": "示例客户",
"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)
签发永久许可证时,将 license_type 设置为 "perpetual",并将 expires_at 设置为 None。
校验许可证
被授权产品只保存可信公钥,并根据当前产品、安装实例和运行机器校验本地许可证:
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"许可证状态异常:{result['status']}")
licensed_version = result["claims"]["product"]["version"]
licensed_edition = result["claims"]["product"]["edition"]
被授权产品负责根据自身的版本兼容规则和功能开放规则,对 licensed_version 和 licensed_edition 进行判断。
许可证续期
续期会生成一份新的签名许可证,同时沿用原有的安装实例 ID 和机器指纹。原许可证保持不变,仍然可以独立验签。新许可证声明中可以包含:
{
"supersedes_license_id": "L260819000001"
}
该字段表示新许可证替代的历史许可证,便于保留完整的授权续期关系。
安全模型
- 系统安全依赖于妥善保护 Ed25519 私钥,而不是隐藏 SDK 的实现代码。
- 被授权产品和部署客户端只能信任明确配置的公钥。
- 许可证和制品签名文档在完成签名后必须视为不可变数据。
- 机器指纹是设备标识,不是身份认证密码或安全凭据。
- 离线授权无法阻止客户修改其完全控制的应用程序,被授权产品应在合适的信任边界执行授权检查。
- 密钥轮换时,应先将新公钥加入可信公钥集合,再使用新私钥签发许可证或签名制品。
- 许可证私钥与部署制品私钥必须分别存储、分别授权和分别轮换。
开发与构建
项目使用 uv 管理依赖,并通过 pyproject.toml 配置阿里云 PyPI 镜像:
uv sync --locked
uv run pytest
uv run pyflakes src tests
uv build --no-sources
开源许可
Copyright (c) 2026 成都领数云科技有限公司。
本项目基于 MIT 许可证 开源。
Metadata
Release files for lsyods_license_sdk 0.3.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 | Provenance | Actions |
|---|---|---|---|---|
| lsyods_license_sdk-0.3.0.tar.gz | 17.5 kB | Without provenance | Details for lsyods_license_sdk-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| lsyods_license_sdk-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for lsyods_license_sdk-0.3.0-py3-none-any.whl |
Total release size: 32.0 kB
Release files / lsyods_license_sdk-0.3.0.tar.gz
| Download URL | lsyods_license_sdk-0.3.0.tar.gz |
|---|---|
| Size | 17.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ab90bc5599c421478bc78bf8b67688edeb7bbab1bef8b64acffc6bc06d25dbef
|
|
BLAKE2b-256 checksum How to use checksums |
1bbcec99596ed3f2a36948d02d2c7fe2e16ae677476e572c0a30597053229e9b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.11
|
Release files / lsyods_license_sdk-0.3.0-py3-none-any.whl
| Download URL | lsyods_license_sdk-0.3.0-py3-none-any.whl |
|---|---|
| Size | 14.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
37f86aa69cfc3b7c9460aeda56161aa38c7f01902e4017b782b7cad4ec32e12d
|
|
BLAKE2b-256 checksum How to use checksums |
444d0845db0dafc474e8051687cbd0ab3e07bbbf5b396a0976a89d3717cfd7b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.11
|
Security for lsyods_license_sdk 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.