不使用 OpenSSL 运行

sgcWebSockets 可以完全不加载任何 OpenSSL 库运行。有两个相互独立的设置能做到这一点,二者都建立在纯 Pascal 的 sgcCrypto 各单元之上,该单元从 Standard 版起提供。

既不需要 OpenSSL 承担连接、也不需要它承担其他加密工作的应用程序,会同时使用这两者。

1. 运行时开关:sgcCryptoBackend

sgcBase_Helpers 单元声明了类型为 TsgcCryptoBackend 的全局变量 sgcCryptoBackend:

该开关是全局的,不针对单个组件。请在创建任何组件之前、启动时设置一次。sgcUseNativeCrypto 在使用原生后端时返回 True。原生后端需要编译进 sgcCrypto 单元(SGC_CRYPTO)。如果没有编译进去,cbNative 会引发异常 "Native crypto not available, sgcCrypto units are not compiled in"。调用 sgcCheckNativeCrypto 可以在启动时就得到该错误,而不必等到首次使用时才发现。

uses
  sgcBase_Helpers;

begin
  sgcCryptoBackend := cbNative;
  sgcCheckNativeCrypto;
  Application.Initialize;
  ...

以下这些部分遵循该开关:

区域 原生运行的内容
哈希与 HMAC 辅助函数 sgcBase_Helpers 的哈希和 HMAC 函数,以及 sgcEncryptString / sgcDecryptString。
JWT、JWS 签名 HMAC、RSA、RSA-PSS、ECDSA 和 EdDSA 的签名与验证(sgcSSL_RSA、sgcSSL_PS、sgcSSL_ES、sgcSSL_ED)。sgcES_GetCurveFromPublicKey 只能处理 OpenSSL 密钥,在原生后端上会引发异常。
证书 sgcSSL 辅助函数:PEM 与 DER 转换、证书加载、CRL URI 以及证书链验证。
OAuth2 与 DPoP OAuth2 的 JWK 辅助函数,以及 OAuth2 服务器对 DPoP 证明的校验(ES256、ES384、ES512、RS256、RS384、RS512)。参阅 DPoP。
Amazon AWS Signature V4、CloudFront 签名 URL,以及 Amazon IoT MQTT 客户端的 Signature V4 身份验证,此时其 SignatureV4.OpenSSL_Options 会被忽略。
Web Push VAPID ES256 令牌、ECDH 密钥协商、HKDF 以及 AES-128-GCM 负载加密。只有到推送服务的 https 连接会通过其 IOHandler 加载 TLS 库。
E2EE 密钥协商、AES-GCM 以及随机数生成器。两种后端在网络上传输的公钥都是 PEM 格式,原始密钥格式仍然可以接受,因此不同后端的对端可以互通。
WebAuthn、SAML、OIDC WebAuthn 的证书、COSE 密钥和认证检查,以及 SAML 和 OIDC 使用的 XMLDSig 签名校验。
NTLM NTLM 身份验证的 MD4 和 DES 代码。它在所有构建中都是原生实现,不再需要任何编译器定义。
AEAD、KEM、HKDF sgcSSL_AEAD(AES-128-GCM、AES-256-GCM、ChaCha20-Poly1305)、sgcSSL_KEM(ML-KEM-768 和 ECDH P-256)以及 sgcSSL_HKDF(现在还支持 sgcHKDF_MD_SHA384)。ML-KEM-768 不需要 OpenSSL 3.5,且密钥编码与 OpenSSL 3.5 相同。在 FIPS 构建中,ChaCha20-Poly1305 不可用,会引发异常。
QUIC、DTLS、SRTP QUIC 报文保护、DTLS 证书以及 SRTP。使用 iohNativeTLS 时,无论该开关如何设置,它们每条连接都已经是原生实现。

sgcCryptoBackend 不会改变某个组件的 TLS 连接。保持 IOHandler = iohOpenSSL 的组件在连接时仍会加载 OpenSSL。

2. 可选的编译器定义:SGC_NATIVE_CRYPTO

该定义默认关闭,现在已经不再是不使用 OpenSSL 运行所必需的了。不启用它时,OpenSSL 代码和原生代码都会被编译进去,由 sgcCryptoBackend 在运行时决定使用哪一个。启用它后,无论 sgcCryptoBackend 如何设置都会强制使用原生后端,并且应用加密单元中的 OpenSSL 代码会被移除,因此可执行文件更小。要启用它,请打开 sgcVer.inc,删除下面这一行前面的点:

{.$DEFINE SGC_NATIVE_CRYPTO}

或者把 SGC_NATIVE_CRYPTO 加入您项目的条件定义中。SGC_NATIVE_CRYPTO 同时会打开它所依赖的 sgcCrypto 单元所需的 SGC_CRYPTO。DISABLE_SGC_NATIVE_CRYPTO 可再次将其关闭。

3. 运行时零 OpenSSL

需要哪些设置,取决于应用程序使用了什么:

区域 实现零 OpenSSL 的设置
基于 TCP 的 TLS:WebSocket、HTTP/1、HTTP/2、TCP、MQTT 及其他协议 TLSOptions.IOHandler(客户端)或 SSLOptions.IOHandler(服务器)= iohNativeTLS。参阅 原生 TLS。
QUIC 和 HTTP/3 IOHandler = iohNativeTLS。握手、报文保护、密钥更新以及 Retry 标签均为原生实现。参阅 QUIC 和 HTTP/3。
DTLS 和 WebRTC DTLSOptions.IOHandler = iohNativeTLS。握手、DTLS 证书以及 SRTP 密钥均为原生实现。参阅 DTLSOptions 和 WebRTC DTLS。
应用加密:JWT、OAuth2、Web Push、Amazon Signature V4、E2EE、WebAuthn、SAML 以及第一张表中的其他区域 启动时设置 sgcCryptoBackend := cbNative,或者使用 SGC_NATIVE_CRYPTO 编译器定义。

iohNativeTLS 所在的几行都不需要任何编译器定义或 sgcCryptoBackend 设置。在不包含 sgcCrypto 单元的构建中选择 iohNativeTLS 会引发异常,绝不会静默回退到 OpenSSL。

iohNativeTLS

使用 iohNativeTLS 时,TLS 1.3 和 TLS 1.2 握手以及记录层运行在原生引擎上。它适用于 WebSocket、HTTP/1、HTTP/2 和 TCP 客户端及服务器,以及建立在它们之上的一切:MQTT、AMQP、STOMP 及其他协议,各 API 组件,IoT 客户端(Certificate.IOHandler),代理服务器的上游连接(Proxy.TLSOptions),以及 LDAP 客户端。证书可以是 PEM、DER 或 .pfx / .p12 文件。