Skip to content

HiAPI 授权保护 —— 最终方案与分阶段开发计划

本文件是权威版,自包含。新会话只需读:本文件 + 记忆库 project_license_protection.md。 (早期的 hiapi-cloud-public授权与代码保护方案.mdGraalVM可行性验证清单.md 走的是已被推翻的 GraalVM/保密路线,已删除。)


0. 真实目标(一切的前提,别再跑偏)

系统本身没有核心算法。用户要的不是"防反编译 / 保密代码",而是三件事:

  1. 控制:没有我的授权,系统跑不起来;可远程限制租户数/实例数、可吊销。
  2. 威慑:客户不敢随意滥用、不敢把源码丢到网上。
  3. 心理:让客户觉得里面加密了重要东西,从而不敢动。

核心认知:客户本地完整运行 + 有代码 → "无法破解"不可能、也不需要。目标是"让老实人没动力、让坏人有成本有风险",靠的是 控制闸门 + 联网授权 + 水印追溯 + 合同,不是加密强度。


1. 方案总览

做法:把一个启动必需(load-bearing)的模块加密,启动时联网到授权服务器校验按客户密钥下发、本地解密加载进 JVM。没授权/超额 → 拿不到模块 → 系统起不来。

为什么选 hiapi-core-public 当闸门:它是登录/验证码/上传(34 文件,2838 行)。抠掉它=没法登录=系统是死的。它不值钱(无算法)但不可或缺,是理想的控制闸门。

四道牙齿

  1. 起不来:闸门模块不在 → 无法登录 → 系统不可用。
  2. 联网授权:激活/心跳/配额在你服务器(nuwa),可限制、可吊销、可发现滥用。
  3. 每客户水印:泄漏到网上能追到是谁。
  4. 合同:法律兜底。

诚实边界:有能力的人能脱掉闸门——改变不了。但①绝大多数客户不会逆向(perception 即挡住)②动了能被 phone-home 发现③水印追人④合同起诉。对目标足够。


2. 明确不做 / 已否决(别在新会话里重新探讨)

否决项原因
GraalVM Native Image闸门是被客户 JVM 应用加载的库,不是独立服务;native image 编不出可被 JVM 加载、Spring 扫描的产物。(技术栈本身能 native,已验证,但此场景不适用)
买 Zelix(贵)hiapi-core-public 是编排样板+标准件(标准 RSA + 开源烂大街的滑块验证码),不值这个钱。用免费 ProGuard。
信封加密客户数据数据是客户自己的,他删掉加密存明文即可,防不住。
把逻辑搬 native 重写没有值得保护的算法。
追求"无法 dump / 不可破解"不可能,且对本目标不必要。

3. 涉及的工程与现状

  • 授权服务端:现 hiapi-cloud-license-server(Go),迁入并合并到 hiapi-cloud-nuwa(hiapi-cloud-appstore,Go,Gin+GORM/MySQL)internal/license
  • 加载器:现 hiapi-core-cpp(JNI + OpenSSL + 反调试)+ Java 侧 hiapi-fast-frame/hiapi-fast-core/hiapi-core-license/.../HiapiCloudLicense.java(CommandLineRunner,static 块 System.load .so,initAuthorization 下载解密 DefineClass + 心跳)。思路保留,修正后用
  • 闸门模块hiapi-fast-frame/hiapi-fast-core/hiapi-core-public(不随源码交付,加密下发)。
  • 宿主应用hiapi-cloud-public(源码交付给客户,客户自己 build 成 JVM 应用;依赖 hiapi-core-public)。

现有已知 BUG(必须修)

  1. HiapiCloudLicense static 块:Windows 上 Files.deleteSystem.load 的 DLL 会抛异常 → 启动崩。
  2. 心跳/连接失败 exit(0):会把客户生产进程拖垮;且授权服务器一抖动全体崩。
  3. C++ loadClass 的 DefineClass 循环里多一个 i++(应删)。
  4. AES key/iv 全网硬编码且写死oFUtQE7...),jar 放公开 OSS——必须改按客户密钥 + 服务器下发。
  5. nuwa/license-server 授权是:clientId 写死 1000,心跳永远返回正常——要做成真校验。

4. 分阶段开发计划(按顺序)

贯穿原则:每个强制点挂开关,默认监控/宽松;现网先激活并 grandfather;启动失败要干净(这正是"起不来"),但运行中断网给宽限别崩;任何阶段可独立回退。

阶段 0 · nuwa 授权服务地基(牙齿,和生产隔离,最先做)

目标:把真授权能力建起来,先不接客户端。 任务

  • internal/license/ 领域 + internal/httpapi/license_handler.go + internal/repository/license_repo.go
  • 数据表(MySQL/GORM):
    • customers(套餐、max_instancesmax_tenants、到期、状态)
    • installs(install_id、customer、首次激活、状态)
    • instances(instance_uuid、install_id、最近心跳、出口IP)—— 浮动并发计数
    • tenant_grants(已发租户名额)
    • module_keys(每客户的模块解密密钥)
    • encrypted_modules(按客户加密的 hiapi-core-public 产物,或存对象存储的引用)
    • watermarks(customer ↔ 水印标识)
    • revocations(吊销列表)
  • Ed25519 签发/验签(弃旧 RSA 分块)。
  • 接口(TLS + 签名 + nonce/timestamp 防重放):
    • POST /license/activate → 校验授权key+配额 → 生成/返回 install_id + 签名票据
    • POST /license/heartbeat → 浮动计数、刷票据、下发吊销、克隆检测
    • POST /license/module/fetch → 校验授权 → 返回按客户密钥加密的闸门模块
    • POST /license/tenant/report → 上报租户数 → 超额检测/告警
    • 管理后台:客户/配额/水印 管理(复用 nuwa 现有 bearer-token 中间件) 生产影响:无。 完成判据:能独立联调激活/心跳/下发/配额。

阶段 1 · 加载器修正 + 按客户密钥下发

目标:客户端接上真授权,闸门成型。 任务

  • 加载器联 nuwa(替换写死域名),激活拿票据 + install_id(存 K8s Secret/PVC)。
  • 从 nuwa 下发加密闸门模块(替换公开 OSS);按客户独立 AES 密钥(替换硬编码)。
  • 本地解密 → DefineClass 加载(沿用现机制,修掉 i++ bug)。
  • 修 Windows 删 .so 崩(加载后不删 / deleteOnExit)。
  • 去掉裸 exit(0):启动期无授权/超额 → 干净拒绝启动(这就是"起不来");运行期断网 → 离线宽限期(建议 7~14 天)后降级,不崩生产
  • 机器/install 绑定(k8s 用 install_id,不用硬件指纹)。 生产影响:先监控模式(只激活+心跳+日志,不强制);给现网先激活、grandfather。带 kill-switch。 完成判据:现网在监控模式稳定;下发/解密/加载链路通;bug 全修。

阶段 2 · 配额强制(实例 / 租户)

目标:真正能"控制开通多少租户/多少实例"。 任务

  • 浮动并发实例计数(心跳统计同时在线 instance_uuid,对照 max_instances,停心跳 60~90s 回收)。
  • 租户配额(创建租户处校验 + tenant/report 对账)。
  • 克隆检测(同 install_id 多出口IP/集群并发 → 标记/吊销)。
  • 强制力度:alert-only → 软提示 → 硬拒绝新增超额;已在跑的放行。 生产影响:逐项、逐 install 灰度。 完成判据:超额能拦/能告警;老实例不受影响。

阶段 3 · 水印 + ProGuard 混淆

目标:可追溯 + 增强"加密感"。 任务

  • 每客户独立构建,注入唯一水印(无害常量/资源顺序/隐写 ID),入库 customer ↔ 水印
  • 免费 ProGuard 过一遍 hiapi-core-public(配好 Spring keep 规则:实体、DTO、Controller、@Service 名等不能乱改)。
  • (可选)保留简化版 native 加载器/反调试,纯为"加密感"+抬高随手门槛,不依赖其保密。 生产影响:改构建,不动运行数据;需功能回归。 完成判据:泄漏样本能提取水印定位客户;混淆后功能正常。

阶段 4 · 上线 + 退役旧件 + 合同

任务

  • 全量启用强制(确保所有 install 已激活、在配额内)。
  • 下线 hiapi-cloud-license-server,域名指向 nuwa。
  • 清理 hiapi-core-cpp 中已废弃部分(加密 jar/OSS/硬编码 key),保留修正后的加载器;归档不用的。
  • 授权合同条款写清:授权范围、实例/租户上限、禁止转售/公开源码、审计权、违约责任。 完成判据:旧服务下线;合同到位。

5. 生产安全红线(贯穿所有阶段)

  • 现有加载器的 exit(0) 和 Windows 删 .so 会崩生产,阶段 1 必修。
  • 升级先监控模式,现网先激活 + grandfather
  • 启动失败=干净拒绝(要的就是这个);运行中断网=宽限+降级,绝不崩
  • 授权服务器要高可用 + 客户端缓存票据,避免你一抖动全体客户挂。
  • 每个强制点挂开关,可独立回退。

6. 优先级(性价比)

  1. 阶段 0 nuwa 真授权 + 配额 + 水印登记(牙齿,先做,隔离生产)。
  2. 阶段 1 加载器修正 + 按客户下发(闸门成型 + 修崩生产的 bug)。
  3. 阶段 2 配额强制(实现"控制租户/实例数")。
  4. 阶段 3 水印 + ProGuard(追溯 + 加密感,免费)。
  5. 阶段 4 上线退役 + 合同

一句话:牙齿在"联网授权+配额+水印+合同",加密只是让闸门有"加密感"+挡懒人。把力气按上面顺序花,别在保密强度上烧钱。