swcenc 加密器 · 离线加密器发行与授权中心
客服邮箱 admin@xueyuanpie.com

swcenc 2.0 —— Swoole Compiler 同款离线加密器

把明文 PHP 源码打包成 swoole_loader 扩展可以直接加载执行的加密文件。

和官方 Swoole Compiler 是同一类东西:离线加密器(源码不出本机)+ 配套 loader。

2.0 相比 1.0 的三件事:

1.02.0
依赖要装 Python3 + 目标版本 PHP + opcache零依赖:自带 Python + PHP 7.0–8.4 运行时(Linux 还自带 glibc)
授权无机器码 + 有效期 + 版本权益,离线校验(RSA-2048 签名,改一个字就失效)
产物控制只能加密绑定域名 / IP / 到期,产物换个站或过了期就跑不起来
平台LinuxLinux x86_64 + Windows x64

一、30 秒上手

# 0) 授权:先拿机器码去换授权文件
./bin/swcenc machine
#    机器码: SWC-XXXX-XXXX-XXXX
#    把机器码发给签发者,拿到 license.json 后放到 ./license/license.json

./bin/swcenc license              # 看授权状态
./bin/swcenc doctor               # 环境自检:能用哪些 (loader, PHP) 组合

# 1) 加密单个文件(PHP 8.3 / loader 3.2)
./bin/swcenc pack app/common.php -o out/common.php --php 8.3

# 2) 整目录加密 + 逐个用真实 loader 验证
./bin/swcenc batch ./app -o ./app_enc --php 8.3 --verify

# 3) 绑定域名与到期(客户最常用的两个开关)
./bin/swcenc batch ./app -o ./app_enc --php 8.3 \
    --domains "example.com,*.example.com" --expire 2027-01-01

Windows 上是同一个用法,把 ./bin/swcenc 换成 bin\swcenc.exe:

bin\swcenc.exe machine
bin\swcenc.exe pack app\common.php -o out\common.php --php 8.3 --domains "example.com"
bin\swcenc.exe doctor
  • 便携包:解压后运行 bin\swcenc.exe(同目录还有 bin\swcenc.cmd,等价)。
  • 安装包:装到 %LOCALAPPDATA%\swcenc(用户级,不弹 UAC),桌面与开始菜单会有

「swcenc 加密器」快捷方式;命令行用完整路径

"%LOCALAPPDATA%\swcenc\bin\swcenc.exe" doctor。

想让任意目录直接敲 swcenc,把 %LOCALAPPDATA%\swcenc\bin 自己加进 PATH 即可

(安装器刻意不动你的 PATH)。

不带参数运行就是交互式菜单(1 自检 / 2 看授权 / 3 加密单文件 / 4 加密整目录 / 5 机器码)。

装到系统里(可选):

sudo ./install.sh            # Linux:装到 /opt/swcenc 并建 /usr/local/bin/swcenc

二、产物怎么跑起来

产物只有在目标机上装了对应那一个版本的 loader 才能执行:

; php.ini
extension=swoole_loader83_nts.so      ; Linux

三条硬规则,先看清再动手:

规则说明
单版本产物只能跑在与加密时相同的 PHP 主次版本上。8.3 加的密只能在 8.3 跑。
单代数loader 3.1 与 3.2 的产物互不通用,头块里写着代数。
Pro 独立--pro 产物只能由 swoole_loader_pro 加载;官方 loader 加载会直接段错误。

./bin/swcenc versions 会打印当前包里 loader × PHP 的完整支持矩阵。


三、命令与选项

swcenc <命令> [选项]

命令
  pack <文件>   -o <输出文件>      打包单个文件
  batch <目录>  -o <输出目录>      批量打包,保持相对路径
  info   <文件>                    查看容器信息
  unpack <文件> -o <输出二进制>     解出容器载荷
  versions                         loader × PHP 支持矩阵
  caps                             各版本能力分层(JSON)
  doctor                           环境自检(含授权状态与内置运行时)
  machine                          打印本机机器码(换授权用)
  license                          查看授权状态

通用选项(pack / batch)
  --php 7.3 | 8.1 ...   目标 PHP 版本(必须与目标服务器一致)
  --loader-version 3.1|3.2          写进头块的 loader 代数(默认 3.2)
  --mode strong|weak                strong=字节码载荷(默认);weak=源码随容器下发
  --verify                          打包后用真实 loader 执行一遍做验证(Linux)
  -j, --jobs N                      batch 的并发数

产物绑定
  --domains a.com,*.b.com           只允许这些域名运行(Web 请求;CLI 默认放行)
  --ips 1.2.3.4,...                 只允许这些来访 IP
  --expire 2027-01-01               到期日(当天结束前仍可用;Web 与 CLI 都会拦)
  --bind-cli                        CLI 也检查域名(默认不检查,见下)
  --bind-quiet                      绑定不通过时不提示原因,只回 403

加固 / Pro
  --pro                             Pro 层(只能配 Pro loader)
  --swc-strict / --swc-calibrate / --swc-encode-ops
                                    与官方同款的诱饵字节 / 编码态 op 等加固
  --guard / --no-guard              运行期反分析自检层(--pro 默认开)
  --scatter off|light|full|mangle   粉碎性重组打散(--pro 默认 full)

授权
  --license <文件>                  指定授权文件路径

四、产物绑定(域名 / IP / 到期)

为什么需要:加密只保证「代码不被读」,不保证「谁都能跑」。客户把加密包交付给下线之后,

真正要控制的是「这份产物能在哪个站、到什么时候为止运行」。

./bin/swcenc pack app.php -o app.enc.php --php 8.3 \
    --domains "customer.com,*.customer.com" \
    --ips "1.2.3.4" \
    --expire 2027-01-01

行为(三条都是刻意的设计):

  • 域名 / IP 只拦 Web 请求,CLI 默认放行 —— 否则客户的定时任务、队列 worker 会集体挂掉,

那是售后灾难而不是保护。要连 CLI 一起绑,加 --bind-cli。

  • 到期是绝对的:Web 与 CLI 都会拦。到期就该停。
  • 域名匹配支持通配前缀:*.example.com 匹配 a.example.com、b.a.example.com,

也匹配 example.com 本身。

绑定层与源码一起被编译进载荷(不是可读的配置),命中不允许的环境时输出:

This script is not licensed to run here (host evil.com).
This script is not licensed to run here (expired on 2027-01-01).
绑定检查发生在每次请求,开销是一次数组比较,可以忽略。

五、授权(机器码 / 有效期 / 版本权益)

授权是离线的:客户机器不需要联网,签发者也不需要部署授权服务器。

./bin/swcenc machine      # 客户把这一行发给签发者
./bin/swcenc license      # 授权状态、功能位、可绑定域名

授权文件(license/license.json)由签发者用私钥签名,工具内置公钥校验:

  • 客户改一个字节 → 签名立刻不匹配(RSA-2048 + SHA-256 / PKCS#1 v1.5);
  • 授权里写死 machines(机器码列表)与 not_after(到期日),换机器或过期就用不了;
  • 版本权益(edition)决定哪些功能可用:
editionstrongbatchprobinddecoy
trial✅
std✅✅
pro✅✅✅✅
enterprise✅✅✅✅✅

授权文件按这个顺序查找:--license 指定 → SWCENC_LICENSE → 包内 license/license.json

→ ~/.swcenc/license.json → /etc/swcenc/license.json。

机器码由「系统 id + 第一块物理网卡 MAC + CPU 型号」算出(Windows 用 MachineGuid +
系统卷序列号 + MAC)。容器里 MAC 每次重建都会变,所以别把加密器装在会重建的容器里,
否则会一直要重新授权。

六、零依赖是怎么做到的

组件LinuxWindows
解释器自带 Python 3.12(含标准库)自带免安装 Python 3.12
PHP 运行时自带 PHP 7.0–8.4(runtime/php/<版本>/)自带官方 NTS x64 的 php.exe + php_opcache.dll
系统库自带 glibc 与全部依赖 .so(runtime/lib/,用自带的 ld.so 启动)自带 VC 运行时(vcruntime140*.dll)

所以客户机上什么都不用装 —— 实测在一台「没有 glibc、没有 PHP、没有 Python」的

Alpine 容器里,license / doctor / pack --verify 与产物执行全部正常。

发行包里也没有加密器自身的源码

引擎不是以 .py 形式交付的:

平台引擎形态包里 .py 数量
Linux12 个模块 Cython 编译成 .so(原生机器码)0
Windows编译成 .pyc 字节码0

授权校验写在编译产物里:ENFORCED_BY_BUILD 这个常量在打包时被烘焙成 True,

所以 SWCENC_ENFORCE=0 ./bin/swcenc pack ... 这种绕过尝试照样被授权拦住 ——

"要不要校验授权"只存在于编译出来的机器码里,既改不了也没有源码可改。

doctor 会明确告诉你用的是内置运行时还是系统里找到的:

  ✅ 内置运行时:/opt/swcenc/runtime
           PHP 10 个版本,Python:自带 —— 客户机不需要装任何东西

七、目录结构

swcenc-2.0.0-linux-x86_64/           swcenc-2.0.0-win64/
├─ bin/swcenc            启动器      ├─ bin/swcenc.exe      启动器(原生,双击出菜单)
│                                     └─ bin/swcenc.cmd      备用启动器
├─ runtime/                          ├─ runtime/
│  ├─ lib/      自带 glibc + .so     │  ├─ php/<版本>/bin/php.exe + php8.dll
│  ├─ php/70..84/                    │  │              ext/php_opcache.dll
│  └─ python/   自带解释器           │  └─ python/   免安装解释器
├─ engine/                           引擎(无 .py:Linux 为 .so,Windows 为 .pyc)
│  ├─ pack/     打包器 + 自检层 + 绑定层 + 授权模块(编译产物)
│  ├─ rev/      逆向数据(op 表 / 诱饵表 / vm 规格,编译产物)
│  ├─ loader31/ loader32/           官方 loader(--verify 与交付给目标机)
│  └─ loaderpro31/ loaderpro32/     Pro loader
├─ license/     public_key.pem + 放 license.json 的地方
├─ examples/
└─ README.md  USAGE.md  INSTALL.md

八、常见问题

Q:--verify 报「真实 loader 加载执行通过 ✅」是什么意思?

产物真的被对应版本的 loader 加载并执行了一遍,输出与原文件一致。这是最硬的验证。

Q:Windows 上为什么不做 --verify?

swoole_loader 是 Linux 扩展(.so),Windows 的 PHP 加载不了它。Windows 上打包会明确

提示跳过验证,请把产物部署到目标服务器验证。需要逐次验证的 PRO 产物建议在 Linux 机器上打包。

Q:哪些 PHP 版本实测能跑通?

发行包里带真实 loader 逐个组合跑过的结果(Alpine 容器,--verify 通过才算数):

目标 PHPloader 3.1loader 3.2说明
7.0 / 7.1 / 7.2❌❌加载时段错误(见下一条)
7.3 / 7.4✅✅含 --swc-strict
8.0 / 8.1✅✅
8.2 / 8.3 / 8.4—(官方 loader 3.1 没有这几个版本)✅含 --pro(8.3 实测)

Q:7.0 / 7.1 / 7.2 为什么不行?

这是引擎本身的现状,不是本工具引入的:用 swoole_loader70/71/72_nts.so 加载对应版本

产出的产物会在载入时段错误(实测环境:PHP 7.0.33 / 7.1.33 / 7.2.33,带与不带 opcache

都一样;同样的问题在线上服务上一模一样地复现)。所以:

  • 建议目标 PHP 7.3 及以上 —— 这几个版本是全组合实测通过的;
  • 确实要交付 7.0–7.2,请先在你的目标机上用一个最小的 PHP 文件试一次再批量;
  • 7.0 / 7.1 上的 --pro / --swc-strict 另有限制:引擎会 fail-closed(宁可报错也不产出

被弱化的"PRO 产物")。

Q:Windows 上能用 --pro / --swc-strict 吗?

只能配 PHP 7.0 / 7.1。7.2+ 的加固层要用一个只在 Linux 上构建的转储扩展,Windows 的 PHP

加载不了它(.so 不是 .dll),所以那两档在 Windows 上会被明确拒绝(不会偷偷降级成弱产物)。

要出加固 / Pro 产物、或者要逐文件 --verify,在 Linux 上打包 —— 那边是全组合支持的。

Windows 上出普通 strong 产物、做产物绑定、取机器码、管理授权都没问题。

Q:产物换目录部署,路径会不会错?

不会。打包时会抹掉载荷里内嵌的构建路径(__FILE__ / __DIR__ 相关),

产物放到哪台机器、哪个目录都能跑。

Q:为什么引擎目录里看不到 .py 文件?

故意的。引擎已编译(Linux .so / Windows .pyc),授权校验也在编译产物内。

改动这些文件会让工具无法启动。

Q:Windows 上装的是 setup.exe,不想装怎么办?

用便携包 swcenc-2.0.0-win64.zip,解压后运行 bin\swcenc.exe,不写注册表也不进 PATH。

安装包同样可以随时在「程序和功能」里卸载干净。

Q:weak 模式是什么?

源码随容器下发(有 loader 守卫,但源码以明文存在于文件里)。适合本机调试或

只要「不被随手改」的场景。正式交付请用默认的 strong。

Q:同一个项目要同时支持 PHP 7.4 和 8.3 怎么办?

Swoole 是单版本加密,所以分别打包两次(--php 7.4 / --php 8.3),

在目标机上按 PHP 版本选用对应产物。


九、安全与合规

  • 只对你拥有合法授权的源码使用本工具。
  • 加密强度取决于目标 loader 与所选加固档位;--pro + --scatter full + --guard

是当前最强的组合。

  • 授权私钥不在发行包里;包内 license/public_key.pem 只能用于校验,不能签发。
文档为随发行包一起提供的原文(docs/README.md)。 下载发行包后可离线查看同样的内容。