Commit Graph
8 Commits
Author SHA1 Message Date
KCA 830dd64012 kca-core: fix CSR attribute DER encoding and conformant decoding
- Generated attributes are now explicitly tagged as UTF8String via
  CertificateSigningRequestBuilder.add_attribute(_tag=_ASN1Type.UTF8String),
  so values include proper DER TLV instead of raw bytes.
- The attribute decoder first attempts DER string parsing (UTF8String, PrintableString,
  IA5String, BMPString, long-form lengths), falling back to legacy raw UTF-8 decode for
  previously generated nonconformant CSRs.
- Regression tests verify DER encoding, Unicode round-tripping, supported string types,
  long values (>127 bytes), and legacy raw UTF-8 attributes.
- Mypy passes cleanly (no issues in 42 source files).
2026-10-25 22:09:22 +00:00
KCA 419a340e8d Fix: chain exports use certificate equality instead of object identity
The chain export formatters in kca-core used  identity checks
(e.g. , ) to determine whether to
exclude the leaf certificate from the chain. This caused duplicates
when the chain was built from separately-parsed certificate objects
that were cryptographically identical (same DER/fingerprint) but
different Python instances.

Changed  →  for value equality across all affected formats:
  - _pem_chain()        : PEM chain export
  - PKCS#7 chain        : serialization_certificates
  - PKCS#12 chain       : serialize_key_and_certificates
  - OpenVPN             : issuer detection
  - JWK chain           : x5c certificate list

Also added a regression test (test_chain_exports_exclude_equivalent_leaf)
that reproduces the exact issue: a leaf certificate re-parsed from its
DER form is treated as a distinct object, so the old -based checks
kept both copies in the output. The new -based checks correctly
deduplicate, retain the issuer, and handle OpenVPN's CA selection.
2026-10-25 22:08:55 +00:00
KCA a0135ef113 Fix expired self-signed cert validation: remove bypass, enable X509_STRICT|POLICY_CHECK, extract numeric error codes from pyOpenSSL 2026-10-25 22:08:15 +00:00
KCA f2d4730c26 Fix SSH private-key import/export for Paramiko 5.1.0 and remove unconditional DSSKey reference
- Replace paramiko-based OpenSSH private key serialization with
  cryptography's PrivateFormat.OpenSSH backend.
  The old code relied on paramiko.RSAKey, paramiko.DSSKey, etc. to write
  private keys, but Paramiko 5.1.0 removed DSSKey entirely and changed
  constructor APIs, causing crashes.

- Add explicit fallback path in _load_ssh_private_with_paramiko that
  guards against missing DSSKey (getattr paramiko 'DSSKey', append only
  when present), modern private_key attribute vs legacy signing_key,
  and Ed25519 PyNaCl key material conversion.

- Add two new test coverage methods:
  test_ssh_private_roundtrip  – round-trip RSA/DSA/EC/Ed25519
    unencrypted and password-encrypted, verifying OpenSSH PEM header
    and DER preservation.
  test_ssh_private_paramiko_fallback – explicitly exercise the
    Paramiko fallback for RSA and EC keys, confirming it still works
    under locked Paramiko 5.1.0.

Also clean up the comment in load_key_bytes to reflect the new fallback
behavior rather than the old 'encrypted OpenSSH keys not supported' note.
2026-10-25 21:44:08 +00:00
KCA e1dfca688b Typed but unhandled extensions preserve DER via public_bytes() 2026-10-25 21:42:42 +00:00
KCA 82b3abaf08 Fix EC JWK: fixed-width x, y, d encoding; restrict to registered curve names
- Encode EC coordinates and private d with curve-width (32/48/66 bytes) to satisfy RFC 7518,
  preserving leading zero octets.
- Restrict JWK  values to registered JOSE names: P-256, P-384, P-521, secp256k1.
  Raise ValueError for unregistered curves (P-192, P-224, Brainpool).
- Add regression tests: deterministic coordinate/private-value widths, leading-zero
  preservation, supported curve names, and rejection of unsupported curves.
- Mypy clean; all core and backend tests pass.
2026-10-25 21:40:57 +00:00
KCA d22ba6662c Fix stale OCSP snapshots indefinitely
- Parse and validate  from snapshot JSON, reject future/missing timestamps
- Enforce snapshot age vs  in cache and stale fallback (no lifetime extension on repeat S3 reads)
- OCSP: , ,
- Remove unused  from signer
- Publisher heartbeats: , republish clean snapshots past interval, preserve dirty-only behavior and concurrency
- Config/env/docker/docs updates for heartbeat

Rolling upgrade: enable publisher heartbeats before deploying the age-enforcing responder so existing snapshots remain within the age window.
2026-10-25 21:30:00 +00:00
KCA ec42cafc28 Fix quadratic ReDoS in PEM import block scanning
Replace the backtracking _PEM_BLOCK regex with a forward-only scanner
that indexes END markers by label, so repeated unterminated headers do
not cause the regex to rescan the remaining input.

Impact: 80 KiB payload went from 8.34 s to 0.001 s.
2026-10-25 21:28:11 +00:00