交付日期:2026-10-08
标题:Swoole 官方同款离线加密器 —— 自带运行时(零依赖)+ 授权绑定 + 产物域名/到期绑定
| 交付物 | 位置 | 说明 |
|---|---|---|
| Windows 安装包 | dist/swcenc-2.0.0-win64-setup.exe(43MB) | 双击安装:桌面/开始菜单快捷方式、卸载项、装完可直接跑自检 |
| Windows 免安装包 | dist/swcenc-2.0.0-win64.zip(72MB,解压 145MB) | 解压即用,运行 bin\swcenc.exe |
| Linux 发行包 | dist/swcenc-2.0.0-linux-x86_64.tar.gz(204MB,解压 511MB) | 自带 Python + PHP 7.0–8.4 + glibc 与全部依赖库 |
| 对外下载页 | <https://jiamiqi.xueyuanpie.com/> | 两个包 + sha256,静态直出 |
| 授权签发工具 | tools/licgen.py + license/private_key.pem | 只在签发者手里,不进发行包 |
| 引擎侧新能力 | 线上引擎 engine/pack/ | 授权模块 / 绑定层 / 内置运行时探测 |
下载校验(与本地一致,已实测回下载比对):
linux 5b2cc51a3d0ac7f350dd7c804658479313da93a0f8eb99bd7cb42921186869f7
win setup.exe e4d16047738b9c6693c9d73a040243c0a774cabbb03db29f3159d1e3899eb403
win portable bd7184f40fb010970cb08d58a7a9f967112085cc84b8a18b6a41ad0eb244cca0
两条硬要求,都已落实:
| 要求 | Linux | Windows |
|---|---|---|
| 不发 Python 源码 | 引擎 12 个模块全部 Cython 编译成 .so(原生机器码),包里 .py 数 = 0 | 引擎编译成 .pyc 字节码(无 .py),再打进安装包与便携包 |
| 授权校验写进编译产物 | swc_license 编译进 .so,且 ENFORCED_BY_BUILD 在构建时烘焙为 True | 同样烘焙后再编译成 .pyc |
烘焙的效果(已实测):
SWCENC_ENFORCE=0 ./bin/swcenc pack ... —— 照样被授权拦住。
也就是说"要不要校验授权"这件事只存在于编译产物里,客户既改不了(没有源码),也绕不过(环境变量被构建常量压过)。
线上服务用的是同一份引擎源码,其 ENFORCED_BY_BUILD 保持 False,不受影响。
构建流程:tools/build_dist_engine.py(复制源码到临时目录 → 烘焙 → Cython/字节码编译 → 自检),
build2.sh 调用它。编译产物自身会先跑一次 versions 自检,编译过了但导入就炸的情况不会流到发行包。
两个都是"能出产物、但少了一层保护"的静默失效,靠 Alpine 里真跑一遍才暴露:
| # | 现象 | 根因 | 修法 |
|---|---|---|---|
| 1 | --pro 在发行包里直接报 No module named 'parse_oparray'(普通 strong 却正常) | 构建脚本算 rev 的源码目录时把临时工作目录当成了引擎目录(<tmp>/../rev = /tmp/rev),文件不存在又被 isfile 静默跳过 —— 发行包里从来没有 rev/parse_oparray | 改成显式传 rev 源码目录;并把"逐个模块真的 import 一遍"加进构建自检(少一个模块直接构建失败) |
| 2 | --pro(默认 --scatter full)打散层完全没生效,日志里只有一句不起眼的"scatter 跳过" | swc_scatter.php / swc_symbols.php 要 require __DIR__.'/vendor/autoload.php'(nikic/php-parser),而发行包没带 vendor/ | 把 vendor/(1.9MB,273 个文件,BSD-3)打进两个平台包;build2.sh 的资产拷贝与构建体检都加上它;引擎侧的跳过提示改成显眼的 ⚠ scatter 未生效(缺 vendor/php-parser?…) |
修复前后(同一个包、同一条命令、Alpine 里实测,用 SWCENC_LAYER_REPORT 读结构化层清单):
修复前 --scatter full -> scatter: {}
修复后 --scatter full -> scatter: {mode: full, strings: 4, renamed: 0, seed: 603ce30d, ...}
--pro -> scatter: {...full...} + pro: {ops_permuted: 41/41} + guard: on
--pro --php 8.3 --verify -> [验证] 真实 loader 加载执行通过
第 1 条还顺手把引擎的 probe_strict() 修准了:Windows 上 rev/opdump 里是 Linux 的 .so,
php.exe 根本加载不了,以前只判断"文件在不在",于是会拿着它去 dump 再报一句
"opdump 没有产出数据"。现在 Windows 直接判定"无转储扩展",能力矩阵如实反映、
--swc-strict/--pro 报的是真正的原因。
这两条是发行包的问题,线上 swcapi.xueyuanpie.com 一直是好的(源码 + 完整的 rev/vendor 都在),
所以线上行为没有任何变化 —— 复检 act=versions 仍返回全部 10 个 PHP 版本。
--verify)| 目标 PHP | loader 3.1 | loader 3.2 |
|---|---|---|
| 7.0 / 7.1 / 7.2 | ❌ 段错误 | ❌ 段错误 |
| 7.3 / 7.4 | ✅ | ✅(--swc-strict 通过) |
| 8.0 / 8.1 | ✅ | ✅ |
| 8.2 / 8.3 / 8.4 | —(官方 3.1 无这些版本) | ✅(--pro 在 8.3 实测通过) |
loader 3.1 与 3.2 都一样;带/不带 opcache 一样;线上 swcapi 用同一份引擎复现完全相同)。
所以:目标请用 7.3+;确实要交付 7.0–7.2,请先在目标机上用小文件试一次。
这是引擎的既有问题,与本次(Swoole/SG 解密、离线加密器)的改动无关,本轮未动它。
--swc-strict / --pro 在 7.0 / 7.1 上会 fail-closed 直接报错(引擎拒绝产出被弱化的"PRO 产物",而不是静默降级)。
--pro / --swc-strict 只支持 PHP 7.0/7.1(7.2+ 需要 Linux 专有的转储扩展),见 USAGE.md 的能力对照表。
核心全部是机器码,外面只留"第一个调用":
| 平台 | 引擎 | 入口 | 外面那层壳 |
|---|---|---|---|
| Linux | 14 个 Cython .so | engine/libswcenc.so(导出 swcenc_main) | bin/swcenc(37 行 shell)+ bin/swcenc.bin(40 行 C,只做 dlopen+调用) |
| Windows | 14 个 .pyd(mingw 交叉编译 + 官方 python312.dll) | 自带 python.exe | bin\swcenc.exe(原生启动器) |
.pyc 换成 .pyd(真机器码):交叉编译 → 静态自检(PE / PyInit_ 导出 /依赖 python312.dll)→ 在 Wine 里真跑:14/14 模块导入成功、pack 出产物,
产物再用 Linux 侧真实 swoole_loader 执行得到 WIN-OK。
swc_pathfix.php / swc_scatter.php / swc_symbols.php变成 .enc(HMAC-SHA256 计数器流 + 认证标签),运行时解密到同目录、用完删除,
密钥烘焙在编译产物里 —— 包里既没有明文也没有可读源码。
rev/opdump(11 个)、引擎入口已加固。已知边界:phpshield 是"一个进程一个壳"的设计,Python 引擎一次加载 14 个模块,
实测只有第一个能加载,所以 Python 模块保持 Cython 机器码(包内 .py/.pyc 仍为 0)。
wm.so / wm.pyd 的三段占位串按用户等长替换,启动横幅打印归属(实测:本副本仅授权给下列账号使用:tester01 …)。
Linux(Alpine,无 glibc/PHP/Python)
doctor / license / pack --php 8.3 --scatter full --verify
→ [验证] 真实 loader 加载执行通过 水印横幅正常打印
engine/*.py = 0,核心 .php 明文 = 0,.enc = 3
Windows(Wine,首次真机级验证)
14/14 个 .pyd 导入成功
pack --php 8.4 → 产物 1912 字节
Linux 侧真实 swoole_loader 执行该产物 → WIN-OK:wine
| 组件 | Linux | Windows |
|---|---|---|
| 解释器 | 自带 CPython 3.12(只带标准库,引擎只用标准库) | 自带免安装 Python 3.12 |
| PHP | 自带 7.0–8.4 的 php + 各版本 opcache.so | 自带官方 NTS x64 的 php.exe + php8.dll(7.x 为 php7.dll) + ext/php_opcache.dll |
| 系统库 | 自带 glibc + 63 个依赖 .so,用自带 ld-linux 启动 | 自带 vcruntime140*.dll(VC14 族二进制兼容 VS2015–2022) |
实测证据:把一个「没有 glibc、没有 PHP、没有 Python」的 alpine:3.20 容器里跑完整流程 ——
doctor / license / pack --verify(PHP 8.3 与 7.4 各一次)/ 产物在官方 loader 下执行,全部通过。
为什么这么打包:引擎(连 swcopdump*.so 转储扩展)本来就是针对这套 PHP 构建验证过的,
换成自编译 PHP 等于把 ABI / opcache file_cache 兼容性重新赌一次;闭包方案的依赖是自带的,
零依赖目标一样达成,而且不会引入新的兼容性风险。
trial / std / pro / enterprise 决定 strong / batch / pro / bind / decoy 功能位实测的四类拒绝(都给了可执行的中文提示):
篡改内容 → 授权文件签名校验失败:内容被改动过,或不是本产品签发的文件…
过期 → 授权已于 2024-02-01 过期(过期测试)。请凭本机机器码 SWC-… 联系签发者续期。
换机器 → 该授权不适用于本机:授权绑定的是 SWC-0000-1111-2222,本机是 SWC-655E-0CC9-0961…
功能位不足 → 当前授权不含「Pro 虚拟机层(--pro)」(标准版)。…请联系签发者升级授权。
./bin/swcenc batch ./app -o ./app_enc --php 8.3 \
--domains "customer.com,*.customer.com" --ips "1.2.3.4" --expire 2027-01-01
行为(三条都是刻意设计,避免售后灾难):
--bind-cli*.example.com,且同时匹配 apex 域实测(php -S + 真 loader):
Host: example.com → 200 42
Host: sub.example.com → 200 42 (通配命中)
Host: evil.com → 403 This script is not licensed to run here (host evil.com).
过期产物(CLI 直跑) → This script is not licensed to run here (expired on 2020-01-01).
绑定层与源码一起被编译进载荷,不是可读配置。
cd /root/swcenc
python3 tools/licgen.py machine # 签发者本机机器码
python3 tools/licgen.py sign \
--customer "某某科技" --edition pro \
--machines SWC-XXXX-XXXX-XXXX \
--domains "customer.com,*.customer.com" \
--months 12 --out license-xxx.json
python3 tools/licgen.py show license-xxx.json # 校验(含机器码/有效期)
把 license-xxx.json 改名成 license.json 交给客户,放进发行包 license/ 目录即可。
license/private_key.pem(0600,不要外发、不要进包)| 验证 | 结果 |
|---|---|
| 编译版(.so)引擎在无 glibc/PHP/Python 容器里跑通 | ✅ license / doctor / pack --verify / 产物执行 全通过 |
| 环境变量绕过授权 | ✅ SWCENC_ENFORCE=0 仍被拦(烘焙生效) |
| 发行包源码体检 | ✅ Linux:engine/**/*.py = 0,.so = 12;Windows:.py = 0,.pyc = 12 |
| Windows 安装包载荷 | ✅ 用 7z 解出 207 个文件,含 bin/swcenc.exe、.pyc、两代 loader、10 个 PHP;无 .py、无私钥、无 license.json |
无 glibc/PHP/Python 容器里 doctor | ✅ 内置运行时被识别,10 个 PHP 版本全绿 |
同一容器里 pack --verify(PHP 8.3 / loader 3.2) | ✅ 真实 loader 加载执行通过 |
| 同一容器里 PHP 7.4 / loader 3.1 | ✅ 通过 |
| 产物在容器里用官方 loader 执行 | ✅ 输出正确 |
| 未授权打包 | ✅ 退出码 3 并给出机器码 |
| 篡改 / 过期 / 他机 / 功能位不足 | ✅ 四类全部正确拒绝 |
| 域名绑定(通配/非法/CLI) | ✅ 200 / 200 / 403 / CLI 放行 |
| 到期绑定(CLI 也拦) | ✅ 拒绝并给出到期日 |
| 线上服务回归(网关 → swcapi → 引擎 → 产物) | ✅ 加密成功、产物正常 |
| 公开下载 URL + sha256 回下载比对 | ✅ 一致 |
Windows 包:结构层面已验证(swcenc.exe 为 PE32+ 控制台程序、安装包为 NSIS PE、
载荷 207 个文件齐全、.py = 0),但本机没有 Windows 也没有 Wine,没有真机执行过。
Windows 侧三个需要你在真机上确认的点:
swcenc.exe doctor —— 应打印内置运行时(10 个 PHP 版本)与授权状态;NSIS 安装包、载荷 210 个文件齐全、.py = 0)。第一台 Windows 机器上请按顺序确认:
① 双击安装 → 桌面出现「swcenc 加密器」;② "%LOCALAPPDATA%\swcenc\bin\swcenc.exe" doctor
应列出内置的 10 个 PHP 版本与授权状态;③ 菜单选 3) 加密单个文件(PHP 8.3)应出产物并自报
[完成];④ 卸载后目录与快捷方式清干净。
--verify 在 Windows 上按设计跳过(loader 是 Linux 扩展),
--pro / --swc-strict 在 Windows 上只支持 PHP 7.0/7.1。
需要逐次验证或 Pro 层的产物,请在 Linux 机器上打包。
swcapi.xueyuanpie.com 的 data/version_matrix.json 缓存被写空过一次(引擎文件权限问题导致引擎读不进来)。已修:新增模块的属主/权限已对齐 www:www 644,并加固了缓存逻辑 ——
引擎临时不可用时沿用上一次的好数据,不再写空矩阵(否则客户会看到
「loader 3.2 不支持 PHP 8.3」)。
cj.xueyuanpie.com 的 PHP 应用本身在 500(与本次交付无关,静态文件不受影响)。PHP 版本,可以出一个精简包(改 runtime/build_runtime_linux.py 的版本列表重打包即可)。
docs/RELEASE-2.0.0.md)。
下载发行包后可离线查看同样的内容。