Skip to Content
新しいバージョン 12 を公開しました 🎉
ObfuscatorFIPS 準拠

FIPS 準拠

Babel Obfuscator で保護したアセンブリは、FIPS が有効なホストで動作します。このページでは、実行時の復号に依存する保護機能(コード暗号化(MSIL)、文字列暗号化、リソース暗号化、値と配列の暗号化)がそうしたホストでどのように動作するか、コンテナーで発生することがある起動時の問題、そしてその解決方法を説明します。解決方法には、Babel の自己完結型のマネージド AES で保護する難読化時の対処と、環境レベルでの対処があります。

背景

多くのお客様は、オペレーティングシステムが FIPS モードで動作するホストにデプロイしています。Linux では、これは /proc/sys/crypto/fips_enabled = 1 として示されます。このモードでは、プラットフォームの暗号化プロバイダー(Linux では OpenSSL)が、すべての暗号化操作を認定済みの FIPS モジュールを通じて処理することが求められます。

よくある問題は、コンテナーがホストの FIPS フラグを引き継いでいるのに、そのベースイメージに認定済みの OpenSSL FIPS プロバイダーが含まれていない場合に起こります。この場合、OpenSSL 3 は FIPS モードに入ろうとして FIPS プロバイダーモジュールの読み込みに失敗し、壊れた状態になります。この状態では、FIPS が通常禁止する操作だけでなく、ダイジェストと暗号の操作がすべて失敗します。

これは環境に起因する状態であり、難読化されたアセンブリや Babel Obfuscator の欠陥ではありません。Babel とは関係なく文書化されています。dotnet/dotnet-docker#5849  と dotnet/runtime#87884  を参照してください。影響を受けるのは難読化されたコードだけではなく、TLS(HttpClient、gRPC)を含め、プロセス内で OpenSSL を使用する .NET の暗号化処理すべてです。

難読化されたアセンブリでの現れ方

実行時にコンテンツを復号する機能(代表的なものはコード暗号化と文字列暗号化)でアセンブリを保護すると、Babel は小さなランタイムを挿入します。このランタイムは、プラットフォームの暗号化プロバイダーを使ってメソッド本体と文字列を復号します。FIPS が壊れたホストでは、このプロバイダーが使えません。復号は型初期化子の中で実行されるため、アセンブリはお使いのコードが 1 行も実行されないうちに起動に失敗します。

System.TypeInitializationException: The type initializer for '...' threw an exception. ---> Interop+Crypto+OpenSslCryptographicException: error:0308010C:digital envelope routines::unsupported at System.Security.Cryptography.AesImplementation.CreateTransform(...)

この起動時の失敗は、Babel のマネージド AES アルゴリズムでアセンブリを保護することで、難読化時に防げます。その場合、挿入されたランタイムはプラットフォームの暗号化プロバイダーを使わずに復号します。後述の FIPS が壊れたホストでのマネージド AES による起動を参照してください。コンテナーを管理できる場合は、それでも OpenSSL 環境の修正(これも後述します)をお勧めします。TLS など、プロセス内で OpenSSL を使用するほかの操作も解決されるためです。

FIPS が壊れたホストでのマネージド AES による起動

Babel Obfuscator は、自己完結型のマネージド AES 復号ルーチンを、保護するアセンブリに組み込めます。これにより、挿入されたランタイムはプラットフォームの暗号化プロバイダーに依存しなくなります。--use スイッチの encryption=aesmanaged 値でアセンブリを保護します。

babel MyApp.dll --msilencryption --use encryption=aesmanaged

MSBuild または .babel プロジェクトでは、次のように指定します。

<Use>encryption=aesmanaged</Use>

難読化ツールは、これまでどおりビルドホスト(正常な状態です)のプラットフォームプロバイダーで暗号化し、同じ暗号文を生成します。変わるのは、保護されたアセンブリに組み込まれる復号ルーチンだけです。これにより、アセンブリは環境を一切変更せずに FIPS が壊れたホストで起動できます。以前のリリースの Babel で保護したアセンブリにマネージド復号ルーチンを組み込むには、難読化し直す必要があります。

パフォーマンス:マネージド復号ルーチンの速度はおよそ 40 MB/s で、ハードウェアアクセラレーションが効くプラットフォームの AES は数 GB/s です。文字列、リソース、および一般的な(キャッシュされる)コード暗号化では、これは起動時に 1 回だけかかるコストで、体感できるほどではありません。例外は、cache=false を指定したメソッドのコード暗号化です。この場合、メソッド本体は呼び出しのたびに復号されます。ホットパスのメソッドでは cache=false と encryption=aesmanaged を組み合わせないようにし、メソッドキャッシュを有効(既定)のままにして、復号が 1 回で済むようにしてください。

コンテナーでの解決

コンテナー内で OpenSSL を使える状態にします。次のどちらのオプションでも、難読化ランタイムの症状に加えて、プロセス内で OpenSSL を使用するほかのすべての操作の問題も解消されます(たとえば、同じアセンブリが Babel Licensing や TLS も使用している場合)。

オプション 1:コンテナーで FIPS に自動的に入らないようにする

Ubuntu ベースの .NET イメージでは、OpenSSL は環境変数 OPENSSL_FORCE_FIPS_MODE に従います。これを 0 に設定すると、OpenSSL は、イメージに含まれていないプロバイダーで FIPS モードに入ろうとしなくなります。

Dockerfile では次のようにします。

ENV OPENSSL_FORCE_FIPS_MODE=0

docker-compose.yml では次のようにします。

environment: OPENSSL_FORCE_FIPS_MODE: 0

この方法は、コンテナー自体が FIPS 検証済みである必要がない場合に使用します。ホストは FIPS が有効なままで、このコンテナーの OpenSSL だけが、壊れた FIPS の自動有効化を回避します。

オプション 2:認定済みの FIPS プロバイダーを含むベースイメージを使用する

コンテナーの内部で FIPS 準拠が求められる場合は、検証済みの FIPS プロバイダーを含むベースイメージで実行してください。そうすれば、暗号化レイヤーは失敗せずに正しく初期化されます。

  • Azure Linux 3.0 の .NET イメージ(mcr.microsoft.com/dotnet/aspnet:8.0-azurelinux3.0 など)。Microsoft の FIPS 認定済み SymCrypt プロバイダーが含まれています
  • Red Hat UBI 9 ベースの .NET イメージ(registry.access.redhat.com/ubi9/dotnet-90 など)
  • FIPS 認定済みの OpenSSL パッケージを備えた Ubuntu Pro

環境の検証

コンテナー内で次のように簡単に確認すると、OpenSSL が正常かどうかがわかります。

# Fails on a broken-FIPS host, succeeds once fixed echo test | openssl dgst -sha1
  • error:03000086(または fips.so を読み込めないというメッセージ)で失敗する場合:OpenSSL は壊れた状態です。オプション 1 または 2 を適用してください。
  • 通常の SHA1(stdin)= ... の行が出力される場合:OpenSSL は正常で、難読化されたアセンブリは通常どおり起動します。

環境を変更できない場合

ベースイメージや環境変数を管理できず、対象環境を厳密に FIPS の制約下に置いたままにしなければならない場合は、前述のマネージド AES アルゴリズム(--use encryption=aesmanaged)でアセンブリを保護してください。挿入される復号ルーチンが、プラットフォームプロバイダーを必要としなくなります。これにより、保護されたアセンブリは、環境に手を加えなくても OpenSSL が壊れたホストで起動でき、実行時に復号するすべての機能(コード暗号化、文字列暗号化、リソース暗号化、値と配列の暗号化)を引き続き利用できます。ただし、同じプロセス内で OpenSSL を使用するほかの操作(TLS など)は、環境を修正するまで失敗し続ける点に注意してください。特定のデプロイについて案内が必要な場合は、サポート にお問い合わせください。

Last updated on