第二章 主流密钥同步协议概述
做密钥同步排查,你得先清楚对方用的什么协议。SSH、TLS、GPG——这三个家伙几乎覆盖了百分之九十的同步场景。我见过不少同学上来就对着日志一通狂翻,却连对方用的是哪种握手方式都没搞清楚,结果白忙活半天。今天咱们就把这三兄弟掰开揉碎,看看它们各自怎么交换密钥、容易在哪儿翻车。
2.1 SSH —— 远程登录的信任桥梁
SSH,说白了就是让你安全地连到另一台机器上敲命令。它最核心的设计是主机密钥验证。服务器启动时生成一对密钥(通常是RSA或Ed25519),客户端第一次连的时候会收到服务器的公钥指纹。你想想看,如果中间有人搞ARP欺骗,客户端拿到的公钥就不对——这就是典型的中间人攻击。
我个人的习惯是,第一次SSH登录时一定核对指纹。很多团队直接配了个StrictHostKeyChecking no,图省事,结果出过几次被劫持换掉密钥的事故。嗯,这里要注意:known_hosts文件里存的是服务器公钥,一旦同步失败,先检查这个文件有没有被篡改。
SSH密钥交换的流程大致是:
- 客户端发起TCP连接,服务端返回自己的主机公钥列表。
- 双方协商加密算法和MAC算法(比如chacha20-poly1305)。
- 通过Diffie-Hellman或ECDH生成会话密钥。
- 后续所有数据用会话密钥加密传输。
我曾经在线上遇到过一个问题:某次升级后所有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的密钥交换支持多种方式: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 --export --armor导出可读的ASCII格式,并在传输后对比指纹SHA256。
2.4 三大协议对比
把这三个协议放在一起看,你会发现它们的核心逻辑是相似的:用非对称密码交换对称会话密钥。区别在于信任模型和管理方式。
| 特性 | SSH | TLS | GPG |
|---|---|---|---|
| 信任模型 | 首次使用信任(TOFU) | CA证书链 | Web of Trust / 直接分发 |
| 公钥分发方式 | 直接交换指纹 | CA签发证书 | 密钥服务器 / 手动交换 |
| 常用场景 | 远程登录、Git推送 | HTTPS、API、IMAP | 文件加密、邮件签名 |
| 容易出问题的地方 | host key变更、known_hosts冲突 | 证书过期、链不完整、域名不匹配 | 公钥过期、指纹错误、子密钥未导出 |
你可以把这张表当作排查前的快速对照。当你收到一个“密钥同步失败”的报错时,先判断是哪个协议层面的问题,再去查对应的日志和配置。别东一榔头西一棒子。
ssh-keyscan抓取当前服务器公钥,与预存的正确指纹比对;TLS用openssl s_client -showcerts导出证书链并检查到期时间;GPG用gpg --list-keys --fingerprint确认公钥指纹。三步能挡住九成以上的同步失败。
2.5 一张图看懂密钥同步协议
下面这张SVG图把三个协议的核心流程画在了一起。你可以看到它们的共同点:先交换公钥/证书,然后协商出临时对称密钥,最后用对称密钥保护数据。区别在于公钥的信任来源和传递方式。
现在你知道了这三个协议的底牌。接下来咱们进入真正的排查环节——当“密钥同步失败”弹出来的时候,该从哪一步开始查。先把这些概念记牢,后面的实操才不会手忙脚乱。