DelphiアプリケーションからOpenSSLのDLLを取り除くことは、かつてはビルド時の判断でした。コンパイラのdefineを有効にして再ビルドし、マシンにOpenSSLを置けない顧客向けに別の実行ファイルを出荷していたのです。sgcWebSockets 2026.10は、これを実行時の判断に変えます。起動時に一度だけ設定するグローバル変数一つで、アプリケーションの暗号処理をOpenSSL上で動かすか、Object Pascalで書かれたライブラリ内蔵の暗号処理上で動かすかを選べます。
接続部分、すなわちOpenSSLなしのTLSについては、OpenSSLのDLLなしのDelphi TLS 1.3で扱っています。この記事はそれ以外のすべて、つまりTLSハンドシェイクの外でアプリケーションが行う署名、ハッシュ、鍵合意、暗号化についてです。
起動時のたった一行
unit sgcBase_Helpersは、型TsgcCryptoBackendのグローバル変数sgcCryptoBackendを宣言しています。
uses
sgcBase_Helpers;
begin
sgcCryptoBackend := cbNative;
sgcCheckNativeCrypto;
Application.Initialize;
...
このスイッチはコンポーネントごとではなくグローバルなので、コンポーネントを作成する前に設定してください。sgcCheckNativeCryptoは省略可能です。ネイティブ暗号のunitがコンパイルに含まれていない場合、アプリケーションが最初の署名を試みる時点ではなく、起動時に明確なメッセージとともに例外を発生させます。
三つの値
cbOpenSSLがデフォルトです。アプリケーションの暗号処理は、これまでのバージョンとまったく同じくOpenSSL上で動作するため、変数を設定するまではアップグレードしても何も変わりません。cbNativeは、アプリケーションの暗号処理をObject Pascal実装上で動作させます。そのためにOpenSSLが読み込まれることは一切ありません。cbAutoは、ライブラリを読み込めるときはOpenSSLを、読み込めないときはネイティブコードを使用します。このチェックは一度だけ実行され、結果はキャッシュされます。
cbAutoは、両方の形で配布される製品向けです。実行ファイルの横にOpenSSLライブラリをインストールする顧客もいれば、それが許されない顧客もいますが、同じビルドがどちらにも対応でき、DLLが見つからないというサポートチケットも発生しません。
// same executable, with or without the OpenSSL libraries beside it
sgcCryptoBackend := cbAuto;
このスイッチが及ぶ範囲
このスイッチは、コンポーネントがあなたに代わって行う暗号処理をカバーします。
- ハッシュとHMACのヘルパー、
- JWTの署名と検証(HS、RS、ES)、
- OAuth2とDPoPの証明、
- AWS Signature V4とCloudFrontの署名付きURL、
- Web Push、
- エンドツーエンド暗号化(E2EE)。異なるバックエンドのピア同士が相互運用できるため、
cbNativeのクライアントが、まだOpenSSLのままのサーバーと通信できます。 - WebAuthnとパスキー、
- SAMLとXML署名、
- NTLM、
- AEAD、ML-KEM、HKDF、
- QUICのパケット保護、DTLSとWebRTCの証明書、SRTP。
これらはいずれもコード変更を必要としません。昨日OpenSSLで署名されていたJWTも、この変数の指定次第で今日はネイティブに署名されます。
接続は別設定
sgcCryptoBackendは、コンポーネントの接続方法を変えません。接続のTLSは、TCP、HTTP、WebSocketの各コンポーネントおよびMQTTなどそれらの上に構築されたすべてのコンポーネントではIOHandler = iohNativeTLSによって、QUICとHTTP/3でも同様に、WebRTCではDTLSOptionsによって、コンポーネントごとに選択されます。
sgcCryptoBackend := cbNative; // application crypto
oClient.TLSOptions.IOHandler := iohNativeTLS; // this connection
OpenSSLハンドラのままのコンポーネントは、接続時に引き続きOpenSSLを読み込みます。QUIC、HTTP/3、DTLSでiohNativeTLSを使えば、スイッチの値にかかわらずOpenSSLはまったく使われません。どこにもOpenSSLを置きたくないアプリケーションは、両方を設定します。暗号処理のためのスイッチと、セキュアな接続を開く各コンポーネントのハンドラです。
defineは今や省略可能
これまで、OpenSSLなしで動作させるにはSGC_NATIVE_CRYPTOコンパイラdefineが必要でした。もはやそれは不要です。これを指定しなければ、OpenSSLとネイティブコードの両方がコンパイルに含まれ、実行時に変数がどちらを使うか決めます。
このdefineには、今もなお一つの用途があります。sgcCryptoBackendの値にかかわらずネイティブバックエンドを強制し、アプリケーション暗号のunitからOpenSSLのコードを取り除くため、実行ファイルが小さくなります。あるビルドが決してOpenSSLを使わないとわかっているなら、これは今も正しい選択です。まだわからないのであれば、外したままにして起動時に決めてください。
重要な理由
- 一つのビルド。ライセンスの問題、すべてのサードパーティバイナリを問うセキュリティ監査、あるいは誰もDLLをコピーできないロックダウンされたマシンといった理由でOpenSSLなしでの出荷を求められる顧客も、他の誰とも同じ実行ファイルを受け取ります。
- フォールバック。
cbAutoは、OpenSSLライブラリが見つからない場合でも、最初の署名で失敗する代わりにアプリケーションを動作させ続けます。 - モバイル。iOSとAndroidでは、アプリケーションの暗号処理のために同梱すべきOpenSSLがそもそも存在しません。
- どこでも同じコード。このスイッチは、Windows、Linux、macOS、iOS、Androidで、Delphi 7からDelphi 13まで、そしてC++Builderでも同じように動作します。
アップグレード
cbOpenSSLがデフォルトなので、変数を設定するまでは何も変わりません。ネイティブバックエンドを試すには、上記の二行をプロジェクトファイルに追加し、テストを実行して比較してください。このスイッチが及ぶ範囲の全リストと、実行時にOpenSSLを完全にゼロにするために各領域で必要な設定は、ヘルプトピックRunning without OpenSSLにあります。
次に読む
質問、フィードバック、移行のお手伝いが必要ですか?お問い合わせください。コードを書いた本人たちから返信が届きます。
