Removing the OpenSSL DLLs from a Delphi application used to be a build decision. You turned on a compiler define, rebuilt, and shipped a second executable to the customers who could not have OpenSSL on their machines. sgcWebSockets 2026.10 turns it into a runtime decision: one global variable, set once at startup, chooses whether the application cryptography runs on OpenSSL or on the cryptography built into the library, written in Object Pascal.
The connection side, TLS without OpenSSL, is covered in Delphi TLS 1.3 Without OpenSSL DLLs. This post is about everything else: the signatures, hashes, key agreement and encryption your application does outside the TLS handshake.
One Line at Startup
The unit sgcBase_Helpers declares the global sgcCryptoBackend, of type TsgcCryptoBackend:
uses
sgcBase_Helpers;
begin
sgcCryptoBackend := cbNative;
sgcCheckNativeCrypto;
Application.Initialize;
...
The switch is global, not per component, so set it before any component is created. sgcCheckNativeCrypto is optional: if the native crypto units are not compiled in, it raises at startup with a clear message instead of on the first signature your application tries to make.
Three Values
cbOpenSSLis the default. The application cryptography runs on OpenSSL, exactly as in previous versions, so upgrading changes nothing until you set the variable.cbNativeruns the application cryptography on the Object Pascal implementation. OpenSSL is never loaded for it.cbAutouses OpenSSL when its libraries can be loaded and the native code when they cannot. The check runs once and the result is cached.
cbAuto is the one for products that are deployed both ways. Some customers install the OpenSSL libraries next to the executable, some are not allowed to, and the same build works for both without a support ticket about a missing DLL.
// same executable, with or without the OpenSSL libraries beside it
sgcCryptoBackend := cbAuto;
What Follows the Switch
The switch covers the cryptography the components do on your behalf:
- the hashing and HMAC helpers;
- JWT signing and verification, HS, RS and ES;
- OAuth2 and DPoP proofs;
- AWS Signature V4 and CloudFront signed URLs;
- Web Push;
- end-to-end encryption (E2EE), where peers on different backends interoperate, so a client on
cbNativetalks to a server still on OpenSSL; - WebAuthn and passkeys;
- SAML and XML signatures;
- NTLM;
- AEAD, ML-KEM and HKDF;
- QUIC packet protection, the DTLS and WebRTC certificates and SRTP.
None of these need a code change. A JWT that was signed with OpenSSL yesterday is signed natively today because the variable says so.
The Connections Are a Separate Setting
sgcCryptoBackend does not change how a component connects. The TLS of a connection is chosen per component, with IOHandler = iohNativeTLS, on the TCP, HTTP and WebSocket components and everything built on them, such as MQTT, on QUIC and HTTP/3, and on DTLSOptions for WebRTC:
sgcCryptoBackend := cbNative; // application crypto
oClient.TLSOptions.IOHandler := iohNativeTLS; // this connection
A component that keeps the OpenSSL handler still loads OpenSSL when it connects. With iohNativeTLS on QUIC, HTTP/3 and DTLS, no OpenSSL is used at all, whatever the switch says. An application that wants no OpenSSL anywhere sets both: the switch for its cryptography, and the handler on each component that opens a secure connection.
The Define Is Now Optional
Until now, running without OpenSSL meant the SGC_NATIVE_CRYPTO compiler define. It is no longer needed. Without it, both the OpenSSL and the native code are compiled in and the variable decides at runtime.
The define still has one use. It forces the native backend whatever sgcCryptoBackend says and removes the OpenSSL code from the application crypto units, so the executable is smaller. If you know a build will never use OpenSSL, it is still the right choice. If you do not know yet, leave it off and decide at startup.
Why It Matters
- One build. Customers who must ship without OpenSSL, because of licensing, a security audit that asks about every third party binary, or locked down machines where nobody may copy a DLL, get the same executable as everyone else.
- A fallback.
cbAutokeeps an application working when the OpenSSL libraries are missing, instead of failing on the first signature. - Mobile. On iOS and Android there is no OpenSSL to bundle for the application cryptography.
- Same code everywhere. The switch works the same on Windows, Linux, macOS, iOS and Android, with Delphi 7 to Delphi 13 and C++Builder.
Upgrading
Nothing changes until you set the variable, because cbOpenSSL is the default. To try the native backend, add the two lines above to your project file, run your tests, and compare. The full list of what follows the switch, and which setting each area needs for zero OpenSSL at runtime, is in the help topic Running without OpenSSL.
Read Next
- Delphi TLS 1.3 Without OpenSSL DLLs, the connection side
Questions, feedback or migration help? Get in touch. You will get a reply from the people who wrote the code.
