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
2 changes: 1 addition & 1 deletion ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ chain: `env_var.into_iter().chain(probe_dirs).chain(known_dirs)`.
| fingerprint.rs | 100.00% | |
| parser.rs | 86.12% | Error paths, Ed448, unknown OIDs |
| util.rs | 98.53% | |
| verify.rs | 82.18% | Partial chain, CRL edge cases |
| verify/ (all) | 82.18% | Split into chain, checks, constraints, crl, helpers, trust_store, webpki |
| main.rs | 25.62% | CLI binary; integration tests run externally |
| **TOTAL** | **69.55%** | Library avg ~91%; main.rs drags total down |
37 changes: 11 additions & 26 deletions PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ improvement opportunities organized by review category.

## Current State Summary

- **240 tests passing** (217 integration + 15 pyca + 8 zlint)
- **276 tests passing** (36 unit + 217 integration + 15 pyca + 8 zlint)
- **0 clippy warnings**
- **Formatting clean** (cargo fmt passes)
- **All test vectors working** (pyca and zlint submodules fully functional)
Expand Down Expand Up @@ -34,7 +34,7 @@ The codebase follows Rust style conventions consistently.
### Issues Found

1. **README.md test count outdated**: States "210 integration tests" but actual
count is 217 integration tests + 15 pyca + 8 zlint = 240 total tests.
count is 36 unit + 217 integration + 15 pyca + 8 zlint = 276 total tests.

2. **docs/design.md outdated**: Lists "Full chain validation" as a non-goal, but
the `verify` subcommand is fully implemented with comprehensive chain
Expand All @@ -48,7 +48,7 @@ The codebase follows Rust style conventions consistently.

### Recommended Changes

- [ ] Update README.md test counts to 240 total
- [x] Update README.md test counts to 276 total
- [ ] Update docs/design.md to reflect that chain verification is implemented
- [ ] Update docs/design.md dependency versions
- [ ] Remove or update outdated Phase references in docs
Expand All @@ -57,26 +57,10 @@ The codebase follows Rust style conventions consistently.

## 3. Refactoring Opportunities

### 3.1 verify.rs Module Size (2378 lines)
### 3.1 verify module (previously single file, now split)

The verification module is the largest in the codebase. While the internal
structure is well-factored with helper functions, it could benefit from being
split into submodules:

```
verify/
├── mod.rs # Public API, VerifyOptions, VerificationResult
├── trust_store.rs # TrustStore implementation
├── chain.rs # Chain building (DFS path building)
├── constraints.rs # Name Constraints checking
├── crl.rs # CRL parsing and revocation checking
├── webpki.rs # WebPKI policy validation
└── helpers.rs # extract_*, verify_*, is_*
```

**Impact**: Medium (maintainability improvement)
**Effort**: Low-medium
**Priority**: Low (current structure is functional)
The verification module was the largest in the codebase (2378 lines) and has
been split into submodules. See Completed Improvements below for details.

### 3.2 main.rs Batch Processing

Expand Down Expand Up @@ -151,10 +135,11 @@ All test vectors work correctly:

| Category | Tests | Status |
|----------|-------|--------|
| Unit tests (lib + CLI) | 36 | ✓ All pass |
| Integration tests | 217 | ✓ All pass |
| pyca/cryptography | 15 | ✓ All pass |
| zlint | 8 | ✓ All pass |
| **Total** | **240** | ✓ All pass |
| **Total** | **276** | ✓ All pass |

### Test Coverage

Expand Down Expand Up @@ -240,7 +225,7 @@ The codebase uses appropriate standard libraries:

1. Test count says "210 integration tests" in project structure section
2. Test count says "155 integration tests" in xcert-lib description
3. Both should say "217 integration tests" (or "240 total tests")
3. Both should say "276 total tests"

### docs/design.md Issues

Expand Down Expand Up @@ -282,7 +267,7 @@ resolved." The file documents closed issues appropriately.

### Documentation Updates (Completed)

1. README.md: Updated test counts to 217 integration tests, 240 total
1. README.md: Updated test counts to 276 total
2. docs/design.md: Updated to reflect chain verification is implemented
3. docs/design.md: Updated x509-parser version to 0.18

Expand All @@ -306,7 +291,7 @@ resolved." The file documents closed issues appropriately.

### Verification

- All 240 tests pass (217 integration + 15 pyca + 8 zlint)
- All 276 tests pass (36 unit + 217 integration + 15 pyca + 8 zlint)
- Zero clippy warnings
- Clean formatting

Expand Down
76 changes: 68 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,48 @@

A fast, memory-safe command-line tool for inspecting X.509 certificates. Read-only alternative to `openssl x509` with JSON output and colored terminal display.

## Quick Start

```bash
# Build
cargo build --release

# Generate a test certificate (or use any .pem/.der file you have)
openssl req -x509 -newkey rsa:2048 -keyout /dev/null -out test.pem \
-days 365 -nodes -subj "/CN=example.com"

# Inspect it
target/release/xcert show test.pem
```

Example output:

```
Certificate:
Version: 3 (0x2)
Serial: 10:00
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, ST = California, O = Test PKI, CN = Test Intermediate CA
Validity:
Not Before: Feb 24 22:17:10 2026 GMT
Not After: Feb 24 22:17:10 2101 GMT
Subject: C = US, ST = California, L = San Francisco, O = Example Corp, CN = www.example.com
Public Key:
Algorithm: RSA (2048 bit)
Exponent: 65537 (0x10001)
Extensions:
Basic Constraints: CA=false
Key Usage: [critical] Digital Signature, Key Encipherment
Extended Key Usage: TLS Web Server Authentication
Subject Alternative Name:
DNS: www.example.com
DNS: example.com
Email: admin@example.com
Authority Information Access:
OCSP: http://ocsp.example.com
Fingerprint (SHA-256): E8:74:48:2A:8B:AA:...
```

## Installation

```bash
Expand Down Expand Up @@ -35,13 +77,22 @@ xcert show /etc/ssl/certs/ --recurse

```bash
xcert field subject cert.pem
# Output: C = US, ST = California, O = Example Corp, CN = www.example.com

xcert field serial cert.pem
xcert field not-after cert.pem
# Output: 10:00

xcert field fingerprint cert.pem
# Output: E8:74:48:2A:8B:AA:E7:36:9D:5B:51:2A:60:12:34:29:...

xcert field dns-names cert.pem
# Output:
# www.example.com
# example.com
# *.example.com

xcert field fingerprint --digest sha384 cert.pem
xcert field curve cert.pem # EC curve name (e.g. P-256)
xcert field dns-names cert.pem # DNS names from SAN
xcert field ip-addrs cert.pem # IP addresses from SAN
xcert field curve ec-cert.pem # EC curve name (e.g. P-256)
xcert field san --json cert.pem
xcert field public-key cert.pem

Expand Down Expand Up @@ -79,14 +130,21 @@ Returns exit code 0 for pass, 1 for fail.

```bash
xcert check expiry 30d cert.pem # Valid for 30+ days?
xcert check expiry 1w cert.pem # Valid for 1+ week?
xcert check host example.com cert.pem
# (exit code 0 = yes, 1 = no)

xcert check host www.example.com cert.pem
# (exit code 0 = matches, 1 = no match)

xcert check email user@example.com cert.pem
xcert check ip 93.184.216.34 cert.pem

# Use in scripts:
if xcert check expiry 7d cert.pem; then
echo "Certificate is valid for at least 7 more days"
fi

# Bulk: check all certs in a directory
xcert check expiry 30d /etc/ssl/certs/
xcert check expiry 30d /etc/ssl/certs/ --json
xcert check expiry 7d --failures-only /etc/ssl/certs/
```

Expand All @@ -106,6 +164,8 @@ Units: `s`, `m`/`min`, `h`/`hr`, `d`/`day`, `w`/`week`, `month`, `y`/`year`.

```bash
xcert verify chain.pem
# Output: chain.pem: OK, www.example.com, 10:00

xcert verify --hostname example.com chain.pem
xcert verify --CAfile ca.pem chain.pem
xcert verify --untrusted intermediates.pem leaf.pem
Expand Down Expand Up @@ -141,7 +201,7 @@ Options:
### Convert between formats

```bash
xcert convert cert.pem cert.der # PEM to DER
xcert convert cert.pem cert.der # PEM to DER (format inferred from extension)
xcert convert cert.der cert.pem # DER to PEM
xcert convert cert.pem --to der # Explicit format (stdout)
```
Expand Down
Loading