Skip to content

Add cross signed root support#8

Open
rkoopmans wants to merge 4 commits into
masterfrom
dev/cross-signed
Open

Add cross signed root support#8
rkoopmans wants to merge 4 commits into
masterfrom
dev/cross-signed

Conversation

@rkoopmans
Copy link
Copy Markdown
Owner

No description provided.

@rkoopmans rkoopmans force-pushed the dev/cross-signed branch 2 times, most recently from 76854b8 to d603205 Compare May 11, 2026 11:26
@rkoopmans rkoopmans requested a review from Copilot May 11, 2026 11:26
@codecov
Copy link
Copy Markdown

codecov Bot commented May 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
cert_chain_resolver/castore/base_store.py 100.00% <ø> (ø)
cert_chain_resolver/castore/file_system.py 100.00% <100.00%> (ø)
cert_chain_resolver/cli.py 100.00% <100.00%> (ø)
cert_chain_resolver/models.py 100.00% <100.00%> (ø)
cert_chain_resolver/resolver.py 100.00% <100.00%> (ø)
cert_chain_resolver/utils.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class support for discovering cross-signed root variants from CA AIA bundles, exposing them via the Python API and optionally emitting them from the CLI for “compatibility bundle” use-cases.

Changes:

  • Resolver now parses AIA downloads as multi-cert bundles, records cross-signed siblings on CertificateChain.cross_signs, and deduplicates them.
  • Models/utilities add multi-certificate PKCS7 loaders plus cross-sign detection via Subject + SPKI fingerprint.
  • CLI/docs/tests updated for --include-cross-signs, plus version bump + changelog entry.

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tox.ini Expands tox matrix / mypy interpreter configuration.
cert_chain_resolver/utils.py Adds *_to_x509_all loaders and routes existing single-cert loaders through them.
cert_chain_resolver/resolver.py Parses AIA bundles, detects cross-sign siblings, stores them on the chain, and recurses.
cert_chain_resolver/models.py Adds public_key_fingerprint, is_cross_sign_of, and CertificateChain.cross_signs storage/dedup.
cert_chain_resolver/cli.py Adds --include-cross-signs, prints cross-sign info, and optionally appends them to bundle output.
cert_chain_resolver/castore/file_system.py Minor typing/comment refactor for _cache.
cert_chain_resolver/castore/base_store.py Minor whitespace cleanup.
cert_chain_resolver/__init__.py Bumps version to 1.5.0.
tests/test_utils.py Adds tests for multi-cert loader behavior and junk-input failures.
tests/test_resolver.py Adds tests for cross-sign recording + dedup behavior during resolution.
tests/test_models.py Adds tests for SPKI fingerprinting, cross-sign predicate, and chain cross-sign container behavior.
tests/test_cli.py Adds arg parsing + output behavior tests for --include-cross-signs and info-mode reporting.
tests/_utils.py Minor formatting tweak.
README.md Documents --include-cross-signs and expected output ordering.
docs/cli_usage.rst Documents new CLI flag and behavior in --info.
docs/api.rst Documents API usage of chain.cross_signs.
CHANGELOG.md Adds 1.5.0 release notes describing cross-sign support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tox.ini
depends =
{py27,py312}: clean
{py27,py314}: clean
report: py27,py312
Comment on lines +59 to +64
primary = Cert(parents[0])
for extra_x509 in parents[1:]:
extra = Cert(extra_x509)
if extra.is_cross_sign_of(primary):
_chain.add_cross_sign(extra)
parent_bytes = bundle_bytes
Comment on lines +37 to +45
def load_bytes_to_x509(bytes_input):
# type: (bytes) -> x509.Certificate
"""Converts Certificate / PKCS7 in ASCII or DER to :py:class:`cryptography.x509.Certificate` object.

Kept for backwards compatibility; returns only the first certificate when the
input contains multiple. Prefer :py:func:`load_bytes_to_x509_all` when you need
every cert in the input.
"""
return load_bytes_to_x509_all(bytes_input)[0]
Comment on lines +59 to +63
return [x509.load_pem_x509_certificate(bytes_input)]
raise ImproperlyFormattedCert("Cert can not be read! It is not a valid PEM")


def load_der_to_x509(bytes_input):
# type: (bytes) -> x509.Certificate
"""Converts bytes formatted DER (PKCS7 or Cert) to :py:class:`cryptography.x509.Certificate` object"""
def load_der_to_x509_all(bytes_input):
print("NotBefore:".ljust(20) + cert.not_valid_before.isoformat())
print("NotAfter:".ljust(20) + cert.not_valid_after.isoformat())
print("Serial:".ljust(20) + str(cert.serial))
print("Sha256Fingeprint:".ljust(20) + str(cert.fingerprint))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants