TLDR;在颁发证书的生命周期内执行证书创建和应用程序提交,或者;不要使用 Let's Encrypt,或者;不要在应用程序中使用固定,而是应用 DANE/DNSSEC 和 CAA。
解释:
使用证书固定的嵌入式应用程序(如 iOS 和 Android)的常规方法是拥有多个固定证书,且不存在(或很少)重叠日期,因此notBefore下一个有效固定证书的日期与上一个有效固定证书notAfter日期相同。
默认情况下,Let's Encrypt 证书notBefore从请求开始故意回溯 1 小时。由 CA 决定日期notBefore和notAfter日期,并且不支持用于嵌入式应用程序的方法。
Let's encrypt 允许您生成 CSR,这是自定义他们颁发的证书的最佳方式,这是我自己的生产应用程序中的示例:
申请证书 1:
certbot certonly \
--dry-run \
-n \
--dns-route53 \
--agree-tos \
--csr "<path to my CSR>" \
--register-unsafely-without-email \
--no-eff-email \
--dns-route53-propagation-seconds 300 \
--cert-path "<path to store the issued X.509 Leaf Certificate>" \
--key-path "<path to store the private key>" \
--fullchain-path "<path to store the issued X.509 Leaf Certificate and the chain of intermediate and CA Certificates as a bundle>" \
--chain-path "<path to store the chain of intermediate and CA Certificates as a bundle minus the actual issued X.509 Leaf Certificate>" \
-d sub.domain.tld
为同一域请求另一个证书,不删除原始证书,并在第一个证书后 2 个月运行:
certbot certonly \
--- same as above ---
--duplicate \
--force-renewal \
-d sub.domain.tld
第二个证书是notBefore在第一个证书后 2 个月颁发的。
需要注意的是,CSR 格式 (PKCS#10) 没有任何字段来放置这些日期,因此它仍然取决于您无法控制的 Let's Encrypt 隐藏决策来获得此结果。
回到威胁模型并更好地理解为什么实施证书固定对您来说会更有益。大多数情况下,为了更合适的选项,pin 被删除了,因为 pin 曾经是许多不适合的事情的解决方案,今天我们有 TLSA/DANE、DNSSEC 等选项,并使用 CAA 记录来完全验证预期的信任链信任锚。
如果您发现您的威胁模型表明固定是您识别出的任何风险的最佳缓解措施,那么您将需要找到一个 CA,该 CA 可以颁发未来日期 ( notBefore) 的叶证书并在您的应用程序中部署多个固定证书。