SSL/TLS Certificate Checker
Overview
Diagnose SSL/TLS certificate issues including expiration, chain problems, misconfiguration, and protocol/cipher weaknesses. Supports both remote endpoints and local certificate files.
Process
Step 1: Identify the Target
Determine what to check:
- Remote endpoint:
host:port(default port 443) - Local certificate file:
.pem,.crt,.cer,.pfx - Certificate store: system trust store
Step 2: Check Remote Certificate
Basic certificate info:
# Full certificate details
echo | openssl s_client -connect [host]:443 -servername [host] 2>/dev/null | openssl x509 -noout -text
# Quick summary (subject, issuer, dates)
echo | openssl s_client -connect [host]:443 -servername [host] 2>/dev/null | openssl x509 -noout -subject -issuer -dates -fingerprint
# Check expiration specifically
echo | openssl s_client -connect [host]:443 -servername [host] 2>/dev/null | openssl x509 -noout -enddate
Windows alternative:
# Check remote certificate
$req = [Net.HttpWebRequest]::Create("https://[host]")
$req.AllowAutoRedirect = $false
$req.Timeout = 10000
try { $req.GetResponse() | Out-Null } catch {}
$cert = $req.ServicePoint.Certificate
[PSCustomObject]@{
Subject = $cert.Subject
Issuer = $cert.Issuer
NotAfter = $cert.GetExpirationDateString()
NotBefore = $cert.GetEffectiveDateString()
}
Step 3: Certificate Chain Verification
# Show full chain
echo | openssl s_client -connect [host]:443 -servername [host] -showcerts 2>/dev/null
# Verify chain
echo | openssl s_client -connect [host]:443 -servername [host] -verify_return_error 2>&1 | grep -E "verify|depth|error"
# Check specific CA bundle
echo | openssl s_client -connect [host]:443 -servername [host] -CAfile [ca-bundle.crt] 2>&1 | grep "Verify return code"
Chain issues to check:
| Issue | Indicator | Fix |
|---|---|---|
| Incomplete chain | "unable to get local issuer certificate" | Add intermediate certs |
| Self-signed | "self signed certificate" | Install CA or add exception |
| Expired intermediate | Intermediate cert past notAfter | Update intermediate |
| Wrong order | Certs not in order leaf→intermediate→root | Reorder chain |
Step 4: Expiration Analysis
# Days until expiration
echo | openssl s_client -connect [host]:443 -servername [host] 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2 | xargs -I{} date -d {} +%s | xargs -I{} echo $(( ({} - $(date +%s)) / 86400 )) days remaining
Expiration thresholds:
| Days Remaining | Severity | Action |
|---|---|---|
| > 30 | OK | No action needed |
| 15-30 | WARNING | Plan renewal |
| 7-14 | HIGH | Renew immediately |
| 1-7 | CRITICAL | Emergency renewal |
| 0 or expired | EXPIRED | Service likely broken |
Step 5: Protocol and Cipher Check
Supported TLS versions:
# Check TLS 1.0 (should be disabled)
echo | openssl s_client -connect [host]:443 -tls1 2>&1 | grep -i "protocol\|error\|alert"
# Check TLS 1.1 (should be disabled)
echo | openssl s_client -connect [host]:443 -tls1_1 2>&1 | grep -i "protocol\|error\|alert"
# Check TLS 1.2
echo | openssl s_client -connect [host]:443 -tls1_2 2>&1 | grep "Protocol\|Cipher"
# Check TLS 1.3
echo | openssl s_client -connect [host]:443 -tls1_3 2>&1 | grep "Protocol\|Cipher"
Cipher strength:
# Currently negotiated cipher
echo | openssl s_client -connect [host]:443 -servername [host] 2>/dev/null | grep "Cipher\|Protocol"
Weak configurations to flag:
| Issue | Risk | Recommendation |
|---|---|---|
| TLS 1.0 enabled | HIGH | Disable |
| TLS 1.1 enabled | MEDIUM | Disable |
| RC4 cipher | HIGH | Remove from config |
| DES/3DES cipher | HIGH | Remove from config |
| No TLS 1.3 | LOW | Enable if possible |
| SHA-1 signature | MEDIUM | Reissue with SHA-256 |
| Key < 2048 bits | HIGH | Reissue with 2048+ |
Step 6: Local Certificate Inspection
Read local cert file:
# PEM format
openssl x509 -in [file.pem] -noout -text
# DER format
openssl x509 -in [file.der] -inform DER -noout -text
# PKCS12 / PFX
openssl pkcs12 -in [file.pfx] -nokeys -info 2>/dev/null
Windows cert store:
# List certificates expiring within 30 days
Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.NotAfter -lt (Get-Date).AddDays(30)} | Select Subject, NotAfter, Thumbprint
# All certs in store
Get-ChildItem Cert:\LocalMachine\My | Select Subject, NotAfter, Issuer | Sort NotAfter
Step 7: Common Issues Diagnosis
| Symptom | Likely Cause | Verification |
|---|---|---|
| "NET::ERR_CERT_DATE_INVALID" | Expired cert | Check enddate |
| "NET::ERR_CERT_AUTHORITY_INVALID" | Unknown CA or self-signed | Check issuer chain |
| "NET::ERR_CERT_COMMON_NAME_INVALID" | Wrong domain in cert | Check SAN/CN |
| "SSL_ERROR_NO_CYPHER_OVERLAP" | No shared ciphers | Check cipher list |
| "ERR_SSL_VERSION_OR_CIPHER_MISMATCH" | Protocol mismatch | Check TLS versions |
| Mixed content warnings | HTTP resources on HTTPS page | Check page resources |
| HSTS error | Cached strict policy | Check HSTS header |
Subject Alternative Names check:
echo | openssl s_client -connect [host]:443 -servername [host] 2>/dev/null | openssl x509 -noout -ext subjectAltName
Step 8: Present Report
## SSL/TLS Certificate Report
**Target:** [host]:443 | **Checked:** [timestamp]
### Certificate Details
| Field | Value |
|-------|-------|
| Subject | [CN] |
| Issuer | [issuer] |
| Valid From | [date] |
| Valid Until | [date] (**[N] days remaining**) |
| Serial | [serial] |
| Signature Alg | [alg] |
| Key Size | [bits] |
| SANs | [domain list] |
### Chain Status
| # | Subject | Issuer | Expires | Status |
|---|---------|--------|---------|--------|
| 0 | [leaf] | [issuer] | [date] | [OK/WARN] |
| 1 | [intermediate] | [issuer] | [date] | [OK/WARN] |
| 2 | [root] | [self] | [date] | [OK/WARN] |
### Protocol & Cipher
| Protocol | Status | Rating |
|----------|--------|--------|
| TLS 1.0 | [enabled/disabled] | [OK/FAIL] |
| TLS 1.1 | [enabled/disabled] | [OK/FAIL] |
| TLS 1.2 | [enabled/disabled] | [OK] |
| TLS 1.3 | [enabled/disabled] | [OK/WARN] |
### Issues Found
- [Issue 1 with severity]
- [Issue 2 with severity]
### Recommendations
1. [Priority actions]
Rules
- NEVER attempt to decrypt or extract private keys
- NEVER modify certificate stores without explicit permission
- ALWAYS use -servername (SNI) for accurate results on shared hosting
- Use timeouts on all network operations
- If openssl is not available, inform user and suggest installation
- Report exact error messages from OpenSSL for debugging
- Check SAN (Subject Alternative Names) not just CN for domain validation