每次发 PHP 编译器 BPC 新版本 的文章/帖子,都有会网友评论说为什么不用 go/java/.net 或者其它别的语言.
今天就来说说为什么?
最初决定要开发 BPC 是为了想要本地部署云招 OurATS 的一个核心组件 简历解析器 bob-parser.
bob-parser 是用 PHP 开发的,而 PHP 的源码加密方案没有找到一个 100%可靠的,并且还想解决软件授权问题.
有网友一提到源码保护什么的,老是会说你的代码是有多好,多有价值,给我我也不看,屎山一堆.
这个问题我们后边再讨论.
但云招的做事风格大致就是这样,想要解决一个问题时,就会尽可能地想把这个问题解决好.
开发了 BPC 一段时间后,发现实际上不只能解决 php cli 程序的编译,php web 项目通过编译成动态链接库当作 module 嵌入 apache 就好了,再进一步,引入了 althttpd, apache 也不需要了.
云招 OurATS 是一个招聘管理系统, ATS 是 Applicant Tracking System 的缩写.
非这个领域的人一开始往往会把 ATS 和招聘渠道(Jobboard)弄混.
招聘渠道是指 Boss 直聘/智联招聘/51job 等面向求职者的网站.
企业从招聘渠道获取到简历后,或者说候选人把简历投递给企业后,下一步进行 简历筛选/征求用人部门意见/安排面试/Offer 审批/Offer 发放... 等工作时需要的 申请追踪系统 就是 ATS.
当然现在的招聘渠道企业后台可能也有一部分 ATS 的功能.
云招 OurATS 没怎么搞市场推广,所以虽然我们从 2010 年就开始做了,很多网友可能没听说过.
这里列几个大家可能听过/用过的招聘管理系统.
有些网友认为开发一套招聘管理系统没什么难的,找几个人搞个半年还能搞不出来?
我们来看看实际案例.
北森在 2019 重构了它的招聘管理系统,在其官网发布的文章中这样说:
2019 年,北森基于 Nature Design3.0“高效、愉悦、温暖”的设计理念,历时 3 年,斥资 2 亿人民币,重塑新一代体验优先的招聘管理系统。
文章链接: https://www.beisen.com/res/848.html
显然,北森的这次重构应该没有更换技术栈,从其 招聘的岗位 来看,开发语言应该是 java/.net.
在不更换开发语言的情况下,重做一个招聘管理系统的成本是 3 年 + 2 亿人民币.
如果换语言的,成本恐怕不只这么多了.
那么这个历时 3 年,斥资 2 亿人民币,重塑新一代的招聘系统有惊艳了市场吗?看看北森在港股的表现就知道了.
在脉脉上经常看到 Moka 比北森好的评价,可是在脉脉上 Moka 比北森裁员裁和还狠.
如果还有网友不信邪,可以下水试一试,反正国内做 ATS 的也没几家,机会还有.
云招 OurATS 从 2010 年开始,到今年已经持续开发了 15 年,代码库现存代码上千万行,换语言重构的成本不好估量.
而 PHP 编译器 BPC 从开始开发到成功编译云招 OurATS,用了 3 年,资金投入约 500 万人民币.
说到底,PHP 真是世界上最好的语言呀!
首先,完美解决了源码保护,软件授权这两大基本需求.
如果换 java/.net 的话,这两个语言的反编译比 PHP 成熟多了.
GraalVM 和 .NET 8 的 Native AOT 是否好用还不好说.
如果换 go 的话,源码保护是没问题,但需要解决软件授权的问题,当然 java/.net 也需要解决这个问题.
BPC 编译还带来了额外好处:
软件交付变得简单了.
整个云招 OurATS 招聘系统被编译成了一个二进制可执行文件,日常升级维护就是替换这一个文件(当然整个系统的运行还需要其它几个辅助程序).
运行环境更安全了.
生产环境不需要 PHP 解释器,因为 PHP 源码已经被 BPC 最终转译成 C,然后编译成可执行文件了.
也就是说,服务器上不能执行 PHP 代码,很多针对 PHP 的攻击手段失效了.
合作方式更灵活
PHP 项目源码保护的一个做法是使用编译型语言编写部分核心逻辑,然后其它代码开源.
有了 BPC 之后,完全可以把核心 PHP 代码编译成动态链接库,其它部分开源.
BPC 的目标是源码保护和软件授权,现阶段没有在生成代码和运行性能上做特别的优化.
因此虽然是编译成 C,但性能在大多数场景下还不如解释执行的 PHP 快.
所以如果是性能敏感的项目慎用.
![]() |
1
a33291 53 天前
> 如果换 java/.net 的话,这两个语言的反编译比 PHP 成熟多了.
关于这一点,据我了解,成熟可靠的保护方案也非常多。 至于 aot ,只能说比“源码级”的反编译难一点,有能力的大佬就是人肉“汇编反编译器”,没有太大区别。 aot 的特色也不是“安全” |
![]() |
2
skyworker 53 天前
其实用 swoole 加密的安全性也没问题, 虽然 swoole 加密需要付费, 不过这笔费用对于需要私有化部署产品的公司而言, 成本并不高.
主要是把 php 代码迁移到 BPC, 环境变化太大, 不清楚到底有多少坑要踩 |
![]() |
3
heguangyu5 OP |
![]() |
4
heguangyu5 OP |
![]() |
5
skyworker 53 天前
@heguangyu5 至少目前为止, 普通人能接触到的途径, 还没有找到能对最新版 swoole 加密过的 php 代码能解密的途径, 我试过很多渠道, 都是"这玩意没法解密".
当然, 不排除很多更隐秘的渠道,能解密 swoole 加密过的 php 代码, 不过这样基本上对我们来说就够了. 如果用户能找到解密 swoole 加密代码的渠道, 这客户的技术水平应该比我们更强, 也不担心用户看我们产品的代码了. |
![]() |
6
skyworker 53 天前
@heguangyu5 "对于没有测试用例保障的项目来说,迁移到 BPC 确实是你说的"不清楚到底有多少坑要踩"
测试用例要多少才覆盖这种"底层可能有 bug"的行为哪? 正常业务流程测试? 模拟 100 个并发测试? 模拟多少个协程并发会引起堆栈错误? 模拟用户输入中有 emoj 特殊字符会不会引起编码错误? 这需要测试的地方就太多了 |
![]() |
7
janus77 53 天前
接着楼上说的,如果你要推广 BPC ,可以官方提供一下测试套件之类的东西
|
![]() |
8
janus77 53 天前
@janus77 #7 举个例子像 GMS 认证测试,就是谷歌官方提供的测试流程和测试套件,这对于这种情况很有必要: https://blog.csdn.net/a546036242/article/details/136850924
|
![]() |
9
heguangyu5 OP @skyworker
一段 php 程序,给定一个输入,得到一个或一些输出. 用 BPC 编译替换掉这段 php 程序,给定同样的输入,如果能得到同样的输出,那就够了. 此时外部已经无法分辨处理这处事情的程序是 php 还后 BPC 编译后的程序. "底层可能有 bug"这种担心怎么说呢?我在开发 BPC 的过程中还发现了 php 的两个 bug,但是这并不影响我每天都用 php. 1. https://bugs.php.net/bug.php?id=81312 2. https://github.com/php/php-src/issues/12715 测试覆盖到你觉得你的程序没问题就够了. 比如 BPC 跑过了 php 的 phpt 测试后,我觉得 BPC 做到这里就够了. BPC 跑通了云招 OurATS 的测试用例后,我觉得云招 OurATS 就够了. 如果你觉得无论多少测试都不能让你放心,那这就无解了,总要有个信任基础的. |
![]() |
10
heguangyu5 OP @janus77 BPC 的测试就是随 PHP 源码发布的 phpt 测试, @see https://github.com/bob-php-compiler/bpc-release/wiki/04_phpt_tests
|
![]() |
11
heguangyu5 OP @skyworker 另外 php 和 BPC 不是二选一的问题,我们自己日常还是用 php 环境开发,只是在本地部署的项目上用 BPC 编译后发布出去.
|
![]() |
12
a33291 53 天前
@heguangyu5 #4
应该比较好找,商业的功能比较强大 java 的话有个叫 virbox 的,但是我没有用过,我接触过的 java 保护机制一般也就是混淆一下,比如 smartgit 等都是这样 .net 的话效果较好的有 vmp ,dn-guard ,smartassembly 强度都非常好,前 2 这基于虚拟化的更胜一筹 现在 java 的 jd-gui 和.net 的 de4dot 以及 dnspy 基本上都停滞发展了,对于一些新的特性支持不好。所以使用较新版本的 runtime/sdk 也可以一定程度上提升“安全性” |
![]() |
13
heguangyu5 OP @a33291 非常感谢!
|
![]() |
14
iminto 52 天前 via Android
@heguangyu5
上混淆后,代码强度就上来了,这是最简单的。 然后 jni 实现核心逻辑,dll/so 文件的反编译难度就上来了。 我目前的做法是,部分核心代码用 jni ,然后加壳,再对壳做一个简单加密,最后做一次混淆。 相当于有了 4 层保护。 运行时,java 代码对 so 进行解密,后面就交给 jni 了。 部分步骤其实很好破解,但要的就是给破解的人上难度,这就够了。 |