第二章 主流密钥同步协议概述

做密钥同步排查,你得先清楚对方用的什么协议。SSH、TLS、GPG——这三个家伙几乎覆盖了百分之九十的同步场景。我见过不少同学上来就对着日志一通狂翻,却连对方用的是哪种握手方式都没搞清楚,结果白忙活半天。今天咱们就把这三兄弟掰开揉碎,看看它们各自怎么交换密钥、容易在哪儿翻车。

2.1 SSH —— 远程登录的信任桥梁

SSH,说白了就是让你安全地连到另一台机器上敲命令。它最核心的设计是主机密钥验证。服务器启动时生成一对密钥(通常是RSA或Ed25519),客户端第一次连的时候会收到服务器的公钥指纹。你想想看,如果中间有人搞ARP欺骗,客户端拿到的公钥就不对——这就是典型的中间人攻击。

我个人的习惯是,第一次SSH登录时一定核对指纹。很多团队直接配了个StrictHostKeyChecking no,图省事,结果出过几次被劫持换掉密钥的事故。嗯,这里要注意:known_hosts文件里存的是服务器公钥,一旦同步失败,先检查这个文件有没有被篡改。

SSH密钥交换的流程大致是:

  1. 客户端发起TCP连接,服务端返回自己的主机公钥列表。
  2. 双方协商加密算法和MAC算法(比如chacha20-poly1305)。
  3. 通过Diffie-Hellman或ECDH生成会话密钥。
  4. 后续所有数据用会话密钥加密传输。

我曾经在线上遇到过一个问题:某次升级后所有SSH连接都报“Host key mismatch”。查了半天发现是运维把服务器端的/etc/ssh/ssh_host_*文件全部重新生成了,但客户端的known_hosts里的旧指纹没清掉。其实解法很简单,用ssh-keygen -R移除旧记录就行。但这种低级错误,浪费了整个下午。

2.2 TLS —— 网上的安全外衣

TLS是HTTPS、邮件加密、API网关的基础。它的密钥同步比SSH更复杂一点——引入了证书链的概念。服务器需要从CA那里申请签名过的证书,客户端内置了根CA的公钥来验证证书合法。

在实际排错过程中,TLS握手失败的原因往往藏在证书里:
- 证书过期(最常见,我见过某大厂因为一个内部CA证书忘了续签,导致所有微服务间的TLS断链,整站挂了半小时)
- 域名不匹配(证书中的CN/SAN和实际Host对不上)
- 证书链不完整(服务端只发了叶子证书,没发中间CA)

关键点:TLS 1.3大幅简化了握手流程,将RTT从2次降到了1次。如果你的系统支持,我建议优先开启TLS 1.3,能减少一半的同步延迟。

TLS的密钥交换支持多种方式:ECDHE(主流)、DHE、PSK(预共享密钥)。ECDHE能保证前向安全性——即使私钥泄露,之前的会话也无法被解密。我个人特别看重这点,所以在设计API网关时强制使用ECDHE套件。

举一个我踩过的坑:某次配置内部服务的mTLS(双向TLS),两边互相验证证书。客户端一直报“certificate verify failed”。调试了大半天,最后发现是服务端配置了SSL_VERIFY_PEER,但客户端的证书签发CA没被服务端信任。说白了就是CA信任链没配全。你想想看,这种问题光看日志根本看不出,必须用openssl s_client -CAfile手动测试才能定位。

2.3 GPG —— 文件与邮件的加密签名

GPG(GnuPG)用的不是客户端-服务器模型,而是点对点的公钥基础设施。每个人生成自己的密钥对,然后把公钥上传到公钥服务器(如keys.openpgp.org)或者直接分发给对方。同步失败最常见的原因就是:你用的公钥和对方实际用的私钥不匹配。

GPG的密钥同步有几个容易出坑的地方:

  • 公钥签名过期:很多人的GPG密钥都设了过期时间,但忘了续期。对方拿到的公钥签名已失效,加密时就会报“unusable public key”。
  • 不存在于密钥服务器:有些团队把公钥存在内网文件服务器,但同步脚本写错了路径,导致真的公钥没下发。
  • 子密钥 vs 主密钥:GPG支持子密钥用于日常加密,主密钥只用来签名的子密钥。如果同步时只导出了子公钥,对方无法验证你主密钥的签名。
⚠️ 曾经的教训:我曾帮一个客户排查邮件加密失败问题。他们用GPG加密后对方收不到可以解密的邮件。我检查后发现,客户加密时用的公钥是从自己本地导出的,但这个公钥的指纹和对方上传到公钥服务器的指纹差了最后两位——因为有人手动修改过公钥文件里的注释字段。GPG默认不校验注释,但导出的纯二进制公钥被改了,指纹就变了。从那以后,我坚持用gpg --export --armor导出可读的ASCII格式,并在传输后对比指纹SHA256。

2.4 三大协议对比

把这三个协议放在一起看,你会发现它们的核心逻辑是相似的:用非对称密码交换对称会话密钥。区别在于信任模型和管理方式。

特性SSHTLSGPG
信任模型首次使用信任(TOFU)CA证书链Web of Trust / 直接分发
公钥分发方式直接交换指纹CA签发证书密钥服务器 / 手动交换
常用场景远程登录、Git推送HTTPS、API、IMAP文件加密、邮件签名
容易出问题的地方host key变更、known_hosts冲突证书过期、链不完整、域名不匹配公钥过期、指纹错误、子密钥未导出

你可以把这张表当作排查前的快速对照。当你收到一个“密钥同步失败”的报错时,先判断是哪个协议层面的问题,再去查对应的日志和配置。别东一榔头西一棒子。

💡 小提示:我个人在写自动化部署脚本时,会强制在脚本里加一段指纹校验逻辑:SSH用ssh-keyscan抓取当前服务器公钥,与预存的正确指纹比对;TLS用openssl s_client -showcerts导出证书链并检查到期时间;GPG用gpg --list-keys --fingerprint确认公钥指纹。三步能挡住九成以上的同步失败。

2.5 一张图看懂密钥同步协议

下面这张SVG图把三个协议的核心流程画在了一起。你可以看到它们的共同点:先交换公钥/证书,然后协商出临时对称密钥,最后用对称密钥保护数据。区别在于公钥的信任来源和传递方式。

密钥同步协议核心流程对比 SSH 主机密钥交换 客户端发起 TCP 连接 服务端返回公钥指纹 DH/ECDH 协商会话密钥 加密传输数据 TLS 证书链验证 ClientHello 携带加密套件 服务端返回证书链 客户端验证 CA 签名+域名 ECDHE 生成会话密钥 GPG 公钥分发 生成密钥对(RSA/Ed25519) 导出公钥(ASCII armored) 对方导入公钥并验证指纹 用对方公钥加密数据/文件 共同点 非对称密钥交换公钥 → 协商对称密钥 → 密钥同步成功

现在你知道了这三个协议的底牌。接下来咱们进入真正的排查环节——当“密钥同步失败”弹出来的时候,该从哪一步开始查。先把这些概念记牢,后面的实操才不会手忙脚乱。