☰
ownCloud 代码签名信任库迁移指南:G1/G2 双代际 trust store 结构与验证行为解析
2026/9/25 6:10:01 网站建设 项目流程
  • 后端
  • 内容协同

【免费下载链接】core

:cloud: ownCloud web server core (Files, DAV, etc.)

项目地址:https://gitcode.com/gh_mirrors/core84/core
点击查看免费下载

ownCloud web server core 通过resources/codesigning/目录承载应用代码签名的信任锚点、中间证书与证书吊销列表(CRL),支撑 Integrity Check 验证器对 first-party 与第三方应用的签名校验。本文以该目录的 README 为核心,结合lib/private/IntegrityCheck/Verifier/下的TrustStore、CrlProvider实现与对应测试,讲解 G1 遗留验证路径与 G2 新验证路径如何共存、证书与 CRL 如何按代际加载,以及 G1 过渡期的兼容语义。读完本文,你将掌握 ownCloud 代码签名信任库的目录布局、代际标记规则、CRL 获取的三级降级策略,并能依据源码与测试用例理解 G1 迁移与 G2 上线的完整行为。

信任库的目录布局

resources/codesigning/是 ownCloud 代码签名验证的信任存储根目录,采用"roots / intermediates / crl"三级分层结构,与 G1、G2 两个证书代际一一对应:

resources/codesigning/ ├── roots/ # Trust anchors(信任锚点) │ ├── root-g1.crt # 遗留 G1 根(实际为中间权威),为过渡期保留 │ └── root-g2.crt # G2 根锚点(CA ceremony 产物) ├── intermediates/ # 中间证书 │ └── intermediate-g2.crt # G2 中间签发者(CA ceremony 产物) ├── crl/ # 证书吊销列表 │ ├── legacy.crl # 冻结的 G1 CRL(面向遗留应用) │ └── developers.crl # G2 叶子 CRL(CA ceremony 产物,通过 CRL_URL 刷新) └── core.crt # 核心叶子证书(first-party 签名用,验证器不使用)

上述文件均已在本仓库确认存在。实际证书信息可通过openssl x509查看:root-g1.crt的主体为CN = ownCloud Code Signing Intermediate Authority(有效期 2016-02-03 至 2026-01-31),root-g2.crt的主体为CN = ownCloud Code Signing Root CA G2(有效期 2026-07-15 至 2051-07-09),intermediate-g2.crt的主体为CN = ownCloud Code Signing Intermediate CA G2(有效期 2026-07-15 至 2031-07-14),core.crt的 CN 为core(有效期 2016-02-03 至 2026-01-31)。

TrustStore 的加载行为:按文件名标记代际

OC\IntegrityCheck\Verifier\TrustStore(见 TrustStore.php)是加载信任锚点与中间证书的核心类,其行为与 README 描述完全一致:

  • roots/ 全部加载为信任锚点:getRoots()通过EnvironmentHelper::getServerRoot()拼接出resources/codesigning/roots路径,逐文件读取 PEM 内容;读取失败(file_get_contents返回false)的文件会被跳过。
  • 按 basename 前缀打代际标签:文件名以root-g1开头则标记为'g1'(遗留验证路径),否则标记为'g2'(新验证路径)。对应源码为:
$generation = \strpos($filename, 'root-g1') === 0 ? 'g1' : 'g2';
  • intermediates/ 作为非可信线索加载:getBundledIntermediates()读取该目录下所有证书,作为"可能帮助叶子证书链接到可信根的提示",不直接作为信任锚点。

因为root-g1.crt存在,roots/ 目录非空,遗留 G1 应用可以正常走验证流程。TrustStoreMigrationTest(见 TrustStoreMigrationTest.php)对此做了显式约束:断言roots/、intermediates/、crl/三个目录存在、roots/root-g1.crt与crl/legacy.crl存在、旧的扁平文件(root.crt、intermediate.crl.pem)已被移除,并验证TrustStore至少加载到一个标记为g1的根。

CrlProvider 的 CRL 获取策略:G1 冻结、G2 三级降级

OC\IntegrityCheck\Verifier\CrlProvider(见 CrlProvider.php)实现了 README 所描述的按代际区分 CRL 来源的逻辑,getCurrentCrl(bool $isG1Chain)是入口:

  • G1 链($isG1Chain === true):跳过网络请求,只读取捆绑的crl/legacy.crl(冻结版本),经CrlValidator::parseAndValidate校验签名后返回;若捆绑 CRL 缺失或校验失败,直接抛出CrlUnavailableException("No valid G1 legacy CRL available")。
  • G2 链($isG1Chain === false):执行三级降级——
    1. 先用CrlFetcher从网络获取VerifierConstants::CRL_URL指向的 CRL,校验通过即返回;
    2. 网络失败或校验失败,回退到捆绑的crl/developers.crl;
    3. 两者均不可用时fail-closed(关闭式失败),抛出CrlUnavailableException("No valid CRL available (fetch and bundled both failed or invalid)")。

CRL 的远端地址定义在 VerifierConstants.php:CRL_URL = 'https://owncloud.dev/developer-certificates/crl/developers.crl'。该常量特意选择 owncloud.dev 而非 owncloud.github.io 路径——后者会 301 跳转而CrlFetcher不跟随重定向(详见设计文档 §13)。

CrlProviderTest(见 CrlProviderTest.php)对这条降级链做了逐一验证:testFetchedValidCrl覆盖"网络 CRL 有效即采用",testFallbackToBundledCrl覆盖"fetch 返回 null 时回退捆绑 CRL",testFetchedInvalidFallbackToBundled覆盖"网络 CRL 签名无效(wrong-issuer)时回退捆绑 CRL",testFailClosedNoCrl与testFailClosedExceptionReasonCode覆盖"双源都不可用时抛CRL_UNAVAILABLE原因码",testG1SkipsFetch则断言 G1 路径下CrlFetcher::fetch永远不会被调用。

G1 过渡:从扁平根迁移到roots/root-g1.crt

生产环境的 ownCloud 10.x 生态此前依赖单一扁平信任锚点resources/codesigning/root.crt。README 明确指出:该文件实际是G1 中间权威(subject 为 "ownCloud Code Signing Intermediate Authority"),它曾是遗留loadCA()验证器事实上的信任锚点。

"Task 13" 将其迁移为roots/root-g1.crt,目的是在建立新的多代际目录布局的同时,保留遗留验证语义的完全一致性——使用 G1 证书签名的应用继续通过验证。迁移测试(见 TrustStoreMigrationTest.php)专门断言旧的扁平文件必须"消失而非重复保留":

  • 旧root.crt必须不存在(已迁移至roots/root-g1.crt);
  • 旧intermediate.crl.pem必须不存在(已迁移至crl/legacy.crl)。

这保证了迁移是"移动"而非"复制",避免新旧两份文件在语义上产生分叉。

遗留 G1 应用在过渡期与日落后的行为差异

LegacyTransitionTest(见 LegacyTransitionTest.php)以参考时间注入的方式,精确刻画了 G1 过渡期的行为矩阵,与VerifierConstants::LEGACY_SUNSET = '2026-12-31T23:59:59Z'呼应:

场景参考时间期望行为
过期 G1 + 日落前2026-06-01isLegacyWarn=true且isPassed=true(warn+allow,输出['LEGACY_ACCEPTED_WARN' => true])
过期 G1 + 日落后2027-06-01抛出BadAlgorithmException(算法门禁拒绝遗留算法,硬性阻止)
过期 G1 但证书被吊销2026-06-01仍抛出RevokedException(吊销检查优先于 warn)
过期 G1 但文件被篡改2026-06-01返回INVALID_HASHdiff,isPassed=false(篡改绝不 warn)
未生效 G1(now < notBefore)2019-01-01抛出BadChainException(硬性阻止,不进入 warn 分支)
无扩展、大写 CN 的遗留 G1 叶子2026-06-01完整管线通过,isPassed=true且非 legacy-warn(保持旧验证器语义)
正常 G2 应用2026-07-12isPassed=true、isLegacyWarn=false(G2 不受影响)

其中"无扩展、大写 CN"用例(testLegacyG1ExtensionlessUppercaseCnPasses)明确以resources/codesigning/core.crt与tests/data/integritycheck/SomeApp.crt的真实形态作为回归基准,证明新验证器对旧格式叶子证书的向后兼容。

G2 可用性:真实 ceremony 产物与测试 PKI 的严格隔离

README 强调 G2 代码签名已是live状态:CA ceremony 已产生真实、离线持有的锚点,并捆绑在仓库中:

  • roots/root-g2.crt—— G2 根锚点(CN "ownCloud Code Signing Root CA G2");
  • intermediates/intermediate-g2.crt—— G2 中间签发者;
  • crl/developers.crl—— G2 叶子吊销列表(由 G2 中间签发)。

G2 在运行时能否通过验证,取决于捆绑 CRL 能否用随附根证书验证通过,而非目录槽位是否为空的静态条件。这些是真实的 ceremony 产物,不是tests/data/integritycheck/verifier/pki/下的测试 PKI 证书。README 明确记录了一个安全教训(Task 10):把测试证书当作生产信任锚点下发是安全错误,因此两套证书严格分离。VerifierTest等测试在临时 server root 中复制测试 PKI 与 CRL fixture(如developers-empty.crl、developers-revoked.crl、intermediate-revoked.crl),验证器在真实运行时路径上绝不清空此隔离。

验证流程全景:从验证器到信任库的调用链

将上述组件串联起来,ownCloud 的签名验证管线为:Verifier::verify()接收签名文件(signature.json)、应用目录树与应用 ID,依次经过ChainValidator(借助TrustStore的根与中间线索构链)、AlgorithmAllowlist(G2 仅允许ecdsa-p384-sha384与rsa-pss-sha384,见 VerifierConstants.php,遗留rsa-pss-sha1仅限 G1 过渡期)、ManifestVerifier(用OnDiskHasher计算文件哈希比对清单)、CrlProvider(按代际获取并校验 CRL)、AppIdResolver(核对 CN 与应用 ID 一致)与IntegrityDiffer。VerifierTest(见 VerifierTest.php)覆盖了完整链路的通过、篡改(INVALID_HASH)、叶子吊销(RevokedException)、中间吊销、坏签名(BadSignatureException)、CN 不匹配(CnMismatchException)与缺失签名(MissingSignatureException)等分支。

参考与进一步阅读

README 末尾给出的两条参考线索:设计文档为 ownCloud G2 code-signing verifier(design/core-g2-code-signing.md的 §2 与 §19,涵盖链验证与 CRL 设计要点),CA ceremony 材料位于 developer-certificates 仓库。在本文所讨论的代码库内,可直接深入阅读的对照材料包括:信任库加载实现 TrustStore.php、CRL 降级实现 CrlProvider.php、常量定义 VerifierConstants.php,以及迁移合规测试 TrustStoreMigrationTest.php 与过渡期行为测试 LegacyTransitionTest.php。需要说明的是,证书与 CRL 均为真实签名材料,仅用于 ownCloud 服务端验证自身签名的应用包,读者如需自行构建测试环境,应使用tests/data/integritycheck/verifier/pki/下的测试 PKI 生成脚本(如gen_g1_pki.sh、gen_g2_pki.sh、gen_crls.sh),而不得将测试证书混入生产信任库。

  • 后端
  • 内容协同

【免费下载链接】core

:cloud: ownCloud web server core (Files, DAV, etc.)

项目地址:https://gitcode.com/gh_mirrors/core84/core
点击查看免费下载

相关推荐

上一篇:Artemis未来路线图:探索下一代交互式学习平台
下一篇:突破QQ音乐加密限制:qmcdump音频格式转换全攻略

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询