sql >> データベース >  >> RDS >> Database

透過的なデータ暗号化と常に暗号化

    データベースに機密データを保存する必要がある場合は、データ暗号化を使用できます 。 SQL Serverは、対称キー、非対称キー、証明書、およびパスワードフレーズを使用した暗号化をサポートしています。読者の皆さんは、すでにこれらの用語に精通していると思います。この記事では、SQLServerが提供する多くの暗号化オプションのうち2つに焦点を当てます。

    • 透過的データ暗号化(TDE)
    • 常に暗号化(AE)

    透過的なデータ暗号化

    透過的データ暗号化(TDE) 使用されていないときに保存されているデータを保護します。データが使用されると、SQLServerはデータを自動的に復号化します。 TDEを使​​用して、データとログファイルのリアルタイムの暗号化と復号化を行うことができます。 データベース暗号化キー(DEK)を使用してデータを暗号化します 、これは対称鍵です。これはデータベースのブートレコードに保存されているため、データベースのリカバリプロセス中にすでに使用可能です。マスターデータベースの証明書を使用してDEKを保護します。証明書の代わりに非対称鍵を使用することもできます。ただし、非対称キーはEKMモジュールに保存する必要があります。 TDEは、AESおよびトリプルDES暗号化のみを使用します。 TDEは、バージョン2012のSQLServerに最初に実装されました。

    TDEは、ユーザーデータベースでのみ使用できます。データベース暗号化キーをエクスポートすることはできません。このキーは、SQLServerデータベースエンジンでのみ使用されます。エンドユーザーは決してそれを使用しません。データベースの所有者を変更した場合でも、DEKを再生成する必要はありません。

    TDEは、ページレベルでデータを暗号化します。さらに、トランザクションログも暗号化します。 TDEを有効にした直後に、DEKの保護に使用される証明書と証明書の保護に使用される秘密鍵をバックアップする必要があります。暗号化されたデータベースを復元するか、別のSQL Serverインスタンスに接続する必要がある場合は、証明書と秘密鍵の両方を復元する必要があります。そうしないと、データベースを開くことができません。 DEKはデータベース自体の一部であるため、エクスポートしないことに注意してください。データベースでTDEを無効にした後でも、DEKを保護するために使用される証明書を保持および維持する必要があります。これは、トランザクションログの一部がまだ暗号化されている可能性があるためです。データベースの完全バックアップを実行するまで、証明書が必要です。

    常に暗号化

    SQL Server 2016 Enterprise Editionでは、新しいレベルの暗号化、つまり常に暗号化(AE)が導入されています。 特徴。この機能により、クライアントアプリケーションでデータを暗号化するのと同じレベルのデータ保護が可能になります。実際、これはSQL Serverの機能ですが、データはクライアント側で暗号化および復号化されます。暗号化キーがSQLServerデータベースエンジンに公開されることはありません。このように、DBAは、暗号化されたデータを使用してSQL Serverインスタンスに対するsysadmin権限を持っているだけでは、暗号化キーがないと機密データを表示できません。このようにして、AEは、データを管理する管理者とデータを所有するユーザーを分離します。

    AEキー

    AlwaysEncryptedには2つのキーが必要です。まず、列マスターキー(CMK)を作成します 。次に、列暗号化キー(CEK)を作成します CMKで保護します。アプリケーションはCEKを使用してデータを暗号化します。 SQL Serverは暗号化されたデータのみを保存し、復号化することはできません。これが可能なのは、列マスターキーが実際にはSQLServerデータベースに格納されていないためです。データベースには、SQLServerはそれらのキーへのリンクのみを格納します。列マスターキーは、SQL Serverの外部で、次のいずれかの場所に保存されます。

    • 現在のユーザーのWindows証明書ストア
    • ローカルマシン用のWindows証明書ストア
    • AzureKeyVaultサービス
    • ハードウェアセキュリティモジュール(HSM) 、MicrosoftCryptoAPIまたはCryptographyAPI:Next Generation
    • をサポートします

    列の暗号化キーはデータベースに保存されます。 SQL Serverデータベース内には、列暗号化キーの値の暗号化された部分のみが、列マスターキーの場所に関する情報とともに保存されます。 CEKがプレーンテキストとしてデータベースに保存されることはありません。前述のように、CMKは実際には外部の信頼できるキーストアに保存されます。

    AEキーの使用

    アプリケーションは、SQLServerバージョン4.6以降の.NETFramework Data Provider、SQL Server6.0以降のMicrosoftJDBCドライバー、SQLServerバージョン13.1のWindowsODBCドライバーなど、AE対応のドライバーを使用してAEキーと暗号化を使用できます。より高い。アプリケーションはパラメータ化されたクエリを送信する必要があります SQLServerに。 AE対応ドライバーはSQLServerデータベースエンジンと連携して、暗号化または復号化する必要のあるパラメーターを決定します。ドライバーは、暗号化または復号化する必要のあるパラメーターごとに、暗号化アルゴリズム、対応するCMKの場所、対応するCEKの暗号化された値など、暗号化に必要なメタデータをデータベースエンジンから取得します。次に、ドライバーはCMKストアに接続し、CMKを取得し、CEKを復号化し、CEKを使用してパラメーターを暗号化または復号化します。次に、同じCEKの次の使用を高速化するために、ドライバーはCEKをキャッシュします。次の図は、プロセスをグラフで示しています。

    この図は、プロセス全体を段階的に表しています。

    1. クライアントアプリケーションはパラメータ化されたクエリを作成します
    2. クライアントアプリケーションは、パラメータ化されたクエリをAE対応ドライバに送信します
    3. AE対応ドライバーはSQLServerに接続して、暗号化または復号化が必要なパラメーター、CMKの場所、およびCEKの暗号化された値を決定します
    4. AE対応ドライバーはCMKを取得し、CEKを復号化します
    5. AE対応ドライバーはパラメーターを暗号化します
    6. ドライバーはクエリをデータベースエンジンに送信します
    7. データベースエンジンはデータを取得し、結果セットをドライバーに送信します
    8. ドライバーは必要に応じて復号化を実行し、結果セットをクライアントアプリケーションに送信します

    AE暗号化タイプ

    データベースエンジンは、暗号化された列に格納されているプレーンテキストデータを操作することはありません。ただし、暗号化の種類によっては、暗号化されたデータに対するクエリが可能です。暗号化には2つのタイプがあります:

    • 確定的暗号化 、これは常に同じ入力値に対して同じ暗号化された値を生成します。この暗号化を使用すると、暗号化された列にインデックスを付け、暗号化された列でポイントルックアップ、等式結合、およびグループ化式を使用できます。ただし、悪意のあるユーザーは、暗号化された値のパターンを分析して値を推測しようとする可能性があります。これは、列の可能な値のセットが離散的で、少数の個別の値がある場合に特に危険です。
    • ランダム化された暗号化 、予測できない方法でデータを暗号化します。

    AEデモ:オブジェクトの作成

    いくつかのデモコードを通じてAEがどのように機能するかを示す時が来ました。まず、デモデータベースを作成して使用しましょう。

    USE master;
    IF DB_ID(N'AEDemo') IS NULL
       CREATE DATABASE AEDemo;
    GO
    USE AEDemo;
    GO
    

    次に、SSMSGUIでCMKを作成します。オブジェクトエクスプローラーで、データベースフォルダーを更新してAEDemoデータベースを表示します。このデータベースフォルダを説明し、[セキュリティ]サブフォルダ、[常に暗号化されたキー]サブフォルダを展開し、[列マスターキー]サブフォルダを右クリックして、ポップアップメニューから[新しい列マスターキー]オプションを選択します。 [名前]テキストボックスにAE_ColumnMasterKeyと入力し、次の図に示すように、[キーストア]ドロップダウンリストで[Windows証明書ストア-ローカルマシン]オプションを選択していることを確認します。

    次のクエリを使用して、CMKが正常に作成されたかどうかを確認できます。

    SELECT * 
    FROM sys.column_master_keys;
    

    次に、CEKを作成します。 SSMSのオブジェクトエクスプローラーで、[列マスターキー]サブフォルダーのすぐ下にある[列暗号化キー]サブフォルダーを右クリックし、ポップアップメニューから[新しい列暗号化キー]オプションを選択します。 CEKにAE_ColumnEncryptionKeyという名前を付け、AE_ColumnMasterKeyCMKを使用して暗号化します。次のクエリで、CEKの作成が成功したかどうかを確認できます。

    SELECT * 
    FROM sys.column_encryption_keys;
    

    現在、新しいバイナリ照合、 BIN2との照合のみ 接尾辞は、AEでサポートされています。したがって、文字列に適切な照合を使用してテーブルを作成しましょう。

    CREATE TABLE dbo.Table1
    (id INT,
     SecretDeterministic NVARCHAR(10) COLLATE Latin1_General_BIN2 
      ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = AE_ColumnEncryptionKey,
       ENCRYPTION_TYPE = DETERMINISTIC,
       ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
     SecretRandomized NVARCHAR(10) COLLATE Latin1_General_BIN2
      ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = AE_ColumnEncryptionKey,
       ENCRYPTION_TYPE = RANDOMIZED,
       ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL
    );
    

    AEデモ:データの挿入

    これで、次のステートメントを使用してデータの行を挿入してみることができます。

    INSERT INTO dbo.Table1
     (id, SecretDeterministic, SecretRandomized)
    VALUES (1, N'DeterSec01', N'RandomSec1');
    

    エラー206、エラーテキストが表示されます:「Operandtype clash:nvarchar is incompatible with nvarchar(4000)encrypted with(encryption_type ='DETERMINISTIC'、encryption_algorithm_name ='AEAD_AES_256_CBC_HMAC_SHA_256'、column_encryption_key_name ='AE_ColumnEncryptionKey'、column_ 。 SQL Serverは、データを暗号化または復号化できません。クライアントアプリケーションからのデータを変更する必要があります。 SQLServerからテーブルに対して限定された一連の操作を実行できます。たとえば、AE列のあるテーブルでTRUNCATETABLEステートメントを使用できます。

    Visual C#で非常に単純なクライアントWindowsコンソールアプリケーションを作成しました。アプリケーションは実際にはキーを取得し、上記のコードで作成されたテーブルに単一の行を挿入します。これがC#コードです。

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    namespace AEDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                string connectionString = "Data Source=localhost; “ +
                  “Initial Catalog=AEDemo; Integrated Security=true; ” +
                  “Column Encryption Setting=enabled";
                SqlConnection connection = new SqlConnection(connectionString);
                connection.Open();
                if (args.Length != 3)
                {
                    Console.WriteLine("Please enter a numeric “ + 
                                      “and two string arguments.");
                    return;
                }
                int id = Int32.Parse(args[0]);
                {
                    using (SqlCommand cmd = connection.CreateCommand())
                    {
                        cmd.CommandText = @"INSERT INTO dbo.Table1 “ +
                            “(id, SecretDeterministic, SecretRandomized)" +
                            " VALUES (@id, @SecretDeterministic, @SecretRandomized);";
    
                        SqlParameter paramid= cmd.CreateParameter();
                        paramid.ParameterName = @"@id";
                        paramid.DbType = DbType.Int32;
                        paramid.Direction = ParameterDirection.Input;
                        paramid.Value = id;
                        cmd.Parameters.Add(paramid);
    
                        SqlParameter paramSecretDeterministic = cmd.CreateParameter();
                        paramSecretDeterministic.ParameterName = 
                          @"@SecretDeterministic";
                        paramSecretDeterministic.DbType = DbType.String;
                        paramSecretDeterministic.Direction = ParameterDirection.Input;
                        paramSecretDeterministic.Value = "DeterSec1";
                        paramSecretDeterministic.Size = 10;
                        cmd.Parameters.Add(paramSecretDeterministic);
    
                        SqlParameter paramSecretRandomized = cmd.CreateParameter();
                        paramSecretRandomized.ParameterName =
                          @"@SecretRandomized";
                        paramSecretRandomized.DbType = DbType.String;
                        paramSecretRandomized.Direction = ParameterDirection.Input;
                        paramSecretRandomized.Value = "RandomSec1";
                        paramSecretRandomized.Size = 10;
                        cmd.Parameters.Add(paramSecretRandomized);
    
                        cmd.ExecuteNonQuery();
                    }
                }
                connection.Close();
                Console.WriteLine("Row inserted successfully");            
            }
        }
    }
    

    Visual StudioからデバッグモードでC#コードを実行するか、アプリケーションをビルドできます。次に、コマンドプロンプトから、またはSQMCMDモードのSSMSからAEDemo.exeアプリケーションを実行できます。

    AEデモ:データの読み取り

    アプリケーションを実行した後、テーブルの作成に使用したSSMSの同じセッションからデータを読み取ってみてください。

    SELECT *
    FROM dbo.Table1;
    

    暗号化されたデータのみを表示できます。次に、SSMSで2番目のクエリウィンドウを開きます。このウィンドウを右クリックして、[接続]、[接続の変更]の順に選択します。 [接続]ダイアログで、下部にある[オプション]ボタンをクリックします。データベース名としてAEDemoと入力し、[追加の接続パラメーター]タブをクリックします。テキストボックスに「列暗号化設定=有効」と入力します(二重引用符は含みません)。次に、[接続]をクリックします。

    SSMSから行を挿入してみてください。次のクエリを使用します。

    INSERT INTO dbo.Table1
     (id, SecretDeterministic, SecretRandomized)
    VALUES (2, N'DeterSec2', N'RandomSec2');
    

    もう一度エラーが発生しました。私が使用しているこのSSMSバージョンは、アドホックインサートをパラメーター化できません。ただし、次のクエリを使用してデータを読み取ってみましょう。

    SELECT *
    FROM dbo.Table1;
    

    今回はクエリが機能し、次の結果が得られます:

    Id SecretDeterministic SecretRandomized

    — ——————– —————-

    1 DeterSec1 RandomSec1

    2 DeterSec2 RandomSec2

    AEの制限

    次のようなAlwaysEncryptedの制限についてはすでに説明しました。

    • 文字列ではBIN2照合のみがサポートされています
    • 確定的暗号化を使用して列にのみインデックスを作成し、それらの列に対して限定されたT-SQL操作のセットを使用できます
    • ランダム化された暗号化で列にインデックスを付けることはできません
    • AEはEnterpriseエディションとDeveloperエディションのみに限定されています
    • SSMSでAEを使用するのは面倒な場合があります

    AEの制限の詳細なリストについては、BooksOnlineを参照してください。ただし、AEの長所にも注意してください。接続文字列の変更を除いて、アプリケーションで変更する必要がないため、実装は簡単です。データは、クライアントメモリからネットワークを経由してデータベースストレージに至るまで、エンドツーエンドで暗号化されます。 DBAでさえ、SQLServer内でのみデータを表示することはできません。 DBAでさえ、CMKを読み取るためにSQLServerの外部のキーストレージにアクセスする必要があります。 SQL ServerのAEおよびその他の暗号化オプションは、可能性の完全なセットを提供します。適切な方法を選択するのは、あなたとあなたが解決しようとしているビジネス上の問題です。

    結論

    透過的データ暗号化は非常に簡単に使用できます。ただし、データ保護は非常に制限されています。 TDEは保存データのみを保護します。ただし、AlwaysEncryptedは本当に強力な機能です。実装するのはまだそれほど複雑ではなく、データは完全に保護されています。 DBAでさえ、暗号化キーにアクセスできなければそれを見ることができません。うまくいけば、AEの制限、特に照合の制限は、SQLServerの将来のバージョンで削除される予定です。


    1. SPARSECOLUMNを使用する理由と時期(SQL SERVER 2008)

    2. MySQLデータソースがVisualStudioに表示されない

    3. 単一のSQL接続で複数のSQLコマンドを実行するにはどうすればよいですか?

    4. SQL SERVER – SQLインジェクション攻撃を回避するために動的SQLを処理する1つのトリック?