0Pricing
Cryptology Academy · 课时

移动与桌面应用中的证书固定

实现 HPKP 和 TrustKit 风格的证书固定,并了解证书固定带来的运维风险。

移动与桌面应用中的证书固定 是 CoddyKit 上的免费 Cryptology Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Cryptology Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Cryptology Academy 课程共包含 4 节课。

证书固定为何存在

标准 TLS 信任操作系统预装的约 150 个根 CA 签发的所有证书。如果任意根 CA 遭到破坏或胁迫,攻击者就可以为任何域名获取证书并拦截 TLS 流量。证书固定会将信任范围限制为特定证书或公钥,而不受签发该证书的 CA 影响。启用证书固定的应用只有在服务器提供完全匹配的预期证书或密钥时,才会接受与服务器的连接。这种保护对移动应用尤其有价值,因为用户无法检查网络流量,而企业 MDM 解决方案可能会安装企业 CA 根证书。

固定类型:证书、公钥与 SPKI

证书固定有三种粒度:(1) 完整证书固定——必须匹配完全相同的 DER 编码证书。这种方式最脆弱,证书每次续期都会导致连接中断。(2) 公钥固定——只比较 SubjectPublicKeyInfo(SPKI)字节。如果保留相同的密钥对,即使证书续期也不会受到影响。(3) SPKI 哈希固定——存储 SHA-256(SPKI),而不是原始密钥。这是 HTTP 公钥固定(HPKP)和 Android 网络安全配置所采用的方式。公钥/SPKI 固定更受推荐:它能够经受 CA 轮换和证书续期,同时仍可检测使用不同密钥对的 MITM。

Android 网络安全配置

Android(API 24+)通过网络安全配置 XML 提供声明式证书固定机制。文件 res/xml/network_security_config.xml 按域名指定固定值:pin-set 使用 digest="SHA-256",并包含经过 Base64 编码的 SPKI 哈希。应用通过 AndroidManifest.xml 中的 android:networkSecurityConfig 引用此文件。对于通过标准 HttpsURLConnection 和 OkHttp 建立的所有 HTTP 连接(使用平台信任管理器时),Android 都会强制执行固定规则。pin-set 至少需要一个备用固定值(不同的密钥或 CA 固定值),以便在主密钥泄露时避免应用被锁死。固定值过期时间(expiration 属性)会强制应用在固定值失效前完成更新。

iOS / macOS 证书固定

iOS 应用在 NSURLSession 代理中实现证书固定。URLSession(_:didReceive:completionHandler:) 代理方法会接收服务器信任对象。应用调用 SecTrustEvaluateWithError 验证证书链,然后使用 SecTrustGetCertificateAtIndex(trust, 0) 提取叶证书,导出其 SPKI 字节,使用 SHA-256 计算哈希,并与存储的固定值进行比较。TrustKit(开源库)通过基于配置的证书固定封装了这一模式,并支持多个固定值、子域名匹配和仅报告模式。Apple 的应用传输安全(ATS)与证书固定相互独立:ATS 强制执行最低 TLS 版本,但不会固定密钥。

HPKP:HTTP 公钥固定(已弃用)

HTTP 公钥固定(HPKP,RFC 7469)曾尝试通过 HTTP 响应头为网页浏览器加入证书固定:Public-Key-Pins: pin-sha256="base64=="; max-age=5184000; includeSubDomains。浏览器会在 max-age 指定的时间内记住固定值,并拒绝连接到密钥不匹配的服务器。由于可能造成灾难性故障,Chrome 于 2017 年弃用 HPKP,并于 2019 年移除它:一次配置错误或密钥丢失,就可能在没有任何恢复途径的情况下永久阻止用户访问网站。HPKP 现在实际上已不再用于网页浏览器;移动应用中的应用级证书固定仍然可行,因为应用更新可以发布新的固定值。

OkHttp 中的证书固定

OkHttp(Android 上广泛使用)通过 CertificatePinner 支持证书固定:CertificatePinner.Builder().add("api.example.com", "sha256/AAAA...==", "sha256/BBBB...==").build()。第二个固定值是备用值。OkHttp 会验证服务器证书链中的任意证书(叶证书、中间证书或根证书)是否至少有一个匹配的固定值。这样既可以固定中间 CA(经受叶证书轮换),也可以固定根 CA(经受中间证书轮换)。当验证失败时,OkHttp 会抛出 SSLPeerUnverifiedException,并在有帮助的错误信息中列出服务器实际使用的 SPKI 哈希,从而便于在开发期间提取固定值。

绕过证书固定:攻击者技术

证书固定提高了拦截流量的难度,但并非无法破解。移动设备上常见的绕过技术包括:(1) Frida 钩子——向应用进程注入 JavaScript,钩住固定验证方法并无条件返回 true。(2) SSLUnpinning 工具——针对常见固定库(TrustKit、OkHttp、原生 SecTrust)的自动化 Frida/Objection 脚本。(3) 定制 ROM——获取设备的超级用户权限并修改 TLS 协议栈。(4) 重新打包——反编译 APK,修改固定配置,再使用新证书重新打包。(5) 内存修补——在运行时修改验证字节码。缓解措施包括检测设备是否具有超级用户权限或已越狱、代码混淆以及完整性检查(SafetyNet/App Attest)。

备用固定值与灾难恢复

证书固定最大的运营风险是自我锁死:如果生产密钥丢失,或者证书过期且备用密钥不可用,用户将一直无法访问服务,直到应用更新发布(可能需要数天到数周)。最佳实践包括:(1) 始终固定至少两个密钥——当前密钥和预先生成、离线存储的备用密钥(存放在 HSM 或隔离网络中)。(2) 设置固定值过期日期,并在过期前发布应用更新。(3) 在强制执行前,通过仅报告模式监控固定失败。(4) 为固定值轮换事故维护紧急应用更新流程(加急审核)。(5) 固定中间 CA,而不是叶证书,以便在不更新应用的情况下轮换叶证书。

桌面应用中的证书固定

使用 Electron、Qt 或原生代码编写的桌面应用,可以通过其 TLS 协议栈 API 实现证书固定。Electron 应用使用 app.on("certificate-error") 事件和 session.setCertificateVerifyProc() 实现自定义验证。Qt 网络代码使用带自定义验证回调的 QSslSocket。.NET 应用使用 ServicePointManager.ServerCertificateValidationCallback。原生 Windows 应用使用 WinHTTP 手动检查证书。桌面应用还面临其他挑战:通过企业代理进行的操作系统级 TLS 流量拦截很常见,而用户可能希望代理功能正常工作,因此需要决定证书固定是否只应用于特定端点。

CI/CD 与自动化测试中的证书固定

证书固定会使自动化测试和 CI/CD 流程更加复杂。对预发布服务器进行真实 HTTPS 调用的集成测试,必须使用其 SPKI 哈希已固定在测试配置中的测试证书。可采用以下方法:(1) 构建变体——调试/预发布构建包含预发布服务器的固定值;发布构建固定生产服务器。(2) 网络安全配置覆盖——Android 允许仅用于调试的固定配置。(3) 模拟服务器——在 TLS 之前的 HTTP 客户端层进行拦截,完全绕过证书固定。(4) 用于 CI 的自签名 CA——使用一个根证书仅在测试构建中受信任的 CI CA 来签发测试证书。切勿在生产环境发布禁用证书固定的构建版本。

证书固定的后量子考虑

证书固定值通常是 RSA 或 EC 公钥的哈希。当后量子迁移开始后,服务器将迁移到 ML-DSA(CRYSTALS-Dilithium)或混合密钥。固定的 SPKI 哈希会发生变化,因为密钥类型和编码都会改变。固定叶证书或公钥的应用需要协调更新:(1) 在服务器迁移前,发布包含后量子 SPKI 哈希作为备用固定值的新版本应用。(2) 完成服务器迁移。(3) 发布更新,移除旧的经典算法固定值。过渡窗口需要谨慎协调。固定中间 CA 或根 CA 的应用受影响较小——变化的只是 CA 的密钥,而且其时间线不一定与叶证书相同。

证书固定测验

为什么相比固定完整证书,固定 SubjectPublicKeyInfo(SPKI)哈希更受推荐?

证书固定回顾

证书固定将 TLS 的信任范围限制为特定证书或公钥,从而防范 CA 被攻破和 MITM 攻击。固定 SPKI 哈希(SubjectPublicKeyInfo 的 SHA-256 哈希)相比固定完整证书更受推荐,因为它能更好地适应证书续期。Android 使用网络安全配置 XML;iOS 使用带有 SecTrust API 的 URLSession 委托;OkHttp 支持 CertificatePinner。请始终包含一个备用固定项,以防止因固定失败而无法访问应用。HPKP(浏览器 HTTP 标头)已弃用。通过 Frida 挂钩和 ROM 修改可以绕过固定机制。后量子密钥迁移需要协调更新应用,以更新 SPKI 哈希。

常见问题解答

「移动与桌面应用中的证书固定」课时是免费的吗?

是的 — 「移动与桌面应用中的证书固定」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Cryptology Academy 课程的其余内容,请升级到 CoddyKit PRO。 Cryptology Academy 课程共包含 4 节课。

「移动与桌面应用中的证书固定」这节课中我会学到什么?

实现 HPKP 和 TrustKit 风格的证书固定,并了解证书固定带来的运维风险。 你通过在浏览器中直接运行的动手代码来练习 Cryptology Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Cryptology Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Cryptology Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「移动与桌面应用中的证书固定」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Cryptology Academy 课中编写并运行代码吗?

能。每节 Cryptology Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. TLS 1.3:0-RTT、早期数据与会话恢复
  2. 双向 TLS(mTLS)实现模式
  3. 移动与桌面应用中的证书固定
  4. TLS 性能:QUIC 与 HTTP/3
← 返回 Cryptology Academy