TsgcWebSocketClient | SChannel Certificate Revocation

TLSOptions.VerifyCertificate 设置为 True,可以确认服务器证书链是受信任的,并且其中包含所连接的主机名。但它完全无法说明该证书自颁发以来是否已被吊销。

这个缺口很重要:如果私钥被窃取,其证书虽已被吊销但尚未过期,那么该证书仍然能够成功通过身份验证,而这正是吊销机制要解决的场景。只有在明确要求时,才会通过 TLSOptions.SChannel_Options.Revocation 检查吊销状态。


oClient.TLS := True;
oClient.TLSOptions.IOHandler := iohSChannel;
oClient.TLSOptions.VerifyCertificate := True;
oClient.TLSOptions.SChannel_Options.Revocation.Check := scrcChainExcludeRoot;

吊销状态是在构建证书链的过程中获取的,这意味着握手期间会连接证书中指定的 CRL 分发点或 OCSP 响应方。这正是该检查默认关闭的原因:启用它会为每个新连接增加网络流量。

Check

用于选择对证书链中的哪些部分查询吊销状态。

scrcDisabled 默认值。不获取任何吊销状态,也不要求提供吊销状态。
scrcEndCertificate 仅检查服务器证书。开销最小的选项,每个连接只查询一次。
scrcChainExcludeRoot 检查服务器证书和中间证书,但不检查根证书。这是通常的选择,因为自签名的根证书很少为自身发布 CRL。
scrcChain 包括根证书在内的整个证书链。

Timeout

整个吊销信息获取过程所允许的毫秒数,而不是每个 URL 的毫秒数,因此不作应答的响应方无法拖住握手过程。默认值为 5000。值为零时将沿用 Windows 的默认值,而该值可能长得多。

CacheOnly

为 True 时,仅使用 Windows 已缓存的吊销数据,握手过程绝不会访问网络,因此永远不会被延迟。此时若缓存为空,吊销状态将无法确定,该情况由 IgnoreNoRevocationCheck 决定。默认值为 False。

IgnoreRevocationOffline

决定无法连接响应方时的处理方式。默认值为 True,即接受该证书,这也是 Web 浏览器采用的软失败行为。将其设置为 False 则改为拒绝。拒绝更为严格,但这会使每个连接都依赖于响应方是否可达,因此响应方一旦中断,您的应用程序也会随之中断。

IgnoreNoRevocationCheck

决定当证书完全没有发布 CRL 分发点和 OCSP 响应方,因而无法确定其状态时的处理方式。默认值为 True,即接受该证书。

这两个 Ignore 属性都绝不会接受已确认被吊销的证书。这种结果始终会被拒绝。

报告的错误

当连接被拒绝时,原因会作为下列值之一传递给 OnSChannelVerifyPeer 事件:

ecCryptRevoked 证书已被其颁发者吊销。始终拒绝。
ecCryptRevocationOffline 无法连接响应方。仅当 IgnoreRevocationOffline 为 False 时才拒绝。
ecCryptNoRevocationCheck 证书未发布任何吊销信息。仅当 IgnoreNoRevocationCheck 为 False 时才拒绝。

安全默认值

TLSOptions.Preset 设置为 tlspSecureDefaults,会连同其他强化默认值一起把该检查启用为 scrcChainExcludeRoot,同时保留这两项软失败设置,因此启用它不会破坏原本可以正常工作的连接。如果您在应用该预设之前已自行选择了检查范围,则该范围保持不变。


oClient.TLSOptions.Preset := tlspSecureDefaults;