Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,58 @@ the CBOM/report/eval schema versions, the database) can change in a minor releas
- **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](docs/product/PRD-011-algorithm-classes-and-flow.md), #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](docs/product/PRD-012-certificate-viewer.md), #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](docs/product/PRD-013-visual-rebuild.md), [UX-DESIGN-011](docs/product/UX-DESIGN-011-instruments-not-paragraphs.md)).
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
one numbered line per problem, 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. Each version folds to one line when all its
suites are Strong, and opens when it needs a look. 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:** the algorithm tables use the bits bar and a post-quantum column.
- **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](docs/product/CRYPTO-REVIEW-001-visual-rebuild.md)).

### Changed

- **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*.
Expand All @@ -45,6 +94,9 @@ the CBOM/report/eval schema versions, the database) can change in a minor releas
### Fixed

- **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.
- **The browser journey retries a browser that does not start**, instead of failing the whole run.
- **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.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ CycloneDX 1.7 CBOM, with PDF reports for each endpoint and for the whole invento
|---|---|
| **TLS endpoints** | Every protocol from SSLv2 to TLS 1.3, every cipher suite and key-exchange group (hybrids such as `X25519MLKEM768` included), the TLS 1.3 signature schemes (ML-DSA included), the certificate chain against the Mozilla and Chrome root stores or your own CA, OCSP stapling, Certificate Transparency and HSTS. STARTTLS for SMTP, IMAP, POP3, FTP, XMPP, LDAP and PostgreSQL. 55 cited checks and the TLS hygiene score. |
| **SSH servers** | Identification and algorithm lists, negotiation as OpenSSH 10.6 would (the ML-KEM hybrid included), every host key fetched and verified (Ed25519, ECDSA, RSA, ML-DSA and the composite `ssh-mldsa44-ed25519`), 18 cited checks, and the CipherHorizon SSH baseline 2026 with the `sshd_config` lines to meet it. It never logs in. |
| **Classical strength** | Every algorithm, key and cipher suite in bits, computed with NIST's own methods (the GNFS estimate for RSA and DH, half the order for curves, SP 800-57 for ciphers and hashes). A suite is as strong as its weakest part and names it, on the report, the PDF, the CLI, the Inventory, SSH reports and the CBOM (`classicalSecurityLevel`). |
| **Classical strength** | Every algorithm, key and cipher suite in bits, computed with NIST's own methods (the GNFS estimate for RSA and DH, half the order for curves, SP 800-57 for ciphers and hashes). A suite is as strong as its weakest part and names it, on the report, the PDF, the CLI, the Inventory, SSH reports and the CBOM (`classicalSecurityLevel`). Every algorithm is classed as asymmetric, symmetric or hash; each report shows every suite part by part and every algorithm by class, drawn as bits bars on one scale. |
| **Certificates** | Open any certificate in a chain to read the whole X.509 document: its chain, validity, key and signature with their strengths, names and uses, every extension decoded, fingerprints, and the PEM to copy or download. |
| **Post-quantum readiness** | L0 to L4 for every TLS endpoint and SSH server, each protocol by its own stated rules, with harvest-now-decrypt-later exposure. |
| **Machines** | Two readable inventory scripts (PowerShell, shell) list a machine's cryptographic software and certificates; nothing is installed and no key material is read. |
| **Inventory** | TLS endpoints, SSH servers, machines and imported CBOMs merged into one CycloneDX 1.7 (or 1.6) CBOM: every algorithm with its OID where one exists (the exact certificate signature algorithm, ECDH on each named curve, legacy ciphers such as 3DES and RC4), certificates with their serial and SHA-256 fingerprint. |
Expand Down
Binary file modified docs/img/endpoints.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/inventory.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/overview-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/report-hybrid-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/report-hybrid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/report-legacy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/report-ssh-baseline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/report-ssh.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/report-starttls.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/ssh-servers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 44 additions & 9 deletions docs/methodology.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,19 @@ traced to a finding and every finding carries its sources.

| Band | Score |
|---|---|
| **Strong** | 90 to 100 |
| **Sound** | 75 to 89 |
| **Excellent** | 90 to 100 |
| **Good** | 75 to 89 |
| **Fair** | 55 to 74 |
| **Weak** | 30 to 54 |
| **Broken** | 0 to 29 |
| **Poor** | 30 to 54 |
| **Failing** | 0 to 29 |
| **Not rated** | no protocol version answered, so there is nothing to rate |

Until PRD-011 the bands were Strong, Sound, Fair, Weak and Broken. They were renamed because *Strong* and *Weak*
are suite-strength words, so one word meant two things on the same page (UX-REVIEW-010 U-1). Stored scans are
migrated, and an evaluation stored with an old name is read as the new one.

**Post-quantum findings are never counted** (category `pqc`). Readiness answers that question, so a well-configured
endpoint that has not yet adopted post-quantum key exchange scores Strong on hygiene and L1 on readiness, and it is
endpoint that has not yet adopted post-quantum key exchange scores Excellent on hygiene and L1 on readiness, and it is
not marked down twice.

The result lists each deduction (rule ID, title, severity, points), any ceiling that changed the outcome, and what is
Expand Down Expand Up @@ -136,7 +140,7 @@ takes every finding except info, orders it by severity, then by whether it stops
untrusted, name mismatch, missing intermediate, no serverAuth, Must-Staple missing, revoked), then by section order,
and shows the first three distinct rules.

## Classical strength (eval/9, PRD-010)
## Classical strength (eval/9, PRD-010; classes and the hash part eval/10, PRD-011)

Every algorithm the product lists has a classical security strength in bits, computed with NIST's own methods.
Where no number applies, it says why instead: a cited break, or no rating. The derivation, with NIST's tables
Expand All @@ -148,14 +152,18 @@ The code is `internal/algo/strength.go` and `strength_of.go`.
| RSA modulus, finite-field DH prime | General Number Field Sieve: E(L) = (1.923·∛(L·ln 2)·∛((ln(L·ln 2))²) − 4.69)/ln 2, rounded to the nearest multiple of eight, at most 256. 1024 → 80, 2048 → 112, 3072 → 128, 4096 → 152, 8192 → 200 | FIPS 140-3 IG D.B; SP 800-56B Rev. 2 Appendix D, Table 4; SP 800-56A Rev. 3, Table 26 |
| Elliptic curves | Half the bit length of the base point's order, taken to the nearest strength SP 800-186 assigns (80, 112, 128, 192, 224, 256): P-256 and Curve25519 → 128, P-384 → 192, Curve448 → 224, P-521 → 256 | SP 800-186 §3 and Table 1 |
| Symmetric ciphers | AES-k → k; 3DES (3TDEA) → 112, disallowed for encryption after 2023; DES, RC4, RC2 → broken. Ciphers NIST does not rate (ChaCha20, Camellia, ARIA, SEED, …) get the bound an exhaustive key search sets, labelled as such | SP 800-57 Part 1 Rev. 5 Table 2; SP 800-131A Rev. 2; RFC 7465 |
| Hashes and MACs | Signatures, where collision resistance is needed: SHA-256 → 128, SHA-384 → 192, SHA-512 → 256; SHA-1 and MD5 → broken. HMAC: SHA-1 → 128, SHA-256 and longer → 256 | SP 800-57 Part 1 Table 3 |
| Hashes and MACs | Signatures, where collision resistance is needed: SHA-256 → 128, SHA-384 → 192, SHA-512 → 256; SHA-1 and MD5 → broken. HMAC, a KDF or a PRF (the TLS PRF, HKDF): SHA-1 → 128, SHA-256 and longer → 256 | SP 800-57 Part 1 Table 3 |
| Signature algorithms | The weaker of the hash (collision strength) and the signer's key, in every spelling (ECDSA-SHA256, SHA256-RSA, sha256WithRSAEncryption, SHA256withRSA). Without the key's size, the hash, and the basis says the key was not given | SP 800-57 Part 1 Tables 2 and 3 |
| Post-quantum algorithms | The classical equivalent of their NIST category: ML-KEM-512/768/1024 → 128/192/256, ML-DSA-44/65/87 → 128/192/256, SLH-DSA by its level | FIPS 203, 204, 205 |
| Hybrids | Secure while either part is, so their stronger part: X25519MLKEM768 → 192 | RFC 10024, RFC 10042 |

**A TLS cipher suite is as strong as its weakest part.** Its parts are the bulk cipher; the key exchange (the
weakest group the server accepts for that version, the DH prime it sent, or, for RSA key transport, the certificate
key); the authentication (the weakest end-entity key the server presented that the suite can use); and, for a
non-AEAD suite, the MAC.
key); the authentication (the weakest end-entity key the server presented that the suite can use); for a non-AEAD
suite, the MAC; and the hash that derives its keys: HKDF's in TLS 1.3, the PRF's in TLS 1.2 (SHA-256 unless the suite
names SHA-384, RFC 5246 §5), the MD5 and SHA-1 pair in TLS 1.0 and 1.1 (secure while either is, RFC 2246 §5, so
128). The hash part is rated in that use; with NIST's numbers it never lowers a suite today, but it counts like any
other part (PRD-011 OD-1), so a later change to the numbers needs no new rule.

| Word | When |
|---|---|
Expand All @@ -168,6 +176,33 @@ An RSA-2048 certificate (112 bits) makes every suite it authenticates *Acceptabl
and the owner's decision OD-1. Each suite states its weakest part and the reason for its word. The words are this
product's own; the numbers are NIST's.

### Classes (PRD-011)

Every algorithm belongs to one class, from its CycloneDX primitive, and has a role within it:

| Class | Primitives | Roles |
|---|---|---|
| **Asymmetric** | `pke`, `signature`, `key-agree`, `kem`, `combiner` (hybrids) | key exchange, signature |
| **Symmetric** | `ae`, `block-cipher`, `stream-cipher`, `mac` | cipher, MAC |
| **Hash** | `hash` | hash (HKDF), hash (PRF), hash (signature) |

A TLS evaluation lists every algorithm the endpoint uses (`algorithms` in the API): its class, role, strength and
post-quantum status, the suites or certificates that use it, and the weakest of each class. A hash is listed once per
use, because its strength depends on the use: SHA-256 deriving keys is 256 bits, signing it is 128. The report's
Configuration opens with this list (*Algorithms in use*); the PDF, `tls scan --details` and the Inventory's *Class*
filter show the same classes.

### One certificate, decoded (PRD-012)

Every certificate in a report's *Chain as served*, its quick look and the CBOM tab opens the certificate's page,
`#/certificates/{sha256}`. The page is decoded from the DER the scan kept (`GET /api/v1/certificates/{sha256}/x509`), so
an older scan gains it without a rescan. In order, it shows: identity, names, the public key (with its classical
strength and post-quantum status), the signature (the weaker of its hash and the issuer's key), every extension with
its criticality and decoded value (one this program does not decode is shown as OID and hex), the fingerprints (SHA-1
as an identifier only) and the PEM, to copy or download. A certificate known only from a machine inventory or an
imported CBOM keeps no DER; its page shows the fields that source gave and says so. Every value comes from the
certificate and is rendered as text.

## SSH

SSH servers share the readiness scale and the findings model. They are **not scored**: an SSH server is judged against
Expand Down
Loading
Loading