尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Envoy OCSP 测试夹具解析:证书身份体系、certs.spec 生成流程与源码级验证

Envoy OCSP 测试夹具解析:证书身份体系、certs.spec 生成流程与源码级验证 Envoy OCSP 测试夹具解析证书身份体系、certs.spec 生成流程与源码级验证【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy本篇技术指南以 Envoy 仓库中 test/common/tls/ocsp/test_data/README.md 为骨架系统讲解 OCSPOnline Certificate Status ProtocolRFC 6960测试夹具的完整设计8 个证书/响应身份各自的用途、私钥与 OpenSSL 配置文件的管理约定以及通过certs.spec声明式规格在 Bazel 构建期自动生成全部产物的流程。读完本文你将理解这些.der响应、.pem证书如何覆盖 OCSP Stapling 的全部状态分支good / revoked / unknown / 多证书 / 响应者身份变体并能在本地复现构建与验证测试。一、为什么需要一套 OCSP 测试夹具Envoy 在 TLS 握手中支持 OCSP Stapling服务器将证书的 OCSP 响应随握手一并下发客户端无需再向响应者responder发起额外请求。相应地Envoy 在 source/common/tls/ocsp/ocsp.h 中实现了 OCSP 响应的解析逻辑只接受格式良好的响应并从中提取证书吊销状态与有效期。要让这套解析代码获得充分验证就必须准备一套覆盖所有分支的证书与响应样本既要有状态为 good 的响应、已吊销的响应、无法识别的 unknown 响应也要有响应者以不同身份标识byName / byKey签发的响应、ECDSA 密钥签发的响应甚至要构造 Envoy应当拒绝的异常响应如一个响应覆盖多张证书。本文所述的目录正是这套夹具。夹具目录位于 test/common/tls/ocsp/test_data/其中只检入私钥和 OpenSSL*.cfg配置证书与 OCSP 响应全部由 Bazel 构建期生成保证了可复现性与最小化检入体积。二、八种身份证书、密钥与响应一一对应原文档明确列出了目录中存在的8 个身份identities其关系如下身份证书文件私钥说明CAca_cert.pem自签名ca_key.pem本目录所有夹具的根证书颁发机构Intermediate CAintermediate_ca_cert.pemintermediate_ca_key.pem由 CA 签发的中间 CAGoodgood_cert.pemgood_key.pem由 CA 签发对应 good 状态的 OCSP 响应good_ocsp_resp.derResponder Key Hash复用 Good 证书—针对 Good 证书的 OCSP 响应但响应者以公钥哈希而非名称标识即responder_key_hash_ocsp_resp.derRevokedrevoked_cert.pemrevoked_key.pem由 CA 签发的已吊销证书对应revoked_ocsp_resp.derUnknown复用 Good 证书—生成 unknown 状态的响应unknown_ocsp_resp.derECDSAecdsa_cert.pemecdsa_key.pem使用 ECDSA 密钥由 CA 签名对应ecdsa_ocsp_resp.derMultiple Cert OCSP Response复用 Good Revoked—以 CA 为签名者、同时覆盖 Good 与 Revoked 两张证书的响应multiple_cert_ocsp_resp.der其中几个身份需要重点理解其设计意图Unknown 身份unknown_ocsp_resp.der是以Intermediate CA为响应者、针对 Good 证书生成的 unknown 响应。因为 Good 证书由 CA而非 Intermediate CA签发响应者对不属于自己签发范围的证书只能返回 unknown 状态。这一样本用于验证 Envoy 对 unknown 状态的解析行为。Responder Key Hash 身份RFC 6960 中ResponderID是一个 CHOICE既可以用byName响应者名称标识也可以用byKey响应者公钥的 SHA-1 哈希标识。source/common/tls/ocsp/ocsp.cc 中的skipResponderId正是同时尝试解析[1]byName与[2]byKey两种上下文标签此样本用于覆盖 byKey 分支。Multiple Cert 身份一个响应内含两个SingleResponse条目。Enovy 的 validateResponse 明确要求OCSP Response must be for one certificate only该样本用于验证拒绝逻辑而非正常解析。关于测试私钥的重要约定目录中所有*_key.pem文件都是故意公开、仅供测试使用的私钥这一点在 test/common/tls/ocsp/test_data/KEYS.md 中有专门说明它们从未保护过任何真实数据任何拿到本仓库副本的人都知道这些私钥绝不允许在 Envoy 测试套件之外使用密钥扫描器会将其标记为泄露这是预期行为不应误报为真实事故。之所以把私钥检入仓库是为了保证构建可复现envoy_toolshed//certs:gen生成器只创建证书、从不创建密钥因此同一份 spec 配合同一批静态私钥永远产出相同的公钥材料。三、OpenSSL 配置夹具的 DN 与扩展基线CA 与各叶子证书的 OpenSSL 配置*.cfg定义了证书的 distinguished name 与扩展。以 test/common/tls/ocsp/test_data/ca_cert.cfg 为例[ req ] default_bits 2048 distinguished_name req_distinguished_name [ req_distinguished_name ] countryName US countryName_default US stateOrProvinceName California stateOrProvinceName_default California localityName San Francisco localityName_default San Francisco organizationName Lyft organizationName_default Lyft organizationalUnitName Lyft Engineering organizationalUnitName_default Lyft Engineering commonName ca commonName_default ca commonName_max 64 [ v3_ca ] subjectKeyIdentifier hash authorityKeyIdentifier keyid:always,issuer basicConstraints critical, CA:true keyUsage critical, digitalSignature, cRLSign, keyCertSigndefault_bits 2048RSA 密钥长度[ v3_ca ]段定义了 CA 证书扩展basicConstraints critical, CA:true声明其 CA 身份keyUsage限定为digitalSignature, cRLSign, keyCertSign叶子证书配置如 good_cert.cfg则不包含[ v3_ca ]扩展段其 DN 中也没有localityName——配置文件注释说明这是因为签发 CA 的策略会丢弃该字段。两者对比恰好演示了 CA 与叶子证书在扩展上的典型差异。四、certs.spec声明式夹具规格所有夹具的配方都集中在 test/common/tls/ocsp/test_data/certs.spec 中。它由envoy_toolshed//certs:gen消费该生成器在 test/common/tls/ocsp/test_data/BUILD 中以generated_certs规则接入采用[cert ...]与[ocsp ...]两类段。证书段[cert ca] key ca_key.pem cfg ca_cert.cfg issuer self [cert intermediate_ca] key intermediate_ca_key.pem cfg intermediate_ca_cert.cfg issuer ca # Leaves were issued by openssl ca, which applied no extensions, so these are # X.509 v1 certificates. The serial numbers match the CA serial file the old # script seeded with 1000 (hex). [cert good] key good_key.pem cfg good_cert.cfg issuer ca serial 1000 [cert revoked] key revoked_key.pem cfg revoked_cert.cfg issuer ca serial 1001 section must_staple [cert ecdsa] key ecdsa_key.pem cfg ecdsa_cert.cfg issuer ca serial 1002关键字段key指向检入的静态私钥cfg该证书的 OpenSSL 配置issuer签发者self表示自签名其余填父证书段名serial显式指定序列号十六进制。good/revoked/ecdsa的序列号 1000/1001/1002 与旧脚本为 CA 序列文件种子的值保持一致section must_stapleRevoked 证书额外引用名为must_staple的配置段。spec 注释特别说明叶子证书由openssl ca签发且未附加扩展因此是X.509 v1 证书。OCSP 响应段[ocsp good_ocsp_resp.der] cert good issuer ca responder ca status good next_update_days 730 info_header good_ocsp_resp_info.h info_header_prefix good_ocsp_resp [ocsp responder_key_hash_ocsp_resp.der] cert good issuer ca responder ca responder_id key status good [ocsp revoked_ocsp_resp.der] cert revoked issuer ca responder ca status revoked [ocsp unknown_ocsp_resp.der] cert good issuer intermediate_ca responder intermediate_ca status unknown [ocsp ecdsa_ocsp_resp.der] cert ecdsa issuer ca responder ca status good [ocsp multiple_cert_ocsp_resp.der] cert good issuer ca status good cert revoked issuer ca status revoked responder ca字段语义cert/issuer被查询的证书及其签发者用于构造CertID签发者名称哈希 签发者公钥哈希 序列号responder签名响应者的身份responder_id key表示以响应者公钥的SHA-1 哈希即 byKey代替名称标识响应者statusgood/revoked/unknown三种证书状态next_update_days 730good 响应的有效期为 730 天约两年确保测试运行时响应仍未过期info_header/info_header_prefix生成 C 头文件good_ocsp_resp_info.h把旧脚本从响应文本转储中刮取出的时间戳改为编译期常量暴露给测试使用multiple_cert_ocsp_resp.der段内重复出现两组cert/issuer/status以此构造包含两个SingleResponse的响应——spec 注释点明这正是用来验证 Envoy拒绝覆盖多张证书响应的行为。五、Bazel 构建期生成从 spec 到产物test/common/tls/ocsp/test_data/BUILD 通过generated_certs规则把上述 spec 变为真实文件CERTS [ ca_cert.pem, ecdsa_cert.pem, ecdsa_ocsp_resp.der, good_cert.pem, good_ocsp_resp.der, good_ocsp_resp_info.h, intermediate_ca_cert.pem, multiple_cert_ocsp_resp.der, responder_key_hash_ocsp_resp.der, revoked_cert.pem, revoked_ocsp_resp.der, unknown_ocsp_resp.der, ] generated_certs( name certs, srcs glob([*.cfg, *_key.pem]), outs CERTS, spec certs.spec, static_srcs glob([*.cfg, *_key.pem]), )生成规则以*.cfg与*_key.pem为静态输入对应只检入私钥和配置的约定产出上表 12 个文件。其中good_ocsp_resp_info.h也在此生成——这正是它在源码树中不存在的根本原因。原文档给出了复现生成命令$ bazel build //test/common/tls/ocsp/test_data:certs $ ls bazel-bin/test/common/tls/ocsp/test_data/构建后即可在bazel-bin对应目录下查看全部.pem证书与.der响应。原文档还说明了一个历史演进OCSP 请求 DER 文件与人类可读的响应转储dump已不再生成——因为没有任何代码读取请求文件而旧转储中被刮取的时间戳如今已改由生成的头文件以常量形式提供。六、源码级验证夹具如何驱动解析与测试6.1 解析侧的字段提取夹具中每个响应都对应 source/common/tls/ocsp/ocsp.h 中一个明确的解析分支OcspResponseStatus枚举完整映射 RFC 6960 B.2 的OCSPResponseStatus0successful、1malformedRequest、2internalError、3tryLater、5sigRequired、6unauthorizedCertId仅保留序列号其解析在 ocsp.cc 中跳过算法与两个哈希只提取serialNumberSingleResponse的this_update_/next_update_决定响应有效期若next_update_缺失则视为始终有过期信息直接判定响应已过期见 ocsp.h 注释BasicOcspResponse以 OID1.3.6.1.5.5.7.48.1.1id-pkix-ocsp-basic识别skipResponderId与skipCertStatus分别覆盖byName/byKey两种响应者标识以及good [0]/revoked [1]/unknown [2]三种证书状态validateResponse强制要求响应状态为 Successful、必须有响应体、且getNumCerts() 1。由于响应来自配置或其他可信来源ocsp.h 的 WARNING 注释明确说明本模块只做格式校验与字段提取不做来自上游服务器的响应校验——这也解释了为何 BasicOCSPResponse 中的签名算法与签名会被直接忽略。6.2 测试侧的逐样本断言test/common/tls/ocsp/ocsp_test.cc 中的OcspFullResponseParsingTest直接把夹具读入解析器并断言行为与夹具身份一一对应测试用例夹具断言要点GoodCertTestgood_ocsp_resp.dergood_cert.pem状态 Successful序列号匹配 good 证书而不匹配 revoked 证书nextUpdate在未来 → 未过期、剩余秒数 0RevokedCertTestrevoked_ocsp_resp.der状态 Successful 且匹配 revoked 证书isExpired()为真、剩余秒数为 0UnknownCertTestunknown_ocsp_resp.der状态 Successful 且匹配 good 证书被判定为已过期ExpiredResponseTest将模拟时钟拨快 10 年后读取good_ocsp_resp.dernextUpdate虽存在但已过去 → 过期、剩余秒数为 0ThisUpdateAfterNowTest时钟拨回 2000 年触发OCSP Response thisUpdate field is set in the future的 warning 日志ResponderIdKeyHashTestresponder_key_hash_ocsp_resp.der以 byKey 标识响应者也能成功解析并匹配 good 证书MultiCertResponseTestmultiple_cert_ocsp_resp.dercreate返回错误OCSP Response must be for one certificate onlyUnsuccessfulResponseTest手工构造字节流解析非 successful 状态响应这些测试通过Event::SimulatedTimeSystem自由控制时间从而在不等待真实时间流逝的前提下验证过期逻辑。ocsp_test的 Bazel 目标声明了data [//test/common/tls/ocsp/test_data:certs]测试运行时即可读取构建期生成的夹具见 test/common/tls/ocsp/BUILD。七、总结与进一步阅读本文所述的 OCSP 测试夹具是 Envoy OCSP Stapling 功能测试的基础设施它以8 个身份覆盖了证书链CA → Intermediate CA → 叶子、三种证书状态good / revoked / unknown、两种响应者标识byName / byKey、ECDSA 密钥体系以及必须被拒绝的多证书响应通过certs.spec声明式描述 Bazel 构建期生成实现了仅检入私钥与配置、产物完全可复现的工程实践。进一步探索的路径阅读 certs.spec 全文理解每一条[cert]/[ocsp]段对照 ocsp_test.cc 与 ocsp.cc把每个.der响应映射到具体解析与断言分支如需了解 ASN.1 底层工具可阅读 source/common/tls/ocsp/asn1_utility.cc 与对应的 asn1_utility_test.cc若要复现全部夹具执行bazel build //test/common/tls/ocsp/test_data:certs若要跑完整验证执行bazel test //test/common/tls/ocsp:all。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表