Skip to content

CipherHorizon v0.4.0

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 22 Oct 08:42
· 7 commits to main since this release
6bc2a02

Security

  • Built with Go 1.27.3 (GO-2026-6809). crypto/x509 now distrusts compromised intermediate certificates, and the
    trust check uses it.

Added

  • Classical strength for every detected algorithm (PRD-010,
    ENH-001). Strengths are computed with NIST's own methods, and the tests
    reproduce NIST's published tables:

    • RSA and finite-field DH by the General Number Field Sieve estimate (FIPS 140-3 IG D.B, SP 800-56B Rev. 2
      Appendix D);
    • elliptic curves at half the order (SP 800-186);
    • ciphers and hashes by SP 800-57 Part 1 Tables 2 and 3;
    • post-quantum algorithms by their NIST category.

    Where it shows:

    • TLS report and PDF: each cipher suite's word now comes from the server and is as strong as its weakest
      part (cipher, key exchange, certificate key, MAC), with its bits and that part named. Groups and certificate
      keys show their bits.
    • API: the evaluation (eval/9) carries suiteStrength and keyStrength; stored scans are re-evaluated
      on start.
    • CLI: tls scan --details prints each suite's and group's strength.
    • Inventory: a Classical strength column, and classicalStrength on every algorithm and key row of
      /api/v1/inventory.
    • SSH reports (page and PDF): a strength for every key exchange, host key (by the presented key's size),
      cipher and MAC.
    • CBOM: classicalSecurityLevel on every algorithm with a strength (1.6 and 1.7).
  • Every algorithm by class: asymmetric, symmetric, hash (PRD-011, #20).

    • A TLS report's Configuration ends with Every algorithm, by class: one lane per class, each algorithm with its
      role, a bits bar, its post-quantum status and the suites or certificates that use it, the weakest ringed.
    • Every suite row shows its parts (cipher, key exchange, signature, MAC, key-derivation hash) as cells with their
      bits, the weakest ringed.
    • The Inventory filters algorithms by class (?class=, a segmented control), and its Kind says the class.
    • The report's CBOM tab has a Classical strength column.
    • The PDF and tls scan --details list the algorithms by class, and the CLI lists each suite's parts.
    • API: the evaluation (eval/10) carries algorithms, and every suite part carries its class.
  • Open any certificate and read the whole X.509 document (PRD-012, #21).

    • Every certificate in the chain and the CBOM tab opens its page.
    • The page shows the chain it was served in, its validity, the key and the issuer's signature with their strengths
      and post-quantum status, its names and uses, every extension with its criticality and decoded value, the
      identifiers to copy, and the PEM (folded) to copy or download.
    • It is decoded from the DER the scan kept (GET /api/v1/certificates/{sha256}/x509), so earlier scans have it
      too.
  • Instruments, not paragraphs: the report, the certificate page and the Inventory are rebuilt
    (PRD-013, UX-DESIGN-011).
    One set of shared instruments draws every quantity the same way on every page: a 0 to 256 bits bar over the
    strength bands, a strength chip, a part cell, a post-quantum glyph, a status tile, a validity bar, the hygiene
    gauge and the readiness stepper. Each says in words what it shows.

    • Summary: four figures (readiness, hygiene, the weakest classical strength, the certificate), Fix first as
      the three things to fix first, each with one chip saying when, the rest folded under a line that counts them, one bar of every check's result, and a tile per area that opens it.
    • Configuration is one place to check the whole setup, in a reviewer's order: protocols and cipher suites
      (what a current client gets, then each version with its groups and its suites in the server's order), the
      certificate chain (each card opens its certificate; a missing issuer is drawn), key exchange and signatures,
      revocation, protocol features, and every algorithm by class. Every TLS version starts folded to one line that
      says whether it should be on and how its suites rate. A row of chips at the top jumps to each part, and
      each part ends with the issues found in it. HSTS shows the header as sent.
    • Inventory: algorithms By class and By classical strength (?strength=: broken, below-112, 112, 128,
      192, 256, not-rated), each bar opening its list; the list is weakest first, with a bits bar.
    • SSH reports (PRD-014,
      UX-DESIGN-012) get the same one-stop Configuration: version and
      software (what a current client gets, as a banner), key exchange (readiness, then each method as a row with its
      bits bar, post-quantum glyph and baseline mark), host keys (a card per key), ciphers, MACs and compression, and
      the baseline (a tile per requirement linking to its source, the changes as chips in their parts, the
      sshd_config lines). The Summary has the same four-figure strip, and the baseline is line 1 of Fix first.
      Checked by CRYPTO-REVIEW-002.
    • Scanner: a TLS scan records whether the server negotiates the heartbeat extension (RFC 6520).
    • Every number and claim on these screens was checked against its source
      (CRYPTO-REVIEW-001).

Changed

  • Breaking (API): the evaluation is now eval/12, and stored scans are re-evaluated on start. The band field
    uses the new hygiene band names (below), and a section's status can be unknown (revocation, when nothing
    vouches for the certificate). Integrations that match on band names or on the set of statuses must be updated.

  • The TLS hygiene bands have new names: Excellent, Good, Fair, Poor, Failing (they were Strong, Sound, Fair,
    Weak, Broken). Strong and Weak now mean only a suite's strength (UX-REVIEW-010, #22). The scores and the
    thresholds are unchanged. Stored scans are migrated, and the API's band field uses the new names.

  • Each suite gains the hash that derives its keys as a part, rated in that use (SP 800-57 Table 3). With NIST's
    numbers it changes no word.

  • Signature algorithms are rated as their hash and their key together, so SHA256withRSA from an imported CBOM
    now reads 128 bits instead of not rated.

  • The report's Summary:

    • the line under N things to fix names the first one;
    • the Cipher suites row names the weakest suite and its bits;
    • the Overview's TLS endpoints tile keeps to its count and the exposed figure.
  • The Inventory explains every not rated strength on the row.

  • Suite strength words follow the weakest-part rule, so some suites read differently:

    • a suite authenticated by an RSA-2048 certificate (112 bits) is now Acceptable, not Strong;
    • a suite with a 1024-bit DH prime is Weak.

    The words are defined in docs/methodology.md and explained in Help.

Fixed

  • Reports on real servers say the right thing (PRD-015,
    CRYPTO-REVIEW-003; eval/12, stored scans are re-evaluated on start):
    • a server whose only suites Go's TLS client will not offer (3DES, RC4, NULL, small DH) had its no-SNI fallback
      certificate reported as its own; the served chain is now read from the scanner's raw TLS 1.2 handshakes, which
      also finds an RSA certificate a server keeps for RSA-only clients. Scan such servers again;
    • a leaf signed straight by an unknown root is no longer called a missing intermediate;
    • a chain under Superfish, eDellRoot or DSDTestProvider is The certificate chains to a root whose private key is
      public
      (critical);
    • revocation reads Status unknown, not Good, unless a stapled OCSP response vouches for the certificate;
    • an untrusted root is described as a private CA or a public root since removed, not only as a private one;
    • a composite DH modulus is critical, and a DH prime that is not a safe prime is low;
    • at equal bits, the weakest classical strength picks a disallowed algorithm (3DES) over an allowed one.
  • SSH evaluation (eval/11; stored scans are re-evaluated on start):
    • a truncated MAC is as strong as its tag: hmac-sha1-96 is 96 bits, not 128 (NIST SP 800-107 Rev. 1);
    • the next steps name OpenSSH releases only to a server that identifies as OpenSSH;
    • a baseline rule with nothing to judge (the RSA size rule on a server with no RSA key) says it does not apply
      instead of Met.
  • Single-DES suites (56-bit key) are Insecure, not Weak (#18).
  • The TLS hygiene figure on a report's Summary opened About this report. It now opens how the score was worked
    out, on Weaknesses.
  • A running scan's connection count could go backwards. Concurrent probes reported counts out of order, and
    progress writes could land out of order. The count now only moves forward, and writes are serialised. This was
    found by a CI run of the workflow test.

Verify what you downloaded

sha256sum --check --ignore-missing checksums.txt
cosign verify-blob checksums.txt --bundle checksums.txt.sigstore.json \
  --certificate-identity-regexp '^https://github.com/offsetsecurity/cipherhorizon/\.github/workflows/release\.yml@refs/tags/v' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

The inventory scripts a server of this version hands out are attached too, with
inventory-scripts.sha256; cipherhorizon scripts list prints the same hashes offline.

Full instructions, including the container image and build provenance: docs/engineering/DISTRIBUTION.md.