WinHTTP合规问询:对等证书无效时应终止TLS握手还是后续阶段?
先明确FIA_X509_EXT1.1的核心合规要求:当检测到对等证书无效时,必须在SSL/TLS握手过程中立即终止连接,绝对不能让握手完成。这个规范的本质是杜绝任何“不可信加密通道”建立的可能性——如果握手完成,意味着客户端和服务器已经完成了密钥交换,哪怕之后马上断开,从合规流程上已经违反了“不与无效证书主体建立安全会话”的要求。
你提到的WinHTTP客户端行为(证书无效仍完成握手,之后在请求前断开),其实是WinHTTP默认证书验证逻辑的局限性:它的默认处理是在握手阶段完成证书检查,但如果没有配置强制终止的逻辑,会允许握手完成,之后在发起请求时才拒绝操作。但这种行为明显不符合FIA_X509_EXT1.1的合规要求。
针对Delphi中使用WinHTTP的场景,你需要做以下调整来满足合规:
启用自定义证书验证回调,在握手过程中实时检测证书有效性:
调用WinHttpSetOption为会话设置WINHTTP_OPTION_STATUS_CALLBACK,实现回调函数处理WINHTTP_CALLBACK_STATUS_SECURE_FAILURE事件。当回调中收到证书错误(比如ERROR_INTERNET_SEC_CERT_INVALID、ERROR_INTERNET_SEC_CERT_CN_INVALID等)时,直接返回FALSE,强制WinHTTP终止握手,而不是让握手流程完成。配置严格的安全标志:
通过WinHttpSetOption设置WINHTTP_OPTION_SECURITY_FLAGS,移除所有SECURITY_FLAG_IGNORE_*类的标志,确保WinHTTP不会忽略任何证书验证错误。比如:var SecurityFlags: DWORD; begin SecurityFlags := SECURITY_FLAG_SECURE; WinHttpSetOption(hSession, WINHTTP_OPTION_SECURITY_FLAGS, @SecurityFlags, SizeOf(SecurityFlags)); end;
举个简单的回调逻辑示例(Delphi下):
function WinHttpCallback(hInternet: HINTERNET; dwContext: DWORD_PTR; dwInternetStatus: DWORD; lpvStatusInformation: Pointer; dwStatusInformationLength: DWORD): DWORD; stdcall; var pSecureFailure: PWINHTTP_SECURE_FAILURE; begin Result := WINHTTP_CALLBACK_STATUS_SUCCESS; case dwInternetStatus of WINHTTP_CALLBACK_STATUS_SECURE_FAILURE: begin pSecureFailure := PWINHTTP_SECURE_FAILURE(lpvStatusInformation); // 检测到任何证书错误,直接终止握手 if (pSecureFailure->dwError <> 0) then begin Result := WINHTTP_CALLBACK_STATUS_ERROR; // 这里可以添加日志记录等操作 end; end; // 处理其他状态... end; end;
这样调整后,当WinHTTP在握手阶段检测到无效证书时,会立即终止连接,不会完成握手流程,完全符合FIA_X509_EXT1.1的合规要求。
最后再强调下:合规要求的核心是“不让无效证书的握手完成”,任何延迟终止的行为(哪怕之后断开)都属于违规,必须在握手过程中第一时间阻断。
内容的提问来源于stack exchange,提问作者Muhammad Uzair Khan

