# AI 代理与契约式设计如何在生产前捕获加密漏洞
AI 代理正在彻底改变开发安全系统的格局:它们不是手动编写代码和测试,而是基于形式化契约生成实现。这消除了契约式设计失败的主要原因——双倍工作量。在一个集成了硬件 TRNG 和 PKI 的项目中,两个关键漏洞正是通过契约测试精准捕获,而普通单元测试根本会漏掉。
为什么测试会漏掉密码学中的逻辑错误
测试只能检查程序员想到的情况。如果他们没想到要验证 RSA 中的填充,或者在输入 DRBG 前检查熵质量——测试就不会自己写出来。这就是 OpenBSD 中一个 27 年的 bug 和 FFmpeg 中一个 16 年的漏洞如何逃过数百万自动化检查的原因。编译器和静态分析工具对逻辑错误无能为力:选择错误的加密模式、跳过证书吊销检查、使用过时标准——这些都悄无声息地逃过它们的侦测。
核心问题:测试是对实现的反应,而不是意图。契约在任何代码编写前就捕捉意图。它们设定边界:系统必须做什么(后置条件)、什么被禁止(不变量),以及在什么条件下可以调用(前置条件)。这不仅仅是文档——而是可执行规范。
契约式方法的不同之处在于:
- 正式性:PRE/POST/INV 以机器可读形式编写,而不是注释。
- 早期检测:契约违反立即失败,而不是在生产环境中。
- 聚焦保证:不是“如何工作”——而是“什么被保证”。
- 单一真相来源:开发过程中契约不变;只有需求变更时才更新。
AI 代理如何处理后半部分工作
契约式设计在主流中失败,是因为双倍工作量:先写契约,再写代码,然后写测试。在截止期限压力下,契约首当其冲被牺牲。今天,AI 代理接管实现和测试生成,只留给人类制定契约。这改变了经济学:一行契约取代数百行代码和测试。
流程如下:
- 人类编写不变量:
padding == RSA-PSS | RSA-OAEP; PKCS#1 v1.5 == FORBIDDEN。 - 代理生成 CryptoEngine 模块,只使用允许的填充。
- 同时,代理创建契约测试,尝试使用 PKCS#1 v1.5 并期望抛出异常。
- 如果测试失败——代理修复实现,而不碰契约。
- 人类只审查 10 行契约,而不是 1000 行代码。
优势:
- 速度:全栈嵌入式项目只需 11 天活跃工作,而不是数月。
- 可靠性:契约是焦点;其中的错误比代码中更容易发现。
- 可扩展性:一人管理不同角色的代理(编码者、测试者、架构师)。
真实案例:集成硬件 TRNG 和契约测试的 PKI
pki-on-box 项目包含五个模块:STM32G431(硬件 TRNG)、Python 守护进程(符合 NIST SP 800-90A 的 DRBG)、CryptoEngine(密钥生成)、KeyStorage(AES-256-GCM)、CA 服务(X.509 签名)。每个模块在接口处都有形式化契约。部署前发现了两个关键漏洞:
- 错误填充:实现意外使用了 PKCS#1 v1.5 而非 RSA-PSS。Bleichenbacher 攻击可通过填充预言机恢复明文——契约测试立即失败。
- 错误 AES 模式:选择了 ECB 而非 GCM。契约要求认证加密——测试再次失败。
项目指标:
- 131 次提交
- 62 个契约测试 + 15 个硬件测试
- 3 块 MCU 板(STM32G474、G431、H750)
- 目标平台:RK3328 ARM64
- AI 成本:1780₽(30 次会话)
- 公开仓库:github.com/vasilievsv/hw.pki-on-box
接口处的契约:关键错误产生之地
逻辑错误发生在模块边界。DRBG 输出字节——CryptoEngine 必须知道如何使用。没有契约——有人从 StackOverflow 示例中随便挑填充。项目中的两个关键契约如下:
contract: key_generation
PRE:
- DRBG.seeded == true
- algorithm ∈ {RSA-2048, ECDSA-P384}
POST:
- private_key.encrypted(AES-256-GCM)
- public_key = derive(private_key)
INV:
- padding == RSA-PSS | RSA-OAEP
- PKCS#1 v1.5 == FORBIDDEN
contract: certificate_issuance
PRE:
- issuer_ca.valid() && !revoked()
- csr.signature.verify() == true
POST:
- cert.serial.unique()
- cert.signature.verify(issuer_ca.public_key) == true
INV:
- root_ca.offline == true
- cert_chain.depth <= max_path_length
填充的契约测试:
def test_rejects_pkcs1v15_padding(self, crypto):
priv, pub = crypto.generate_rsa_keypair(bits=2048)
data = b"invariant check"
sig = crypto.sign_data(priv, data)
# PSS must rabotat
pub.verify(sig, data, padding.PSS(...))
# PKCS1v15 must slomatsya
with pytest.raises(Exception):
pub.verify(sig, data, padding.PKCS1v15(), hashes.SHA256())
该测试不检查功能——它验证不变量遵守。如果填充变更——测试失败,即使签名“技术上有效”。
关键收获
- 契约 > 测试:测试检查实现;契约检查意图。只有通过形式化保证才能捕获逻辑错误。
- AI 消除双倍工作:代理从契约生成代码和测试;人类专注规范。
- 边界处的关键错误:填充、加密模式、吊销检查——全由模块接口的不变量控制。
- 公开验证:带有硬件 TRNG 和契约测试的项目在公开仓库中供审计。
- 时间经济学:全栈嵌入式系统只需 11 天而非数月——得益于角色分工和自动生成。
— Editorial Team
暂无评论。