许可证与合规风险:误用GPL/AGPL加密库

加密SDK接入,技术选型只是第一步。

真正让你夜不能寐的,往往不是算法跑得不够快,而是——你用的那个库,到底能不能用在企业产品里?

我见过不止一个团队,花了好几个月接入一个开源的加密库,代码写完了,审查过了,结果法务突然跳出来说:这库是GPL的,不能放。改动,重来,工期泡汤。

咱今天就来聊聊这件事。

GPL/AGPL 的核心陷阱

先明确一件事。

GPL 和 AGPL 不是普通的开源许可证。它们属于“强著佐权”(Strong Copyleft)许可证。说白了,它们的要求是:

  • 如果你在项目里用了GPL的代码,那么你的整个项目——无论是否直接修改——都必须以GPL协议开源。
  • AGPL更激进,它把GPL对“分发”的限制,延伸到了“网络交互”。你架个Web服务,只要用到了AGPL代码,你就必须把完整源码给所有用户。

对企业产品来说,这就非常麻烦了。

你不可能把自研的核心算法、业务逻辑、数据库结构全都公开出去。那不是开源,那是裸奔。

为什么加密库成了“重灾区”?

我遇到过几个真实案例。

有一个团队做金融安全产品,需要RSA和AES的加密实现。他们图省事,直接从GitHub上拉了个高星仓库,star数两千多,看起来靠谱。结果呢?

这个库的许可证是 GPL-3.0-only。他们没有注意到。代码直接静态链接进了主程序。等到内部合规审查时,法务直接叫停。

为什么加密库容易踩这个坑?三个原因:

  1. 加密库往往是“基础设施”——你很少为一个加密算法单独写一个微服务,基本都是直接链接进去。
  2. GPL/AGPL库伪装成“宽松许可”——很多开发者只看README不看LICENSE文件。
  3. 修改了也不行——GPL的传染性不因为你“改了几行代码”就消失。

商业授权 vs 开源许可证

这里有个表格,我把常见的加密库许可类型做了个对比。你对照着看,心里就有底了。

许可证 类型 企业内部使用 分发产品 网络服务 建议
BSD-2/3 宽松 ✓ ✓ ✓ 常用首选
MIT 宽松 ✓ ✓ ✓ 常用首选
Apache-2.0 宽松 ✓ ✓ ✓ 商业友好
LGPL-2.1/3.0 弱著佐权 ✓ 动态链接可豁免 ✓ 需谨慎
GPL-2.0/3.0 强著佐权 ✓ ✗(要求全量开源) ✓ 避免使用
AGPL-3.0 最强著佐权 ✓ ✗ ✗(网络交互也要求开源) 远离

这里有个小细节。

LGPL允许你在动态链接的情况下,不把主程序开源。但是很多加密SDK是纯C写的,你不可能在Java或Go里动态链接C库的细节……所以LGPL有时也救不了你。

最常见的“高危函数”清单

我个人的习惯是:在项目初期,就列一张“高风险函数调用”清单。凡是涉及第三方库的加密接口调用,都必须提前过一遍许可证。

我给你列一个参考清单,这些函数在GPL/AGPL加密库中的出现频率极高:

// 这些函数所在的库,你必须检查许可证
EVP_CIPHER_CTX_new()       // 许多GPL的OpenSSL替代品
RSA_generate_key_ex()       // GnuTLS 或 LibreSSL 变体
EC_KEY_new_by_curve_name()  // 有些mbedTLS分支是GPL的
SHA256_Init()               // 旧版OpenSSL之外的实现
EVP_PKEY_encrypt()          // 不要只看函数名,看库来源

你注意看,上面这些函数本身没有问题。问题在于:你调用的这个实现库的许可证是什么。

同一个函数名,可以在BSD库里有,也可以在GPL库里有。

避坑指南:我踩过的两个坑

踩坑一:静态链接的GPL加密库

我曾经…在一个嵌入式项目中,用了OpenSSL的某个GPL分支实现。当时没在意,直接把整个静态库链接进去了。产品量产之后,客户要求做开源合规审计。结果发现,我们的整个固件都必须以GPL开源。

后果:

  • 重写加密层,改用mbedTLS(Apache-2.0)。
  • 推迟交付2个月。
  • 直接经济损失接近七位数。

避坑二:AGPL的Web API加密库

另一个项目,做API网关的加密模块。后端调用了一个AGPL-3.0的加密解析库。法务发现后说:不行,AGPL要求所有通过此API访问的用户都能获得源码。我们当时是SaaS产品,用户通过浏览器用我们的服务,这不就相当于所有人都必须得到源码吗?

最终,我们换成了Google的Tink库(Apache-2.0),合规通过。

商用授权需要注意什么?

有些库是“双许可证”模式。

比如知名的加密库 OpenSSL,它的原始版本是OpenSSL许可证(类似Apache),但是很多公司会基于它修改发布GPL版本。你从GitHub上拉下来的,不一定是官方版。

再比如 wolfSSL,它提供GPL和商业授权两种选择。如果你的产品是闭源商业软件,你需要购买商业授权,否则就只能用GPL。

购买商业授权要注意三点:

  1. 授权范围:看清楚是“按产品授权”还是“按公司授权”。有些授权只覆盖某一个产品线。
  2. 衍生作品覆盖:商业授权是否覆盖了你的团队对库的修改?有些许可不包含修改后的派生作品。
  3. 审计条款:有些商业授权附带审计权。对方有权检查你的代码是否遵守协议。我遇到过被审计的情况,差点翻车。

我的合规检查清单

这部分是我项目的内部标准,分享给你。

合规检查清单(必做项)

  • 确认每个第三方加密库的完整许可证文本,不只看README。
  • 区分“直接依赖”和“传递依赖”——尤其是静态链接的依赖,容易遗漏。
  • 建立许可证白名单:包含BSD-2/3、MIT、Apache-2.0、ISC;禁止:GPL、AGPL。
  • 每次引入新库,必须触发法务审核流程,不能工程师自己做决定。
  • 保留所有库的下载记录和版本信息,便于审计追溯。

一个典型的GPL感染流程图

我画一个简单的关系图,帮你理解代码是怎么被“感染”的。

GPL许可证感染传播路径图 使用GPL加密库 静态链接 整个程序被GPL感染 分发产品 要求:全量源码必须以GPL公开 不能闭源发布 商业机密暴露 / 重写加密层 / 法律诉讼 动态链接 主程序 通常不受感染 ⚠ 关键判断逻辑 静态链接 vs 动态链接:GPL对静态链接的传染性是确定的,企业级产品请避免。 AGPL额外规则:即使通过Web提供服务(动态链接),也视为分发,必须开源全部源码。 最优实践:使用BSD/MIT/Apache-2.0 加密库,或购买商业授权。

你从这张图可以清楚的看到:只要你的产品是静态链接GPL加密库,并且对外分发(不论是出售还是免费发布),你的整个程序就必须以GPL开源。

AGPL更狠,你做个SaaS服务,用户通过网络访问你的功能,也算“分发”。

我反复强调这条路径,是因为太多人“觉得没事”。

最后说一个真实的“商业授权”弯路

有个朋友的公司,几年前做硬件密码机。

他们选了某知名加密库的商业授权版。花了十几万买授权。结果呢?合同里有一条:“本授权仅适用于固件版本v2.x.x,升级至v3.x.x需重新授权。”

他们开发到一半,发现必须用新版本修复安全漏洞。但是新版本不在授权范围。再付一次钱?还是换库?最后被迫推迟了三个月,重新做了技术选型。

所以你买商业授权时,一定要看清楚:

  • 授权是永久性的还是订阅制?
  • 是否覆盖所有版本升级?
  • 是否包含安全补丁的授权?

建议你在采购阶段,就让法务和工程师一起参与。别让商务单独谈。很多条款,法务看不出来技术限制,工程师看得出来。

核心建议

  • 白名单机制:只允许BSD、MIT、Apache-2.0、ISC的加密库。见到GPL/AGPL一律走特殊审批流程。
  • 依赖树扫描:利用工具(比如FOSSA、BlackDuck、Snyk)自动扫描所有传递依赖的许可证。
  • 双许可证保留备选:万一需要,立刻切换到商业授权,而不是临时找替代库。
  • 法务介入:别自己决定。我看到过太多“我觉得这个库的GPL条款只针对库本身”的误解。

嗯,许可证这件事,越早重视,成本越低。