文章目录1. TLCP 为什么经常说“双证书”2. 一次简化版 TLCP 握手3. 本工程默认密码套件怎么理解3.1 TLCP_ECC_SM4_GCM_SM33.2 TLCP_ECC_SM4_CBC_SM33.3 为什么默认不启用 ECDHE4. sm2sig_sm3 为什么重要5. TrustManager、KeyManager 在握手里分别做什么5.1 TrustManager验证对方5.2 KeyManager证明自己6. Hostname 校验在 TLCP 里还要不要7. TLCP 握手问题如何分层7.1 TCP 层7.2 协议层7.3 密码套件层7.4 签名算法层7.5 证书链层7.6 Hostname 层8. 本工程怎么记录握手8.1 socketPreparations8.2 handshakes8.3 hostnameChecks9. 新手最该记住的 5 句话普通 TLS 新手最容易卡在“证书链”TLCP 新手更容易卡在“为什么服务端有两张证书”“为什么有 ECC 和 ECDHE 两类套件”“为什么客户端有时也要双证书”。这一篇专门讲 TLCP 的握手和双证书。1. TLCP 为什么经常说“双证书”TLCP/国密 SSL 的典型服务端会使用两套 SM2 证书/私钥证书用途类比签名证书证明服务端身份对握手关键参数签名“我是谁”加密证书用于密钥交换中加密预主密钥等“给我发秘密时用这把公钥加密”普通 TLS 里服务端通常一张证书就能承担认证用途密钥交换可以走 RSA/ECDHE 等不同机制。TLCP 的国密双证书体系把签名和加密用途分开了。Tongsuo 文档也把 NTLS/TLCP 的特点描述为加密证书/私钥和签名证书/私钥相分离。2. 一次简化版 TLCP 握手用本工程默认单向认证场景举例客户端只验证服务端客户端自己不发证书。1. ClientHello - 客户端说我支持 TLCPv1.1 - 我支持这些密码套件TLCP_ECC_SM4_GCM_SM3 / TLCP_ECC_SM4_CBC_SM3 - 我支持签名算法sm2sig_sm3 2. ServerHello - 服务端选择 TLCPv1.1 - 服务端选择一个双方都支持的密码套件 3. Certificate - 服务端发送签名证书和加密证书 - 证书链可能包含中间 CA 4. ServerKeyExchange - 服务端用签名证书对应私钥对关键参数签名 5. 客户端验证 - 验证证书链是否能链到本地 TrustStore - 验证证书签名算法、公钥算法是否支持 - 验证 ServerKeyExchange 签名 6. ClientKeyExchange - 客户端生成预主密钥 - 用服务端加密证书公钥加密后发给服务端 7. 双方派生会话密钥 - 后续 HTTP 数据用 SM4 保护 8. Finished - 双方确认握手没有被篡改真正协议细节比这个多但新手先抓住三点服务端身份靠签名证书证明关键秘密用加密证书保护CA 链验证失败、签名算法不支持、密码套件不匹配都会导致握手失败。3. 本工程默认密码套件怎么理解application.yml默认enabled-cipher-suites:-TLCP_ECC_SM4_GCM_SM3-TLCP_ECC_SM4_CBC_SM33.1TLCP_ECC_SM4_GCM_SM3可以粗略拆成片段含义TLCP协议族ECC静态 ECC-SM2 相关密钥交换/认证模式SM4对称加密算法GCMAEAD 工作模式SM3杂凑/完整性相关算法3.2TLCP_ECC_SM4_CBC_SM3和上面类似只是 SM4 的工作模式从 GCM 换成 CBC。3.3 为什么默认不启用 ECDHEREADME 里已经提示当前默认没有客户端证书所以先启用常见 ECC 套件。如果服务端只接受TLCP_ECDHE_*通常要同时配置客户端证书 KeyStore再把 ECDHE 套件加入列表。示例enabled-cipher-suites:-TLCP_ECDHE_SM4_GCM_SM3-TLCP_ECDHE_SM4_CBC_SM3-TLCP_ECC_SM4_GCM_SM3-TLCP_ECC_SM4_CBC_SM3client-key-store:path:file:/secure/client.p12type:PKCS12password:changeitkey-password:changeit是否必须客户端证书要以服务端配置为准。你不能只看客户端代码猜。4.sm2sig_sm3为什么重要本工程默认client-signature-schemes:-sm2sig_sm3启动时KonaProviderInitializer会把它写到com.tencent.kona.ssl.client.signatureSchemes这个系统属性会影响 ClientHello 里的signature_algorithms扩展。如果服务端是 SM2 证书而客户端没有告诉服务端“我支持 SM2 with SM3 签名”服务端可能无法选择合适签名算法常见错误是no suitable signature algorithm所以联调时第一批要确认的字段包括{tlcp:{konaClientSignatureSchemes:sm2sig_sm3}}如果这里是空的先别怀疑业务接口先修客户端签名算法配置。5. TrustManager、KeyManager 在握手里分别做什么5.1 TrustManager验证对方客户端的 TrustManager 用于验证服务端证书链。本工程构造 TrustManager 的核心路径trust-certificates 配置 ↓ ResourceLoader 读取 classpath:/file:/绝对路径/相对路径 ↓ CertificateFactory(X.509, KonaPKIX) 解析证书 ↓ KeyStore(JKS, KonaPKIX) 临时装入 CA ↓ TrustManagerFactory(PKIX, KonaSSL) 生成 TrustManager重点对 SM2 证书链不要随手换成默认 JDK Provider。否则可能证书解析或签名验证阶段失败。5.2 KeyManager证明自己客户端 KeyManager 用于客户端证书认证。只有配置了client-key-store.path本工程才会加载 KeyStore 并创建 KeyManager。路径client-key-store.path ↓ KeyStore(type, KonaPKIX) 加载 PKCS12/JKS ↓ KeyManagerFactory(NewSunX509, KonaSSL) ↓ SSLContext.init(keyManagers, trustManagers, random)6. Hostname 校验在 TLCP 里还要不要要。TLCP 解决的是传输安全协议和国密算法问题不代表你可以忽略证书主体匹配。证书链校验回答这张证书是不是可信 CA 签出来的Hostname 校验回答这张证书是不是发给我正在访问的这个 host/IP 的本工程为了兼容内网 IP 联调默认关闭hostname-verification-enabled:false生产建议开启。正确做法是让服务端证书 SAN 包含访问域名或 IP而不是长期关闭校验。7. TLCP 握手问题如何分层看到握手失败时不要马上乱改密码套件。先按层看7.1 TCP 层现象Connection refused No route to host Connection timed out说明还没进 TLCP。检查 IP、端口、防火墙、服务是否监听。7.2 协议层现象wrong version number unsupported protocol可能客户端说 TLCP服务端端口不是 TLCP或者服务端说普通 TLS客户端只启用 TLCP。7.3 密码套件层现象handshake_failure no cipher suites in common检查enabled-cipher-suites与服务端支持列表是否有交集。7.4 签名算法层现象no suitable signature algorithm优先检查sm2sig_sm3是否生效。7.5 证书链层现象PKIX path building failed CertPathValidatorException certificate verify failed检查 CA 链是否完整、证书是否过期、是否把服务端证书误当 CA、Provider 是否是 Kona。7.6 Hostname 层现象Hostname ... not verified No subject alternative names matching IP address ...检查 SAN/CN 和访问地址是否匹配。8. 本工程怎么记录握手TlcpHandshakeRecorder会记录三类信息{tlcpTrace:{socketPreparations:[],handshakes:[],hostnameChecks:[]}}8.1socketPreparations能看到 socket 上实际启用的协议和密码套件{enabledProtocols:[TLCPv1.1],enabledCipherSuites:[TLCP_ECC_SM4_GCM_SM3,TLCP_ECC_SM4_CBC_SM3]}如果这里没有记录可能失败发生在 socket 创建前比如 OkHttp ConnectionSpec 校验、URL 构造、证书文件读取。8.2handshakes握手完成后才会有。可以看到协议密码套件peer certificatessession idprincipal。如果handshakes为空但socketPreparations有记录说明 socket 已经准备好但握手没有完成。8.3hostnameChecks能看到 Hostname Verification 是否启用、校验目标是什么、结果是什么。9. 新手最该记住的 5 句话TLCP 常见服务端有签名证书和加密证书不要只按普通 TLS 单证书理解。客户端 TrustStore 放 CA客户端 KeyStore 放自己的证书和私钥。sm2sig_sm3缺失会导致 SM2 证书服务端签名算法协商失败。密码套件必须和服务端有交集ECC/ECDHE 是否需要客户端证书要问服务端。联调可以临时关闭 hostname verification但生产应让 SAN 匹配并开启。下一篇开始读本工程代码地图把这些概念对应到具体类和配置。