System.Data.SqlClient から Microsoft.Data.SqlClient に移行すると「信頼されていない機関によって証明書チェーンが発行されました。」エラーが発生する - C#

System.Data.SqlClient から Microsoft.Data.SqlClient に移行すると 「信頼されていない機関によって証明書チェーンが発行されました。」エラーが発生する現象と対処法を紹介します。

現象の確認

SqlConnectionを利用してデータベースに接続するアプリケーションのライブラリを System.Data.SqlClient から Microsoft.Data.SqlClient に移行すると以下のエラーが発生する場合があります。
エラーメッセージ
SqlException (0x80131904):A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - 信頼されていない機関によって証明書チェーンが発行されました。)
英語では以下のメッセージです。
エラーメッセージ
SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The certificate chain was issued by an authority that is not trusted.)

原因

データベースサーバーとの接続を暗号化した場合、デフォルトの設定では信頼されている証明機関の証明書が必要となりました。
補足
Scaffold-DbContextコマンドでエラーが発生する場合についてはこちらの記事を参照してください。 原因は同じです。

対処法

Microsoftから解決策が紹介されています。(参照)
  • データベースサーバーに証明書をインストールする
  • Microsoft OLE DB Driver for SQL Server 18.x を使用する
  • アプリケーション接続文字列プロパティで、[データの暗号化/暗号化の使用] 設定に [はい] または [必須] の値が既に指定されている場合は、値を [いいえ] または [省略可能] に変更する。または;Encrypt=Falseを接続文字列に追加する
  • ;Trust Server Certificate=true を接続文字列に追加する
  • コードでデータの暗号化をfalseに設定する
  • コードでTrust Server Certificateをtrueに設定する

Microsoft OLE DB Driver for SQL Server 18.x を使用する

バージョン18.xのMicrosoft OLE DB Driver for SQL Server をインストールして利用する方法です。

[データの暗号化/暗号化の使用] 設定に値を [いいえ] または [省略可能] に変更する

接続文字列に、次の設定を追記します。
;Encrypt=False

文字列の書式は以下になります。
Data Source=(ホスト名またはIPアドレス);Initial Catalog=(接続データベース名);User ID=(ユーザーID);Password=(パスワード);Encrypt=False
具体例
Data Source=192.168.0.100;Initial Catalog=iPentecSandBox;User ID=penta;Password=hopstep;Encrypt=False

;Trust Server Certificate=true を接続文字列に追加する

接続文字列に、次の設定を追記します。
;Trust Server Certificate=true
文字列の書式は以下になります。
Data Source=(ホスト名またはIPアドレス);Initial Catalog=(接続データベース名);User ID=(ユーザーID);Password=(パスワード);Trust Server Certificate=true
具体例
Data Source=192.168.0.100;Initial Catalog=iPentecSandBox;User ID=penta;Password=hopstep;Trust Server Certificate=true

コードでデータの暗号化をfalseに設定する

SqlConnectionStringBuilderを利用している場合には、Encryptプロパティをfalseに設定する方法が利用できます。
    //DB Connectionの作成
    public static SqlConnection CreateMSSQLConnection(string DBHost, string DBName, string DBUser, string DBPass, int DBTimeout)
    {

      SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

      builder.DataSource = DBHost;
      builder.UserID = DBUser;
      builder.Password = DBPass;
      builder.InitialCatalog = DBName;
      builder.ConnectTimeout = DBTimeout;
      builder.Encrypt = false;               //この行を追加

      SqlConnection connection = new SqlConnection(builder.ConnectionString);
      return connection;
    }

コードでTrust Server Certificateをtrueに設定する

SqlConnectionStringBuilderを利用している場合には、TrustServerCertificateプロパティをtrueに設定する方法が利用できます。
    //DB Connectionの作成
    public static SqlConnection CreateMSSQLConnection(string DBHost, string DBName, string DBUser, string DBPass, int DBTimeout)
    {
      SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

      builder.DataSource = DBHost;
      builder.UserID = DBUser;
      builder.Password = DBPass;
      builder.InitialCatalog = DBName;
      builder.ConnectTimeout = DBTimeout;
      builder.TrustServerCertificate = true;               //この行を追加

      SqlConnection connection = new SqlConnection(builder.ConnectionString);
      return connection;
    }

どの対応方法が良いのか?

AppサーバーとDBサーバーが外部のネットワークやインターネットを経由する場合は 暗号化を有効化する方式(Encrypt=true;TrustServerCertificate = true;)が良いと考えられます。特にインターネットを経由する場合は証明書を導入する方式が良いです。
AppサーバーとDBサーバーがデータセンター内で接続されている場合でも、ゼロトラストの設計であれば、暗号化を有効化する方式が良さそうです。
アプリケーションサーバーとデータベースサーバーのネットワークがデータセンター内にあり、 データセンター内は信頼できる設計、または、AppサーバーとDBサーバーが別ネットワークで物理的に直結している場合では、 暗号化しない方式(Encrypt=false;)のほうが性能が良いです。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2023-12-03
作成日: 2023-12-03
iPentec all rights reserverd.