实现原理:离线 vs 在线分析
对应代码:
pkg/offline.go(NewOfflineAnalysis+ FromCert 函数族)+ 在线函数分布于各模块
cert-skills 每个分析能力几乎都有"在线域名"和"离线证书"两个版本。本页讲这套双模架构的设计、函数签名与边界。
双模全景
离线入口
func NewOfflineAnalysis(cert *x509.Certificate, intermediates ...*x509.Certificate) *OfflineAnalysisResult把已解析的证书 + 可选中间证书池(变长参数)包成结果,Target = cert.Subject.CommonName,构造 *x509.CertPool。全程零网络。
FromCert 函数签名表
| 函数 | 签名 | 底层调用 |
|---|---|---|
AnalyzeSecurityFromCert | (cert *x509.Certificate, host string) (*SecurityAnalysis, error) | 转发 AnalyzeSecurityFromCertWithState(cert, host, nil) |
AnalyzeSecurityFromCertWithState | (cert, host string, state *tls.ConnectionState) (*SecurityAnalysis, error) | ScanCertSecurityFromChain → 映射 issue → 离线评分 |
CheckDistrustedCAFromCert | (chain []*x509.Certificate) *DistrustedCAResult | 遍历 chain,fingerprintCert + matchDistrustedCA |
CheckKeyUsageFromCert | (cert *x509.Certificate) *KeyUsageComplianceResult | 4 条规则内联,keyUsageToStrings/extKeyUsageToStrings |
CheckPolicyFromCert | (cert *x509.Certificate) *PolicyAnalysisResult | cert.PolicyIdentifiers + knownPolicyOIDs + determineValidationType |
CheckNameConstraintsFromCert | (chain []*x509.Certificate) *NameConstraintsResult | 需 len(chain)>=2;collectLeafNames + extractCAConstraint |
ScanCertSecurityFromChain | (cert, host string, state *tls.ConnectionState) (*CertSecurityResult, error) | 18 项 certCheck(state==nil 时 12 项) |
fingerprintCert(L328-334):GenerateFingerprints(cert)["sha256"],取不到返回 ""。
共享核心
ScanCertSecurityFromChain 是两者共用核心——state==nil 自动只跑前 12 项。这套设计让离线模式复用同一套证书层规则,不重复实现。
离线 issue 映射
离线版把未通过检查直接映射成 issue(offline.go L55-64):
issue.Severity = check.Severity
issue.Type = check.Code // 如 "CERT-005"
issue.Description = check.Name
issue.Impact = check.Detail然后用离线专属权重算分。
离线 vs 在线评分权重精确对比
| 维度 | 在线(security.go L361-393) | 离线(offline.go L67-95) |
|---|---|---|
| Critical 扣分 | −30 | −25 |
| High 扣分 | −20 | −15 |
| Medium 扣分 | −10 | −5 |
| Low 扣分 | −5 | −2 |
| Good 阈值 | ≥90 | ≥80 |
| Medium 阈值 | ≥70 | ≥60 |
| Low 等级 | ≥50 | —(无 Low 等级) |
| High 等级 | —(无 High 等级) | ≥40 |
| Critical 阈值 | <50 | <40 |
| 起始分 | 100 | 100 |
| 下限 | 0 | 0 |
关键差异:
- 离线每级少扣 5 分(更宽容)
- 但等级阈值更严:Good 从 90 降到 80;离线无 "Low" 等级,多一个 "High" 等级覆盖 40-59
- 同一张证书在 40-59 区间:在线判 Critical,离线判 High
设计哲学:宁可宽松,不误判
离线拿不到协议层信息,少了一大块扣分来源。所以离线权重每级少扣 5 分,等级阈值也更宽容——宁可偏宽松,也不因缺信息误判为高风险。这是诚实的工程权衡。
能做与不能做
CLI 如何路由:文件后缀自动切换
CLI 层用文件后缀自动路由(isFileTarget,helpers.go):
所以 cert-skills analyze ./server.pem 自动走离线,cert-skills analyze example.com 走在线——同一命令,双模自动切换。
MCP 与 CLI 的不对称
MCP 工具大多只支持在线域名(需要 tls.ConnectionState)。离线文件分析请用 CLI 的文件路径模式(cert-skills analyze ./server.pem)。
离线场景
CI、取证、批量文件、历史证书——这些场景要么无网络,要么目标已下线。离线模式让同一套证书层规则在这些场景复用。
在线专属能力
以下必须在线,无离线版:
scan-vulns(漏洞扫描,需 raw TLS)jarm/ja3(需握手)check-hsts(需 HTTP 响应头)check-caa(需 DNS 查询,但解析逻辑有 wire 离线版)check-ocsp-must-staple(属协议层,需 OCSP staple)check-revocation的 OCSP 部分(CRL 部分可离线)