为桌面软件与 Unity 应用做的授权基础设施

卖你的软件。
密钥的事交给 Keygate。

一套 HTTP API 加一个原生 SDK:生成激活密钥、设备绑定激活、验证与吊销授权、签发离线证书、扣减用量。我们只做 SDK 和 API——不打包、不签名、不替你发布安装程序。

  • 设备绑定激活
  • 限期离线租约
  • 永久离线证书
  • Ed25519 票据验签
  • 用量计量
  • C ABI · Unity IL2CPP

工作原理

三次调用,整个接入就完成了。

先在用户中心拿到项目参数,然后在应用启动时激活一次,之后交给 SDK 的后台心跳与本地验签。下面全部是真实字段名。

注册账户,创建项目

注册后系统自动下发免费额度密钥。在「项目管理」页创建项目取 project_key,在「SDK 下载与说明」页取本账户专属的 sdk_hmac_key 与验签公钥。base_url 填 HTTPS 域名本身,不要附加 /api。

{
  "base_url": "https://token.your-domain.com",
  "project_key": "<项目页生成>",
  "sdk_hmac_key": "<用户中心取得,账户专属>",
  "ed25519_public_key": "<GET /api/sdk/public-key>",
  "pinned_root_certificates_pem": ["<部署的根 CA PEM>"],
  "heartbeat_interval_secs": 60,
  "verify_interval_secs": 14400,
  "offline_only": false
}

每次销售发一把密钥,在应用内激活

把密钥交给客户(发放、赠送或后台签发都行)。客户在你的应用里输入一次,SDK 完成设备绑定激活;成功后本机持有加密缓存,重复激活同一台设备不会占第二个名额。

int ready = await LicSdkClient.Instance.InitAsync(configJson);
if (ready != 0) return;                       // 0 = SDK 就绪

int code = await LicSdkClient.Instance.ActivateAsync(licenseKey);
if (code == 0) UnlockFullVersion();           // 0 = 已激活并绑定本机
else ShowMessage(await LicSdkClient.Instance.GetLastErrorAsync());

运行中校验、计量与离线部署

后台按间隔自动心跳与在线校验,状态变化通过事件回到 Unity 主线程。完全离线的机器:在用户中心导出离线激活包(限期 limited_date 或永久 perpetual,无需设备 ID),宿主读成字节后导入即可离线使用。

LicSdkClient.Instance.LicenseEventReceived += OnLicenseEvent;

LicenseSdkState state = await LicSdkClient.Instance.GetStateAsync();
// ActiveOnline / ActiveOfflineLease / ActiveOfflinePerpetual / Expired / Revoked / Blocked

await LicSdkClient.Instance.ImportOfflineLicenseFileAsync(packagePath);
await LicSdkClient.Instance.ConsumeSavedAsync("export", 1, idempotencyKey); // 需联网,离线返回 -13

不想用 SDK?API 是普通的 HMAC 签名 JSON 接口,任何语言都能自己实现,包括自行验证 Ed25519 票据。

SDK

授权判定发生在客户端,但信任来自签名。

Rust 核心负责激活、验签、加密缓存与后台任务;C# 胶合层把它包成 Unity / .NET 宿主可直接调用的异步接口。不显示文件选择框,不猜当前工作目录——路径由你的宿主传进来。

设备绑定与项目归属

一把密钥激活一台设备,并记录所属项目。后台可以解绑、暂停、吊销;被停止的设备本地门禁同时关闭(状态 Blocked,接口返回 -17)。

限期离线(lease)

导出离线包时由服务端计算并限制 expires_at,不会晚于密钥与项目的有效期。到期后必须重新联网续签,本地只验签、不自造到期时间。

永久离线(perpetual)

expires_at = null,签名后不因时间自然到期,只允许用于本身永久的密钥与项目。代价必须说清楚:设备完全离线时,服务端无法实时告知吊销、暂停或额度变化。

用量计量

POST /api/metering/consume 携带 Idempotency-Key,重复请求不会重复扣减。计量只在联网时生效,离线返回 -13——不会为了“能用”而静默绕过配额。

Ed25519 票据与密钥轮换

授权状态由服务端用 Ed25519 签名,票据带 key_id;SDK 同时接受兼容期内的旧公钥。签名私钥只存在于 Service 侧,导出的证书里不含 License Key、HMAC 密钥或服务端秘密。

动态库与平台

C ABI 版本 2,产物是 DLL / SO / DYLIB。Unity 完整发布包含 C# 绑定、示例、licsdk.h 与 release-manifest.json;下载目录当前提供 Windows x64 / x86 与 macOS Apple Silicon / Intel,Linux 与 Android 产物当前不提供,需要时由发布脚本在具备工具链的构建机上按 target 构建。

我们不提供什么

  • 不打包安装程序,不碰 Inno Setup / Nuitka 这类构建链。
  • 不做代码签名、公证,也不替你上架或代发布。
  • 不做离线设备的实时吊销——物理上做不到,任何供应商都一样。
  • 不在客户端做最终授权判定:额度、状态、有效期始终由服务端下发。
下载 Unity 完整发布包

API

一组小而稳的 JSON 接口。

SDK 发出的就是这些请求。它们由 Web 反向代理转发到内网 Service,客户端永远看不到内部地址;请求体有大小上限,超限直接返回 413。

方法 路径 用途 鉴权
GET/health服务与数据库连通性公开
GET/api/sdk/public-keyEd25519 验签公钥与 key_id公开
POST/api/sdk/register登记设备与项目归属HMAC 签名头
POST/api/activations/online在线激活并绑定设备,返回签名票据HMAC 签名头
POST/api/activations/heartbeat刷新授权状态(限期 / 永久 / 暂停 / 吊销)HMAC 签名头
POST/api/metering/consume计量扣减,仅在线生效HMAC 签名头 + Idempotency-Key
POST/api/sdk/offline-claim离线包联网认领;其余副本返回已吊销HMAC 签名头
POST/api/auth/register客户账户注册(邮箱激活链接或管理员邀请码,激活后下发免费额度密钥)账户会话 Cookie
POST/api/auth/activate核销邮件激活链接,激活待激活账户公开
POST/api/auth/activate/resend重发账户激活邮件(60 秒频控)公开
GET/api/portal/*项目、密钥、设备、账单与 SDK 参数账户会话 Cookie
GET/api/admin/*管理控制台:签发、解绑、暂停、导出离线包ADMIN_API_KEY

SDK 自动附加 X-Timestamp / X-Nonce / X-Request-Sig / Idempotency-Key;时间戳与 nonce 用于防重放,证书与设备绑定关系由服务端保存。

价格

免费开始,按已激活的密钥计费。

没有打包费、没有签名费、没有发布抽成——因为那些我们根本不做。计费只发生在「密钥真的被激活并在用」的时候。

免费额度

¥0 / 起

  • 注册自动下发 100 把激活密钥(数量由部署方配置)
  • 免费密钥标记为非计费,激活后不产生账单
  • 在线激活、心跳、离线包导出全都能用
  • 不裁剪功能,也不限时试用
注册拿额度

自托管部署

部署到你的环境

  • Service、Web、PostgreSQL 全部跑在你自己的机器上
  • 签名私钥、HMAC 密钥与根 CA 由你掌握
  • 离线包、认领记录与审计记录留在本地库
  • TLS 在反向代理终止,Service 只监听 127.0.0.1
管理控制台入口

额度用尽不会弄坏任何东西:已激活的密钥继续有效,只是发不出新密钥。账户欠费时计费中的授权会被暂停(状态 suspended),付款后自动恢复。金额与额度以用户中心「账单」页为准,货币为 CNY。

常见问题

只回答真正重要的问题。

你们能帮我打包、签名或上架吗?

不能,也不做。Keygate 只交付三样东西:原生 SDK 动态库、C# 胶合层、HTTP API。构建、代码签名、公证和上架留在你自己的流程里。好处是授权判定不依赖任何外部构建服务——SDK 断网时照样按签名票据本地判定。

我的用户需要一直保持在线吗?

不需要。只有首次激活必须联网。之后 SDK 按 verify_interval_secs(默认 14400 秒)与 heartbeat_interval_secs(默认 60 秒)后台刷新,并把服务端签名的票据写进本机加密缓存;网络错误不会改变已缓存的授权。完全离线的机器请导出离线激活包。

限期离线和永久离线该怎么选?

限期(limited_date)适合“离线一段时间再联网续签”:到期时间由服务端计算并压到不超过密钥与项目的有效期,到期后必须联网。永久(perpetual)的 expires_at 为 null,不会自然到期,只允许用于本身永久的密钥与项目——代价是离线期间收不到任何变更。

永久离线证书能被远程吊销吗?

完全离线时不能——任何供应商都做不到,设备不联网就收不到吊销、暂停或额度变化。能保证的部分是:首台联网设备用 Project Key 认领后,其余副本再次联网会返回已吊销;管理员解绑会撤销旧包的认领资格并让密钥恢复可用;重启或重新导入同一个原始文件也不会清除已写入的吊销签名。

额度用完或者欠费会怎样?

已激活的密钥继续有效,只是发不出新的。欠费暂停只作用于计费中的授权(状态变为 suspended,本地门禁返回 Blocked),付款后恢复;免费额度密钥与永久授权不会被欠费逻辑连带停掉。

支持哪些引擎和平台?

Unity IL2CPP(提供 C# 胶合层与示例)、任何能做 P/Invoke 的 .NET 宿主,以及任何能发 HTTPS 请求的语言直接调用 API。原生库是 C ABI 版本 2 的 DLL / SO / DYLIB;发布目标清单见 release-manifest.json,未构建的平台不能当作已发布。

我可以不用 SDK,自己验证票据吗?

可以。调用 GET /api/sdk/public-key 取 Ed25519 公钥与 key_id,按 key_id 选公钥验签,并保留兼容期内的旧公钥以支持轮换。但请不要自己实现密码学——用平台标准库,也别把设备指纹当秘密密钥用。

我的数据存在哪里?

取决于部署方,本项目默认自托管:Service 只监听 127.0.0.1,公网流量统一由 Web 转发,TLS 在反向代理终止。激活密钥在服务端以哈希索引、密文仅在门户按需解密展示;日志不会写 License Key、HMAC 密钥或签名私钥。

一个域名,就能开始卖授权。

注册账户 → 创建项目拿 Project Key → 下载 SDK → 在应用里激活第一把密钥。