Sdílet prostřednictvím


Použití funkce Always Encrypted se zprostředkovatelem dat Microsoft .NET pro SQL Server

Platí pro: .NET Framework .NET Standard

Tento článek obsahuje informace o tom, jak vyvíjet aplikace .NET pomocí funkce Always Encrypted nebo Always Encryptedse zabezpečenými enklávy a poskytovatelem dat Microsoft .NET pro SQL Server.

Funkce Always Encrypted umožňuje klientským aplikacím šifrovat citlivá data a nikdy nezoradit data nebo šifrovací klíče pro SQL Server nebo Azure SQL Database. Ovladač s povolenou funkcí Always Encrypted, jako je poskytovatel dat Microsoft .NET pro SQL Server, dosahuje tohoto zabezpečení transparentním šifrováním a dešifrováním citlivých dat v klientské aplikaci. Ovladač automaticky určí, které parametry dotazu odpovídají citlivým databázovým sloupcům (chráněné pomocí funkce Always Encrypted) a před předáním dat serveru zašifruje hodnoty těchto parametrů. Ovladač podobně transparentně dešifruje data načtená ze šifrovaných databázových sloupců ve výsledcích dotazu. Další informace naleznete v tématu Vývoj aplikací pomocí funkce Always Encrypted a Vývoj aplikací pomocí funkce Always Encrypted se zabezpečenými enklávy.

Požadavky

  • Nakonfigurujte funkci Always Encrypted v databázi. Tento proces zahrnuje zřízení klíčů Always Encrypted a nastavení šifrování pro vybrané sloupce databáze. Pokud ještě nemáte databázi s nakonfigurovanou funkcí Always Encrypted, postupujte podle pokynů v kurzu: Začínáme s funkcí Always Encrypted.
  • Pokud používáte funkci Always Encrypted se zabezpečenými enklávy, další požadavky najdete v tématu Vývoj aplikací s využitím funkce Always Encrypted se zabezpečenými enklávy .
  • Ujistěte se, že je na vývojovém počítači nainstalovaná požadovaná platforma .NET. U Microsoft.Data.SqlClient je funkce Always Encrypted podporovaná pro rozhraní .NET Framework i .NET Core. Ujistěte se, že rozhraní .NET Framework 4.6 nebo novější nebo .NET Core 2.1 nebo vyšší je nakonfigurované jako cílová verze platformy .NET ve vašem vývojovém prostředí. U Microsoft.Data.SqlClient verze 2.1.0 a vyšší je funkce Always Encrypted podporována také pro .NET Standard 2.0. Pokud chcete používat funkci Always Encrypted se zabezpečenými enklávy, vyžaduje se .NET Standard 2.1 . Pokud chcete používat enklávy VBS bez ověření identity, vyžaduje se Microsoft.Data.SqlClient verze 4.1 nebo vyšší. Pokud používáte Visual Studio, projděte si přehled cílení na architekturu.

Následující tabulka shrnuje požadované platformy .NET pro použití funkce Always Encrypted s Microsoft.Data.SqlClient.

Podpora funkce Always Encrypted Podpora funkce Always Encrypted pomocí zabezpečené enklávy Cílový rámec Verze Microsoft.Data.SqlClient Operační systém
Ano Ano .NET Framework 4.6 nebo novější 1.1.0+ Windows
Ano Ano .NET Core 2.1 nebo novější 2.1.0+1 Windows, Linux, macOS
Ano Ne .NET Standard 2.0 2.1.0+ Windows, Linux, macOS
Ano Ano .NET Standard 2.1+ 2.1.0+ Windows, Linux, macOS

Poznámka:

1 Před Microsoft.Data.SqlClient verze 2.1.0 je funkce Always Encrypted podporována pouze ve Windows.

Povolení funkce Always Encrypted pro dotazy aplikací

Nejjednodušší způsob, jak povolit šifrování parametrů a dešifrování výsledků dotazů, které cílí na šifrované sloupce, je nastavení hodnoty klíčového Column Encryption Setting slova připojovacího řetězce na povolenou.

Následující příklad používá připojovací řetězec, který umožňuje funkci Always Encrypted:

string connectionString = "Data Source=server63; Initial Catalog=Clinic; Integrated Security=true; Column Encryption Setting=enabled";
SqlConnection connection = new SqlConnection(connectionString);

Následující fragment kódu je ekvivalentní příklad použití vlastnosti SqlConnectionStringBuilder.ColumnEncryptionSetting.

SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "server63";
builder.InitialCatalog = "Clinic";
builder.IntegratedSecurity = true;
builder.ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled;
SqlConnection connection = new SqlConnection(builder.ConnectionString);
connection.Open();

Funkce Always Encrypted je také možné povolit pro jednotlivé dotazy. Podívejte se na část Řízení dopadu na výkon funkce Always Encrypted níže. Povolení funkce Always Encrypted nestačí k úspěšnému šifrování nebo dešifrování. Musíte se také ujistit, že:

  • Aplikace má oprávnění databáze VIEW ANY COLUMN MASTER KEY DEFINITION a VIEW ANY COLUMN ENCRYPTION KEY DEFINITION, která jsou nutná pro přístup k metadatům o klíčích Always Encrypted v databázi. Podrobnosti najdete v části Oprávnění k databázi v nástroji Always Encrypted (databázový stroj).
  • Aplikace má přístup k hlavnímu klíči sloupce, který chrání šifrovací klíče sloupců, které šifrují dotazované databázové sloupce.

Povolení funkce Always Encrypted se zabezpečenými enklávy

Od Microsoft.Data.SqlClient verze 1.1.0 ovladač podporuje funkci Always Encrypted se zabezpečenými enklávy.

Obecné informace o vývoji aplikací pomocí enkláv naleznete v tématu Vývoj aplikací pomocí funkce Always Encrypted se zabezpečenými enklávy.

Pokud chcete povolit výpočty enklávy pro připojení k databázi, musíte kromě povolení funkce Always Encrypted nastavit následující klíčová slova připojovacího řetězce (jak je vysvětleno v předchozí části):

  • Attestation Protocol – určuje protokol ověření identity.

    • Pokud toto klíčové slovo není zadané, jsou v připojení zakázány zabezpečené enklávy.
    • Pokud používáte SQL Server s enklávami založenými na virtualizaci (VBS) a službou Strážce hostitele (HGS), hodnota tohoto klíčového slova by měla být HGS.
    • Pokud používáte Azure SQL Database s enklávami Intel SGX a ověřování identity Microsoft Azure, hodnota tohoto klíčového slova by měla být AAS.
    • Pokud používáte Azure SQL Database nebo SQL Server s enklávami VBS a chcete se vyhnout ověření identity, měla by být hodnota tohoto klíčového slova None. Vyžaduje verzi 4.1 nebo vyšší.

    Poznámka:

    Jedinou možností, která je aktuálně podporovaná pro enklávy VBS ve službě Azure SQL Database, je žádná (bez ověření identity).

  • Enclave Attestation URL – určuje adresu URL ověření identity (koncový bod služby ověření identity). Adresu URL ověření identity pro vaše prostředí potřebujete získat od správce služby ověření identity.

Podrobný kurz najdete v tématu Kurz: Vývoj aplikace .NET pomocí funkce Always Encrypted se zabezpečenými enklávy.

Načítání a úpravy dat v šifrovaných sloupcích

Po povolení funkce Always Encrypted pro dotazy na aplikace můžete použít standardní rozhraní SQLClient API (viz Načítání a úpravy dat v ADO.NET) nebo zprostředkovatel dat Microsoft .NET pro rozhraní API SQL Serveru definovaný v oboru názvů Microsoft.Data.SqlClient k načtení nebo úpravě dat v šifrovaných databázových sloupcích. Pokud má vaše aplikace požadovaná oprávnění k databázi a má přístup k hlavnímu klíči sloupce, zprostředkovatel dat Microsoft .NET pro SQL Server zašifruje všechny parametry dotazu, které cílí na šifrované sloupce, a dešifruje data načtená z šifrovaných sloupců a vrátí hodnoty prostého textu typů .NET odpovídající datovým typům SQL Serveru nastaveným pro sloupce ve schématu databáze. Pokud funkce Always Encrypted není povolená, dotazy s parametry, které cílí na šifrované sloupce, selžou. Dotazy můžou stále načítat data ze šifrovaných sloupců, pokud dotaz nemá žádné parametry, které cílí na šifrované sloupce. Zprostředkovatel dat Microsoft .NET pro SQL Server se ale nebude pokoušet dešifrovat žádné hodnoty načtené z šifrovaných sloupců a aplikace bude přijímat binární šifrovaná data (jako pole bajtů).

Následující tabulka shrnuje chování dotazů v závislosti na tom, jestli je funkce Always Encrypted povolená, nebo ne:

Charakteristika dotazu Funkce Always Encrypted je povolená a aplikace má přístup ke klíčům a metadatům klíčů. Funkce Always Encrypted je povolená a aplikace nemá přístup ke klíčům ani metadatům klíčů. Funkce Always Encrypted je zakázaná.
Dotazy s parametry, které cílí na šifrované sloupce Hodnoty parametrů jsou transparentně šifrované. Error Error
Dotazy načítající data ze šifrovaných sloupců bez parametrů, které cílí na šifrované sloupce. Výsledky z šifrovaných sloupců se transparentně dešifrují. Aplikace přijímá hodnoty prostého textu datových typů .NET odpovídajících typům SQL Serveru nakonfigurovaným pro šifrované sloupce. Error Výsledky z šifrovaných sloupců se nešifrují. Aplikace přijímá šifrované hodnoty jako bajtová pole (bajt[]).

Následující příklady ilustrují načítání a úpravy dat v šifrovaných sloupcích. Příklady předpokládají cílovou tabulku s následujícím schématem. Sloupce SSN a BirthDate sloupce jsou šifrované.

CREATE TABLE [dbo].[Patients]([PatientId] [int] IDENTITY(1,1),
 [SSN] [char](11) COLLATE Latin1_General_BIN2
 ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC,
 ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256',
 COLUMN_ENCRYPTION_KEY = CEK1) NOT NULL,
 [FirstName] [nvarchar](50) NULL,
 [LastName] [nvarchar](50) NULL,
 [BirthDate] [date]
 ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED,
 ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256',
 COLUMN_ENCRYPTION_KEY = CEK1) NOT NULL
 PRIMARY KEY CLUSTERED ([PatientId] ASC) ON [PRIMARY])
 GO

Příklad vložení dat

Tento příklad vloží řádek do tabulky Pacienti. Všimněte si následujících podrobností:

  • V ukázkovém kódu není nic specifického pro šifrování. Zprostředkovatel dat Microsoft .NET pro SQL Server automaticky detekuje a šifruje parametry paramSSN a paramBirthdate, které cílí na šifrované sloupce. Díky tomuto chování je šifrování pro aplikaci transparentní.
  • Hodnoty vložené do databázových sloupců, včetně šifrovaných sloupců, se předávají jako objekty SqlParameter . Při odesílání hodnot do nešifrovaných sloupců je použití SqlParameter volitelné (i když se důrazně doporučuje, protože pomáhá zabránit injektáži SQL), vyžaduje se pro hodnoty, které cílí na šifrované sloupce. Pokud se hodnoty vložené do SSN sloupců nebo BirthDate sloupců předaly jako literály vložené v příkazu dotazu, dotaz by selhal, protože zprostředkovatel dat Microsoft .NET pro SQL Server by nemohl určit hodnoty v cílových šifrovaných sloupcích, takže by hodnoty nezašifroval. V důsledku toho by server odmítl je jako nekompatibilní se šifrovanými sloupci.
  • Datový typ parametru, který cílí na SSN sloupec, je nastavený na řetězec ANSI (non-Unicode), který se mapuje na datový typ char/varchar SQL Serveru. Pokud byl typ parametru nastavený na řetězec Unicode (String), který se mapuje na nchar/nvarchar, dotaz selže, protože Funkce Always Encrypted nepodporuje převody z šifrovaných hodnot nchar/nvarchar na šifrované hodnoty char/varchar. Informace o mapování datových typů najdete v tématu Mapování datových typů SYSTÉMU SQL Server .
  • Datový typ parametru vloženého BirthDate do sloupce je explicitně nastaven na cílový datový typ SQL Serveru pomocí SqlParameter.SqlDbType Vlastnost, místo aby se spoléhat na implicitní mapování typů .NET na datové typy SQL Server použité při použití SqlParameter.DbType Vlastnost. Struktura DateTime se ve výchozím nastavení mapuje na datový typ datetime SQL Serveru. Vzhledem k tomu, že datový typ BirthDate sloupce je datum a funkce Always Encrypted nepodporuje převod šifrovaných hodnot data a času na šifrované hodnoty kalendářních dat, použití výchozího mapování by vedlo k chybě.
string connectionString = "Data Source=server63; Initial Catalog=Clinic; Integrated Security=true; Column Encryption Setting=enabled";

using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
using (SqlCommand cmd = connection.CreateCommand())
{
    connection.Open();
    cmd.CommandText = @"INSERT INTO [dbo].[Patients] ([SSN], [FirstName], [LastName], [BirthDate]) VALUES (@SSN, @FirstName, @LastName, @BirthDate);";

    SqlParameter paramSSN = cmd.CreateParameter();
    paramSSN.ParameterName = @"@SSN";
    paramSSN.DbType = DbType.AnsiStringFixedLength;
    paramSSN.Direction = ParameterDirection.Input;
    paramSSN.Value = "795-73-9838";
    paramSSN.Size = 11;
    cmd.Parameters.Add(paramSSN);

    SqlParameter paramFirstName = cmd.CreateParameter();
    paramFirstName.ParameterName = @"@FirstName";
    paramFirstName.DbType = DbType.String;
    paramFirstName.Direction = ParameterDirection.Input;
    paramFirstName.Value = "Catherine";
    paramFirstName.Size = 50;
    cmd.Parameters.Add(paramFirstName);

    SqlParameter paramLastName = cmd.CreateParameter();
    paramLastName.ParameterName = @"@LastName";
    paramLastName.DbType = DbType.String;
    paramLastName.Direction = ParameterDirection.Input;
    paramLastName.Value = "Abel";
    paramLastName.Size = 50;
    cmd.Parameters.Add(paramLastName);

    SqlParameter paramBirthdate = cmd.CreateParameter();
    paramBirthdate.ParameterName = @"@BirthDate";
    paramBirthdate.SqlDbType = SqlDbType.Date;
    paramBirthdate.Direction = ParameterDirection.Input;
    paramBirthdate.Value = new DateTime(1996, 09, 10);
    cmd.Parameters.Add(paramBirthdate);

    cmd.ExecuteNonQuery();
}

Příklad načítání dat ve formátu prostého textu

Následující příklad ukazuje filtrování dat na základě šifrovaných hodnot a načtení dat prostého textu ze šifrovaných sloupců.

string connectionString = "Data Source=server63; Initial Catalog=Clinic; Integrated Security=true; Column Encryption Setting=enabled";
using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
using (SqlCommand cmd = connection.CreateCommand())
{
    connection.Open();
    cmd.CommandText = @"SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE SSN=@SSN";

    SqlParameter paramSSN = cmd.CreateParameter();
    paramSSN.ParameterName = @"@SSN";
    paramSSN.DbType = DbType.AnsiStringFixedLength;
    paramSSN.Direction = ParameterDirection.Input;
    paramSSN.Value = "795-73-9838";
    paramSSN.Size = 11;
    cmd.Parameters.Add(paramSSN);
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        if (reader.HasRows)
        {
            while (reader.Read())
            {
                Console.WriteLine(@"{0}, {1}, {2}, {3}", reader[0], reader[1], reader[2], ((DateTime)reader[3]).ToShortDateString());
            }
        }
    }
}

Poznámka:

  • Hodnota použitá v klauzuli WHERE k filtrování SSN sloupce musí být předána pomocí SqlParameter, aby zprostředkovatel dat Microsoft .NET pro SQL Server mohl transparentně šifrovat před odesláním do databáze.

  • Všechny hodnoty vytištěné programem budou ve formátu prostého textu, protože zprostředkovatel dat Microsoft .NET pro SQL Server transparentně dešifruje data načtená ze SSN sloupců a BirthDate sloupců.

  • Dotazy můžou ve sloupcích provádět porovnání rovnosti, pokud jsou šifrované pomocí deterministického šifrování.

Příklad načítání šifrovaných dat

Pokud funkce Always Encrypted není povolená, dotaz může stále načítat data ze šifrovaných sloupců, pokud dotaz nemá žádné parametry, které cílí na šifrované sloupce.

Následující příklad ukazuje, jak načíst binární šifrovaná data z šifrovaných sloupců.

string connectionString = "Data Source=server63; Initial Catalog=Clinic; Integrated Security=true";

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand cmd = connection.CreateCommand())
{
    connection.Open();
    cmd.CommandText = @"SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE [LastName]=@LastName";

    SqlParameter paramLastName = cmd.CreateParameter();
    paramLastName.ParameterName = @"@LastName";
    paramLastName.DbType = DbType.String;
    paramLastName.Direction = ParameterDirection.Input;
    paramLastName.Value = "Abel";
    paramLastName.Size = 50;
    cmd.Parameters.Add(paramLastName);
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        if (reader.HasRows)
        {
            while (reader.Read())
            {
                Console.WriteLine(@"{0}, {1}, {2}, {3}", BitConverter.ToString((byte[])reader[0]), reader[1], reader[2], BitConverter.ToString((byte[])reader[3]));
            }
        }
    }
}

Poznámka:

  • Protože funkce Always Encrypted není v připojovacím řetězci povolena, dotaz vrátí zašifrované hodnoty SSN a BirthDate jako bajtová pole (a program převede hodnoty na řetězce).

  • Dotaz, který načítá data ze šifrovaných sloupců se zakázaným funkcí Always Encrypted, může mít parametry, pokud žádný z parametrů cílí na šifrovaný sloupec. Výše uvedené dotazy filtrují podle lastName, který není v databázi šifrovaný. Pokud je dotaz filtrovaný podle SSN nebo BirthDate, dotaz selže.

Předcházení běžným problémům při dotazování šifrovaných sloupců

Tato část popisuje běžné kategorie chyb při dotazování šifrovaných sloupců z aplikací .NET a několik pokynů, jak se jim vyhnout.

Chyby převodu nepodporovaného datového typu

Funkce Always Encrypted podporuje několik převodů pro šifrované datové typy. Podrobný seznam podporovaných převodů typů naleznete v části Always Encrypted. Pokud se chcete vyhnout chybám převodu datových typů, postupujte následovně:

  • Nastavte typy parametrů, které cílí na šifrované sloupce, aby byl datový typ parametru SQL Serveru přesně stejný jako typ cílového sloupce, nebo je podporován převod datového typu SQL Serveru parametru na cílový typ sloupce. Pomocí vlastnosti SqlParameter.SqlDbType můžete vynutit požadované mapování datových typů .NET na konkrétní datové typy SQL Serveru.
  • Ověřte, zda je přesnost a měřítko parametrů, které se zaměřují na sloupce s datovými typy decimal a numeric v SQL Serveru, stejné jako přesnost a měřítko nakonfigurované pro cílový sloupec.
  • Ověřte, zda přesnost parametrů určených pro sloupce typu datetime2, datetimeoffset nebo time v SQL Serveru nepřesahuje přesnost cílového sloupce (v dotazech, které upravují hodnoty v cílovém sloupci).

Chyby způsobené předáváním prostého textu místo šifrovaných hodnot

Všechny hodnoty, které cílí na šifrovaný sloupec, musí být v aplikaci zašifrované. Při pokusu o vložení nebo úpravu nebo filtrování podle hodnoty prostého textu v zašifrovaném sloupci se zobrazí chyba podobná této:

Microsoft.Data.SqlClient.SqlException (0x80131904): Operand type clash: varchar is incompatible with varchar(8000) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK_Auto1', column_encryption_key_database_name = 'Clinic') collation_name = 'SQL_Latin1_General_CP1_CI_AS'

Pokud chcete těmto chybám zabránit, ujistěte se, že:

  • Funkce Always Encrypted je povolená pro dotazy aplikací, které cílí na šifrované sloupce (pro připojovací řetězec nebo v objektu SqlCommand pro konkrétní dotaz).
  • SqlParameter slouží k odesílání dat určených pro šifrované sloupce. Následující příklad ukazuje dotaz, který nesprávně filtruje literálem nebo konstantou v šifrovaných sloupcích (SSN) místo předání literálu uvnitř objektu SqlParameter.
using (SqlCommand cmd = connection.CreateCommand())
{
    cmd.CommandText = @"SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE SSN = '795-73-9838'";
    cmd.ExecuteNonQuery();
}

Práce s úložišti hlavních sloupcových klíčů

Pokud chcete zašifrovat hodnotu parametru nebo dešifrovat data ve výsledcích dotazu, musí poskytovatel dat Microsoft .NET pro SQL Server získat šifrovací klíč sloupce, který je nakonfigurovaný pro cílový sloupec. Šifrovací klíče sloupců jsou uloženy v šifrované podobě v metadatech databáze. Každý šifrovací klíč sloupce má odpovídající hlavní klíč sloupce, který se použil k šifrování šifrovacího klíče sloupce. Metadata databáze neukládají hlavní klíče sloupce – obsahuje pouze informace o úložišti klíčů obsahujícím určitý hlavní klíč sloupce a umístění klíče v úložišti klíčů.

Pokud chcete získat hodnotu prostého textu šifrovacího klíče sloupce, zprostředkovatel dat Microsoft .NET pro SQL Server nejprve získá metadata o šifrovacím klíči sloupce a odpovídajícím hlavním klíči sloupce. Potom pomocí informací v metadatech kontaktuje úložiště klíčů obsahující hlavní klíč sloupce a dešifruje šifrovaný šifrovací klíč sloupce. Zprostředkovatel dat Microsoft .NET pro SQL Server komunikuje s úložištěm klíčů pomocí poskytovatele úložiště hlavního klíče sloupce, což je instance třídy odvozené z třídy SqlColumnEncryptionKeyStoreProvider.

Proces získání šifrovacího klíče sloupce:

  1. Pokud je pro dotaz povolen funkce Always Encrypted, poskytovatel dat Microsoft .NET pro SQL Server transparentně volá sys.sp_describe_parameter_encryption k načtení metadat šifrování pro parametry, které cílí na šifrované sloupce, pokud má dotaz parametry. U šifrovaných dat obsažených ve výsledcích dotazu SQL Server automaticky připojí metadata šifrování. Informace o hlavním klíči sloupce zahrnují:

    • Název zprostředkovatele úložiště klíčů, který zapouzdřuje úložiště klíčů obsahující hlavní klíč sloupce.
    • Klíčová cesta, která určuje umístění hlavního klíče pro sloupec v úložišti klíčů.

    Mezi informace o šifrovacím klíči sloupce patří:

    • Hodnota klíče pro šifrování sloupce.
    • Název algoritmu, který se použil k šifrování šifrovacího klíče sloupce.
  2. Zprostředkovatel dat Microsoft .NET pro SQL Server používá název hlavního zprostředkovatele úložiště klíčů sloupce k vyhledání objektu zprostředkovatele, což je instance třídy odvozené z SqlColumnEncryptionKeyStoreProvider třídy v interní datové struktuře.

  3. K dešifrování šifrovacího klíče sloupce zprostředkovatel dat Microsoft .NET pro SQL Server volá metodu SqlColumnEncryptionKeyStoreProvider.DecryptColumnEncryptionKey(), které předá cestu k hlavnímu klíči sloupce, šifrovanou hodnotu šifrovacího klíče sloupce a název šifrovacího algoritmu použitého pro vytvoření zašifrovaného klíče šifrování sloupce.

Použití integrovaných poskytovatelů úložišť hlavních klíčů pro sloupce

Zprostředkovatel dat Microsoft .NET pro SQL Server obsahuje následující předdefinované poskytovatele hlavního úložiště klíčů sloupců, kteří jsou předem zaregistrováni s konkrétními názvy zprostředkovatelů (slouží k vyhledání poskytovatele). Tito integrovaní poskytovatelé úložiště klíčů jsou podporováni pouze ve Windows.

Class Description Název zprostředkovatele (vyhledávání) Platforma
Třída SqlColumnEncryptionCertificateStoreProvider Zprostředkovatel úložiště certifikátů systému Windows. MSSQL_CERTIFICATE_STORE Windows
SqlColumnEncryptionCngProvider – třída Zprostředkovatel úložiště klíčů, který podporuje rozhraní Microsoft Cryptography API: API nové generace (CNG). Úložiště tohoto typu je obvykle modul hardwarového zabezpečení – fyzické zařízení, které chrání a spravuje digitální klíče a poskytuje kryptografické zpracování. MSSQL_CNG_STORE Windows
SqlColumnEncryptionCspProvider – třída Zprostředkovatel úložiště klíčů, který podporuje rozhraní API kryptografie Microsoftu (CAPI). Úložiště tohoto typu je obvykle modul hardwarového zabezpečení – fyzické zařízení, které chrání a spravuje digitální klíče a poskytuje kryptografické zpracování. MSSQL_CSP_PROVIDER Windows

Abyste mohli tyto poskytovatele používat, nemusíte provádět žádné změny kódu aplikace, ale poznamenejte si následující podrobnosti:

  • Vy nebo váš DBA potřebujete zajistit, že název poskytovatele, nakonfigurovaný v metadatech hlavního klíče sloupce, je správný a že cesta hlavního klíče sloupce je v souladu s formátem cesty klíče platným pro daného poskytovatele. Doporučujeme nakonfigurovat klíče pomocí nástrojů, jako je SQL Server Management Studio, které při vydávání příkazu CREATE COLUMN MASTER KEY (Transact-SQL) automaticky vygeneruje platné názvy zprostředkovatelů a cesty klíčů. Další informace najdete v tématu Konfigurace funkce Always Encrypted pomocí aplikace SQL Server Management Studio a konfigurace funkce Always Encrypted pomocí PowerShellu.
  • Ujistěte se, že vaše aplikace má přístup k klíči v úložišti klíčů. Tento proces může zahrnovat udělení přístupu k klíči nebo úložišti klíčů v závislosti na úložišti klíčů nebo provádění dalších kroků konfigurace specifické pro úložiště klíčů. Pokud například chcete získat přístup k úložišti klíčů implementující CNG nebo CAPI (například modul hardwarového zabezpečení), musíte se ujistit, že je na počítači aplikace nainstalovaná knihovna implementující CNG nebo CAPI pro váš obchod. Podrobnosti najdete v tématu Vytvoření a uložení hlavních klíčů sloupců pro funkci Always Encrypted.

Použití poskytovatele služby Azure Key Vault

Azure Key Vault je pohodlná možnost ukládat a spravovat hlavní klíče sloupců pro Always Encrypted (zejména pokud jsou vaše aplikace hostované v Azure). Zprostředkovatel dat Microsoft .NET pro SQL Server neobsahuje integrovaného zprostředkovatele hlavního úložiště klíčů sloupců pro Azure Key Vault, ale je k dispozici jako balíček NuGet (Microsoft.Data.SqLClient.AlwaysEncrypted.AzureKeyVaultProvider), který můžete snadno integrovat s vaší aplikací. Podrobnosti najdete v tématu Always Encrypted – Ochrana citlivých dat ve službě SQL Database pomocí šifrování dat a uložení šifrovacích klíčů ve službě Azure Key Vault.

Class Description Název zprostředkovatele (vyhledávání) Platforma
SqlColumnEncryptionAzureKeyVaultProvider – třída Zprostředkovatel pro Azure Key Vault. AZURE_KEY_VAULT Windows, Linux, macOS

Možnosti podpory .NET

Version Verze Microsoft.Data.SqlClient Platformy .NET
3.0.0 3.0.0+ .NET Framework 4.6.1+, .NET Core 2.1+, .NET Standard 2.0+
2.0.0 1.1.3+
2.1.0+
.NET Framework 4.6.1 nebo novější, .NET Core 2.1+
.NET Standard 2.0+
1.2.0 1.0.19269.1+
2.1.0+
.NET Framework 4.6 nebo novější, .NET Core 2.1+
.NET Standard 2.0+
1.1.0 1.0.19269.1+ .NET Framework 4.6 nebo novější, .NET Core 2.1+
1.0.0 1.0.19269.1+ .NET Framework 4.6 nebo novější, .NET Core 2.1+

Počínaje verzí 3.0.0Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider podporuje funkce ukládání šifrovacích klíčů sloupců do mezipaměti při registraci poskytovatele pomocí rozhraní SQLConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection nebo SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand API.

Počínaje verzí 2.0.0 systém Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider podporuje nové rozhraní API Azure.Core a Azure.Identity pro provádění ověřování pomocí Azure Key Vault. Instanci TokenCredential implementace je teď možné předat SqlColumnEncryptionAzureKeyVaultProvider konstruktorům pro inicializaci objektu zprostředkovatele služby Azure Key Vault.

Poznámka:

Podporuje Microsoft.Data.SqLClient.AlwaysEncrypted.AzureKeyVaultProvidertrezory a spravované HSM ve službě Azure Key Vault.

Příklady, které demonstrují šifrování a dešifrování ve službě Azure Key Vault, najdete v tématu Práce se službou Azure Key Vault s funkcí Always Encrypted a službou Azure Key Vault se zabezpečenými enklávy.

Implementace vlastního poskytovatele úložiště hlavního klíče pro sloupce

Pokud chcete uložit hlavní klíče sloupců do úložiště klíčů, které není podporováno existujícím poskytovatelem, můžete implementovat vlastního zprostředkovatele rozšířením třídy SqlColumnEncryptionKeyStoreProvider a registrací zprostředkovatele pomocí jedné z následujících metod:

public class MyCustomKeyStoreProvider : SqlColumnEncryptionKeyStoreProvider
{
    public const string ProviderName = "MY_CUSTOM_STORE";

    public override byte[] EncryptColumnEncryptionKey(string masterKeyPath, string encryptionAlgorithm, byte[] columnEncryptionKey)
    {
        // Logic for encrypting a column encrypted key.
    }
    public override byte[] DecryptColumnEncryptionKey(string masterKeyPath, string encryptionAlgorithm, byte[] EncryptedColumnEncryptionKey)
    {
        // Logic for decrypting a column encrypted key.
    }
}  
class Program
{
    static void Main(string[] args)
    {
        Dictionary<string, SqlColumnEncryptionKeyStoreProvider> providers =
            new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>();
        providers.Add(MyCustomKeyStoreProvider.ProviderName, new MyCustomKeyStoreProvider());
        SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);
        // ...
    }
}

Priorita mezipaměti sloupcového šifrovacího klíče

Tato část se týká verze 3.0 a vyšší zprostředkovatele dat Microsoft .NET pro SQL Server.

Šifrovací klíče sloupce (CEK) dešifrované vlastními poskytovateli úložiště klíčů zaregistrovanými v připojení nebo instanci příkazu nebudou uloženy do mezipaměti poskytovatelem dat Microsoft .NET pro SQL Server. Poskytovatelé vlastních úložišť klíčů by měli implementovat mechanismus ukládání CEK do mezipaměti.

Počínaje verzí 3.0.0 , Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProviderkaždá instance Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider má vlastní implementaci mezipaměti CEK. Při registraci v instanci připojení nebo příkazu budou sady CEKs, dešifrované instancí Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider, vymazány, když tato instance přestane být v oboru platnosti.

class Program
{
    private static string connectionString;

    static void Main()
    {
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            using (SqlCommand command = connection.CreateCommand())
            {
                Dictionary<string, SqlColumnEncryptionKeyStoreProvider> customKeyStoreProviders = new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>();
                SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new DefaultAzureCredential());
                customKeyStoreProviders.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);
                command.RegisterColumnEncryptionKeyStoreProvidersOnCommand(customKeyStoreProviders);
                // Perform database operation using Azure Key Vault Provider
                // Any decrypted column encryption keys will be cached
            } // Column encryption key cache of "azureKeyVaultProvider" is cleared when "azureKeyVaultProvider" goes out of scope
        }
    }
}

Poznámka:

Mezipaměť CEK implementovaná zprostředkovateli vlastního úložiště klíčů bude zakázána ovladačem, pokud je instance zprostředkovatele úložiště klíčů zaregistrovaná v ovladači globálně pomocí metody SqlConnection.RegisterColumnEncryptionKeyStoreProviders . Jakákoli implementace ukládání do mezipaměti CEK by měla před uložením do mezipaměti odkazovat na hodnotu SqlColumnEncryptionKeyStoreProvider.ColumnEncryptionKeyCacheTtl a neukládat ji do mezipaměti, pokud je hodnota nula. Vyhnete se tak duplicitním ukládáním do mezipaměti a možným nejasnostem uživatelů při pokusu o konfiguraci ukládání klíčů do mezipaměti.

Registrace vlastního poskytovatele úložiště sloupcových hlavních klíčů

Tato část se vztahuje na verzi 3.0 a vyšší poskytovatele.

Poskytovatelé úložiště hlavních klíčů mohou být zaregistrováni u ovladače ve třech různých vrstvách. Priorita těchto tří registrací je následující:

  • Registrace jednotlivých příkazů se zkontroluje, pokud není prázdná.
  • Pokud je registrace jednotlivých příkazů prázdná, registrace jednotlivých připojení se zkontroluje, jestli není prázdná.
  • Pokud je registrace podle připojení prázdná, globální registrace se zkontroluje.

Jakmile se jakýkoli poskytovatel úložiště klíčů najde na úrovni registrace, ovladač se nebude vracet k ostatním registracím, aby hledal poskytovatele. Pokud jsou poskytovatelé zaregistrovaní, ale správný poskytovatel se nenajde na úrovni, vyvolá se výjimka obsahující pouze registrované poskytovatele v registraci, která byla zkontrolována.

Předdefinovaní zprostředkovatelé úložiště hlavních klíčů, které jsou k dispozici pro Úložiště certifikátů ve Windows, úložiště CNG a CSP, jsou předem zaregistrováni.

Tři úrovně registrace podporují různé scénáře při dotazování šifrovaných dat. Příslušnou metodu lze použít k zajištění přístupu uživatele aplikace k datům prostého textu, pokud může poskytnout požadovaný hlavní klíč sloupce, a to ověřením v úložišti klíčů obsahujícím hlavní klíč sloupce.

Aplikace, které sdílejí instanci SqlConnection mezi více uživateli, mohou chtít použít SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand. Každý uživatel musí před spuštěním dotazu zaregistrovat zprostředkovatele úložiště klíčů v instanci SqlCommand , aby získal přístup k šifrovaném sloupci. Pokud zprostředkovatel úložiště klíčů má přístup k požadovanému hlavnímu klíči sloupce v úložišti klíčů pomocí zadaných přihlašovacích údajů uživatele, dotaz bude úspěšný.

Aplikace, které vytvářejí instanci SqlConnection pro každého uživatele, mohou chtít použít SqlConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection. Zprostředkovatelé úložiště klíčů zaregistrovaní touto metodou můžou používat připojení pro všechny dotazy, které přistupují k šifrovaným datům.

Zprostředkovatelé úložiště klíčů zaregistrovaní pomocí SqlConnection.RegisterColumnEncryptionKeyStoreProviders budou při ověřování v úložišti klíčů používat identitu danou aplikací.

Následující příklad ukazuje přednost zprostředkovatelů úložiště hlavních klíčů pro vlastní sloupce zaregistrovaných v instanci připojení:

class Program
{
    static void Main()
    {
        Dictionary<string, SqlColumnEncryptionKeyStoreProvider> customKeyStoreProviders = new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>();
        MyCustomKeyStoreProvider myProvider = new MyCustomKeyStoreProvider();
        customKeyStoreProviders.Add("MY_CUSTOM_STORE", myProvider);
        // Registers the provider globally
        SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customKeyStoreProviders);

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            customKeyStoreProviders.Clear();
            SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider();
            customKeyStoreProviders.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);
            // Registers the provider on the connection
            // These providers will take precedence over globally registered providers
            connection.RegisterColumnEncryptionKeyStoreProvidersOnConnection(customKeyStoreProviders);
        }
    }
}

Následující příklad ukazuje prioritu poskytovatelů úložiště hlavních klíčů pro vlastní sloupce zaregistrovaných v instanci příkazu.

class Program
{
    static void Main()
    {
        Dictionary<string, SqlColumnEncryptionKeyStoreProvider> customKeyStoreProviders = new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>();
        MyCustomKeyStoreProvider firstProvider = new MyCustomKeyStoreProvider();
        customKeyStoreProviders.Add("FIRST_CUSTOM_STORE", firstProvider);
        // Registers the provider globally
        SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customKeyStoreProviders);

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            customKeyStoreProviders.Clear();
            MyCustomKeyStoreProvider secondProvider = new MyCustomKeyStoreProvider();
            customKeyStoreProviders.Add("SECOND_CUSTOM_STORE", secondProvider);
            // Registers the provider on the connection
            connection.RegisterColumnEncryptionKeyStoreProvidersOnConnection(customKeyStoreProviders);

            using (SqlCommand command = connection.CreateCommand())
            {
                customKeyStoreProviders.Clear();
                SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider();
                customKeyStoreProviders.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);
                // Registers the provider on the command
                // These providers will take precedence over connection-level providers and globally registered providers
                command.RegisterColumnEncryptionKeyStoreProvidersOnCommand(customKeyStoreProviders);
            }
        }
    }
}

Použití zprostředkovatelů úložiště klíčů hlavního sloupce pro zřizování programových klíčů

Když poskytovatel dat Microsoft .NET pro SQL Server přistupuje k šifrovaným sloupcům, transparentně vyhledá a zavolá zprostředkovatele hlavního úložiště klíčů pravého sloupce k dešifrování šifrovacích klíčů sloupců. Kód běžné aplikace obvykle přímo nevolá poskytovatele úložiště sloupcových hlavních klíčů. Můžete však explicitně vytvořit instanci a volat poskytovatele k programovému vytvoření a správě Always Encrypted klíčů: k vygenerování šifrovaného klíče šifrování sloupce a dešifrování klíče šifrování sloupce (například jako součást rotace hlavního klíče sloupce). Další informace najdete v tématu Přehled správy klíčů pro funkci Always Encrypted. Implementace vlastních nástrojů pro správu klíčů může být nutná pouze v případě, že používáte vlastního zprostředkovatele úložiště klíčů. Pokud používáte klíče uložené v úložištích klíčů, pro které existují předdefinované poskytovatele, nebo ve službě Azure Key Vault, můžete ke správě a zřizování klíčů použít existující nástroje, jako je SQL Server Management Studio nebo PowerShell. Následující příklad znázorňuje generování šifrovacího klíče sloupce a použití třídy SqlColumnEncryptionCertificateStoreProvider k šifrování klíče pomocí certifikátu.

using System.Security.Cryptography;
static void Main(string[] args)
{
    byte[] EncryptedColumnEncryptionKey = GetEncryptedColumnEncryptonKey();
    Console.WriteLine("0x" + BitConverter.ToString(EncryptedColumnEncryptionKey).Replace("-", ""));
    Console.ReadKey();
}

static byte[]  GetEncryptedColumnEncryptonKey()
{
    int cekLength = 32;
    String certificateStoreLocation = "CurrentUser";
    String certificateThumbprint = "698C7F8E21B2158E9AED4978ADB147CF66574180";
    // Generate the plaintext column encryption key.
    byte[] columnEncryptionKey = new byte[cekLength];
    RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
    rngCsp.GetBytes(columnEncryptionKey);

    // Encrypt the column encryption key with a certificate.
    string keyPath = String.Format(@"{0}/My/{1}", certificateStoreLocation, certificateThumbprint);
    SqlColumnEncryptionCertificateStoreProvider provider = new SqlColumnEncryptionCertificateStoreProvider();
    return provider.EncryptColumnEncryptionKey(keyPath, @"RSA_OAEP", columnEncryptionKey);
}

Řízení dopadu na výkon funkce Always Encrypted

Vzhledem k tomu, že Funkce Always Encrypted je technologie šifrování na straně klienta, většina režijních nákladů na výkon se pozoruje na straně klienta, ne v databázi. Kromě nákladů na operace šifrování a dešifrování jsou dalším zdrojem výkonové režie na straně klienta:

  • Další dotazy k databázi za účelem načtení metadat pro parametry dotazu.
  • Volání k úložišti hlavního klíče, aby získalo přístup k hlavnímu klíči sloupce.

Tato část popisuje integrované optimalizace výkonu ve zprostředkovateli dat Microsoft .NET pro SQL Server a způsob řízení dopadu výše uvedených dvou faktorů na výkon.

Řízení doby odezvy za účelem načtení metadat pro parametry dotazu

Pokud je pro připojení povolená funkce Always Encrypted, Microsoft .NET datový poskytovatel pro SQL Server bude standardně volat sys.sp_describe_parameter_encryption pro každý parametrizovaný dotaz, předávající příkaz dotazu (bez hodnot parametrů) SQL Serveru. sys.sp_describe_parameter_encryption analyzuje příkaz dotazu, aby zjistil, jestli některé parametry musí být zašifrované, a pokud ano, vrátí u každého z nich informace související s šifrováním, které umožní poskytovateli dat Microsoft .NET pro SQL Server šifrovat hodnoty parametrů. Výše uvedené chování zajišťuje vysokou úroveň transparentnosti klientské aplikace. Aplikace (a vývojář aplikace) nemusí vědět, které dotazy přistupují k šifrovaným sloupcům, pokud se hodnoty cílené na šifrované sloupce předávají zprostředkovateli dat Microsoft .NET pro SQL Server v objektech SqlParameter.

Ukládání metadat dotazů do mezipaměti

Zprostředkovatel dat Microsoft .NET pro SQL Server ukládá výsledky sys.sp_describe_parameter_encryption pro každý příkaz dotazu. Pokud se tedy stejný příkaz dotazu spustí několikrát, ovladač volá sys.sp_describe_parameter_encryption pouze jednou. Ukládání metadat šifrování do mezipaměti pro příkazy dotazů podstatně snižuje náklady na výkon při načítání metadat z databáze. Ukládání do mezipaměti je ve výchozím nastavení povolené. Ukládání metadat parametrů do mezipaměti můžete zakázat nastavením vlastnosti SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled na hodnotu false, ale nedoporučuje se to s výjimkou výjimečných případů, jako je ten popsaný níže:

Zvažte databázi, která má dvě různá schémata: s1 a s2. Každé schéma obsahuje tabulku se stejným názvem: t. Definice tabulek s1.t a s2.t jsou identické, s výjimkou vlastností souvisejících se šifrováním: Sloupec s názvem c, ve s1.t není šifrován, a je šifrován v s2.t. Databáze má dva uživatele: u1 a u2. Výchozí schéma pro u1 uživatele je s1. Výchozí schéma je u2s2. Aplikace .NET otevře dvě připojení k databázi, zosobní u1 uživatele na jednom připojení a u2 uživatele na jiném připojení. Aplikace odešle dotaz s parametrem, který cílí na c sloupec přes připojení pro uživatele u1 (dotaz nezadá schéma, takže se předpokládá výchozí schéma uživatele). V dalším kroku aplikace odešle stejný dotaz přes připojení uživatele u2 . Pokud je ukládání metadat dotazu do mezipaměti povolené, po prvním dotazu se mezipaměť naplní metadaty označujícími c sloupec, na který cílí parametr dotazu, není zašifrovaný. Protože druhý dotaz má stejný příkaz dotazu, použijí se informace uložené v mezipaměti. V důsledku toho ovladač odešle dotaz bez šifrování parametru (což je nesprávné, protože cílový sloupec , s2.t.cje zašifrován), únik hodnoty prostého textu parametru na server. Server zjistí, že nekompatibilita a ovladač vynutí aktualizaci mezipaměti, takže aplikace transparentně odešle dotaz s správně zašifrovanou hodnotou parametru. V takovém případě by se ukládání do mezipaměti mělo zakázat, aby se zabránilo úniku citlivých hodnot na server.

Nastavení funkce Always Encrypted na úrovni dotazu

Pokud chcete řídit dopad na výkon načítání metadat šifrování pro parametrizované dotazy, můžete povolit funkci Always Encrypted pro jednotlivé dotazy místo nastavení pro připojení. Tímto způsobem můžete zajistit, že se sys.sp_describe_parameter_encryption volá jenom pro dotazy, o kterých víte, že mají parametry zaměřené na šifrované sloupce. Mějte ale na paměti, že tím snížíte transparentnost šifrování: pokud změníte vlastnosti šifrování sloupců databáze, budete možná muset změnit kód aplikace tak, aby odpovídal změnám schématu.

Poznámka:

Nastavení funkce Always Encrypted na úrovni dotazu omezuje výhody výkonu ukládání metadat šifrování parametrů do mezipaměti.

Chcete-li řídit chování Always Encrypted jednotlivých dotazů, musíte použít tento konstruktor SqlCommand a SqlCommandColumnEncryptionSetting. Tady je několik užitečných pokynů:

  • Pokud většina dotazů klientské aplikace vykonávají přístup k šifrovaným sloupcům:
    • Nastavte klíčové slovo připojovacího řetězce Nastavení šifrování sloupce na Povoleno.
    • Nastavte sqlCommandColumnEncryptionSetting na Zakázáno pro jednotlivé dotazy, které nemají přístup k žádným šifrovaným sloupcům. Toto nastavení zakáže jak volání sys.sp_describe_parameter_encryption , tak pokus o dešifrování všech hodnot v sadě výsledků.
    • Nastavte SqlCommandColumnEncryptionSetting na ResultSetOnly pro jednotlivé dotazy, které neobsahují žádné parametry vyžadující šifrování, ale načítají data ze šifrovaných sloupců. Toto nastavení zakáže volání sys.sp_describe_parameter_encryption a šifrování parametrů. Dotaz bude moct dešifrovat výsledky ze sloupců šifrování.
  • Pokud většina dotazů, které klientská aplikace spustí, nemá přístup k šifrovaným sloupcům:
    • Nastavte klíčové slovo připojovacího řetězce Nastavení šifrování sloupce na Zakázáno.
    • Nastavte SqlCommandColumnEncryptionSetting na Povoleno pro jednotlivé dotazy, které mají všechny parametry, které je potřeba šifrovat. Toto nastavení umožní jak volání sys.sp_describe_parameter_encryption , tak dešifrování všech výsledků dotazu načtených ze šifrovaných sloupců.
    • Nastavte SqlCommandColumnEncryptionSetting na ResultSetOnly pro dotazy, které neobsahují žádné parametry vyžadující šifrování, ale načítají data ze šifrovaných sloupců. Toto nastavení zakáže volání sys.sp_describe_parameter_encryption a šifrování parametrů. Dotaz bude moct dešifrovat výsledky ze sloupců šifrování.

V následujícím příkladu je funkce Always Encrypted pro připojení k databázi zakázaná. Dotaz, který aplikace vydává, má parametr, který cílí na sloupec LastName, který není šifrovaný. Dotaz načte data z SSN a BirthDate sloupců, které jsou oba zašifrované. V takovém případě není vyžadováno volání sys.sp_describe_parameter_encryption pro načtení metadat šifrování. Dešifrování výsledků dotazu je však potřeba povolit, aby aplikace získala hodnoty prostého textu ze dvou šifrovaných sloupců. K zajištění toho se používá nastavení SqlCommandColumnEncryptionSettingResultSetOnly .

string connectionString = "Data Source=server63; Initial Catalog=Clinic; Integrated Security=true";
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(@"SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE [LastName]=@LastName",
connection, null, SqlCommandColumnEncryptionSetting.ResultSetOnly))
{
    connection.Open();
    SqlParameter paramLastName = cmd.CreateParameter();
    paramLastName.ParameterName = @"@LastName";
    paramLastName.DbType = DbType.String;
    paramLastName.Direction = ParameterDirection.Input;
    paramLastName.Value = "Abel";
    paramLastName.Size = 50;
    cmd.Parameters.Add(paramLastName);
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        if (reader.HasRows)
        {
            while (reader.Read())
            {
                Console.WriteLine(@"{0}, {1}, {2}, {3}", reader[0], reader[1], reader[2], ((DateTime)reader[3]).ToShortDateString());
            }
        }
    }
}

Ukládání šifrovacích klíčů sloupců do mezipaměti

Aby se snížil počet volání do úložiště hlavních klíčů sloupce pro dešifrování šifrovacích klíčů sloupců, zprostředkovatel dat Microsoft .NET pro SQL Server ukládá sloupcové šifrovací klíče v podobě prostého textu do paměti. Jakmile poskytovatel obdrží šifrovaný sloupcový šifrovací klíč z metadat databáze, ovladač se nejprve pokusí najít sloupcový šifrovací klíč ve formátu prostého textu, který odpovídá hodnotě šifrovaného klíče. Ovladač volá úložiště klíčů obsahující hlavní klíč sloupce pouze v případě, že v mezipaměti nemůže najít hodnotu šifrovaného šifrovacího klíče sloupce.

Položky mezipaměti se z bezpečnostních důvodů odstraní po konfigurovatelné době životnosti. Výchozí hodnota životnosti je 2 hodiny. Pokud máte přísnější požadavky na zabezpečení týkající se toho, jak dlouho lze šifrovací klíče sloupců ukládat do mezipaměti v prostém textu v aplikaci, můžete ho změnit pomocí vlastnosti SqlConnection.ColumnEncryptionKeyCacheTtl.

Vlastní zprostředkovatelé úložiště klíčů zaregistrovaní pomocí SqlConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection a SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand nebudou mít šifrovací klíče dešifrovaného sloupce uložené v mezipaměti zprostředkovatele dat Microsoft .NET pro SQL Server. Místo toho musí vlastní poskytovatelé úložiště klíčů implementovat vlastní mechanismus ukládání do mezipaměti. Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider Verze 3.0.0 a vyšší přináší vlastní implementaci ukládání do mezipaměti.

Aby bylo možné podporovat scénáře, ve kterých mohou různí uživatelé stejné aplikace spouštět více dotazů, můžou být vlastní zprostředkovatelé úložiště klíčů mapováni na uživatele a zaregistrováni v instanci připojení nebo příkazu specifické pro daného uživatele. Následující příklad ukazuje, jak lze instanci Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider opakovaně používat napříč různými SqlCommand objekty pro stejného uživatele. Mezipaměť šifrovacích klíčů sloupce bude přetrvávat při více dotazech, čímž se sníží počet přístupů do úložiště klíčů.

using Microsoft.Data.SqlClient;
using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider;
using System.Collections.Generic;

class Program
{
    // Maps a SqlColumnEncryptionAzureKeyVaultProvider to some object that represents a user
    static Dictionary<object, SqlColumnEncryptionAzureKeyVaultProvider> providerByUser = new();

    void ExecuteSelectQuery(object user, SqlConnection connection)
    {
        // Check if the user already has a SqlColumnEncryptionAzureKeyVaultProvider
        SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider = providerByUser[user];
        if (azureKeyVaultProvider is null)
        {
            // Create a new SqlColumnEncryptionAzureKeyVaultProvider with the user's credentials and save it for future use
            azureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider();
            providerByUser[user] = azureKeyVaultProvider;
        }

        Dictionary<string, SqlColumnEncryptionKeyStoreProvider> customProviders = new();
        customProviders.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);

        using SqlCommand command = new("SELECT * FROM Customers", connection);
        command.RegisterColumnEncryptionKeyStoreProvidersOnCommand(customProviders);
        // Perform database operations
        // Any decrypted column encryption keys will be cached by azureKeyVaultProvider
    }

    void ExecuteUpdateQuery(object user, SqlConnection connection)
    {
        // Check if the user already has a SqlColumnEncryptionAzureKeyVaultProvider
        SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider = providerByUser[user];
        if (azureKeyVaultProvider is null)
        {
            // Create a new SqlColumnEncryptionAzureKeyVaultProvider with the user's credentials and save it for future use
            azureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider();
            providerByUser[user] = azureKeyVaultProvider;
        }

        Dictionary<string, SqlColumnEncryptionKeyStoreProvider> customProviders = new();
        customProviders.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);

        using SqlCommand command = new("UPDATE Customers SET Name = 'NewName' WHERE CustomerId = 1", connection);
        command.RegisterColumnEncryptionKeyStoreProvidersOnCommand(customProviders);
        // Perform database operations
        // Any decrypted column encryption keys will be cached by azureKeyVaultProvider
    }
}

Povolení další ochrany pro ohrožený SQL Server

Ve výchozím nastavení zprostředkovatel dat Microsoft .NET pro SQL Server využívá databázový systém (SQL Server nebo Azure SQL Database) k poskytování metadat o tom, které sloupce v databázi jsou šifrované a jak. Metadata šifrování umožňují poskytovateli dat Microsoft .NET pro SQL Server šifrovat parametry dotazu a dešifrovat výsledky dotazu bez jakéhokoli vstupu z aplikace, což výrazně snižuje počet změn požadovaných v aplikaci. Pokud ale dojde ke kompromitaci procesu SQL Serveru a útočník zfalšuje metadata, která SQL Server odešle zprostředkovateli dat Microsoft .NET pro SQL Server, může být útočník schopen ukrást citlivé informace. Tato část popisuje rozhraní API, která pomáhají poskytovat dodatečnou úroveň ochrany proti tomuto typu útoku za cenu snížené transparentnosti.

Vynucení šifrování parametrů

Než poskytovatel dat Microsoft .NET pro SQL Server odešle parametrizovaný dotaz na SQL Server, požádá SQL Server (voláním sys.sp_describe_parameter_encryption), aby analyzoval příkaz dotazu a zadal informace o parametrech v dotazu, které mají být zašifrovány. Ohrožená instance SQL Serveru by mohla zavést zprostředkovatele dat Microsoft .NET pro SQL Server v omyl odesláním metadat, která naznačují, že parametr neukazuje na šifrovaný sloupec, i když je sloupec v databázi zašifrovaný. V důsledku toho zprostředkovatel dat Microsoft .NET pro SQL Server nešifroval hodnotu parametru a odeslal by ji jako prostý text do ohrožené instance SQL Serveru.

Chcete-li zabránit takovému útoku, může aplikace nastavit SqlParameter.ForceColumnEncryption Vlastnost parametru na hodnotu true. Toto nastavení způsobí, že poskytovatel dat Microsoft .NET pro SQL Server vyvolá výjimku, pokud metadata přijatá ze serveru indikují, že parametr není potřeba šifrovat.

I když použití SqlParameter.ForceColumnEncryption vlastnost pomáhá zlepšit zabezpečení, snižuje také transparentnost šifrování klientské aplikace. Pokud aktualizujete schéma databáze tak, aby změnilo sadu šifrovaných sloupců, možná budete muset provést i změny aplikace.

Následující ukázka kódu ukazuje použití vlastnosti SqlParameter.ForceColumnEncryption k zabránění zasílání čísel sociálního zabezpečení do databáze v prostém textu.

using (SqlCommand cmd = _sqlconn.CreateCommand())
{
    // Use parameterized queries to access Always Encrypted data.

    cmd.CommandText = @"SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE [SSN] = @SSN;";

    SqlParameter paramSSN = cmd.CreateParameter();
    paramSSN.ParameterName = @"@SSN";
    paramSSN.DbType = DbType.AnsiStringFixedLength;
    paramSSN.Direction = ParameterDirection.Input;
    paramSSN.Value = ssn;
    paramSSN.Size = 11;
    paramSSN.ForceColumnEncryption = true;
    cmd.Parameters.Add(paramSSN);

    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        // Do something.
    }
}

Konfigurace cest k důvěryhodným hlavním klíčům sloupce

SQL Server vrací metadata šifrování pro parametry dotazů cílených na šifrované sloupce a pro výsledky získané ze šifrovaných sloupců. Tato metadata zahrnují cestu k hlavnímu klíči sloupce, která identifikuje úložiště klíčů a umístění klíče v tomto úložišti. Pokud dojde k ohrožení zabezpečení instance SQL Serveru, může odeslat cestu ke klíči, která nasměruje poskytovatele dat Microsoft .NET pro SQL Server na místo, které je kontrolováno útočníkem. Tento proces může vést k úniku přihlašovacích údajů úložiště klíčů, pokud úložiště klíčů vyžaduje ověření aplikace.

Aby se takovým útokům zabránilo, může aplikace určit seznam důvěryhodných cest klíčů pro daný server pomocí vlastnosti SqlConnection.ColumnEncryptionTrustedMasterKeyPaths. Pokud zprostředkovatel dat Microsoft .NET pro SQL Server obdrží cestu klíče mimo seznam důvěryhodných cest klíčů, vyvolá výjimku.

I když nastavení důvěryhodných cest klíčů zlepšuje zabezpečení aplikace, budete muset změnit kód nebo/a konfiguraci aplikace při každé obměně hlavního klíče sloupce (kdykoli se změní cesta k hlavnímu klíči sloupce).

Následující příklad ukazuje, jak nakonfigurovat cesty důvěryhodného hlavního klíče sloupce:

// Configure trusted key paths to protect against fake key paths sent by a compromised SQL Server instance
// First, create a list of trusted key paths for your server
List<string> trustedKeyPathList = new List<string>();
trustedKeyPathList.Add("CurrentUser/my/425CFBB9DDDD081BB0061534CE6AB06CB5283F5Ea");

// Register the trusted key path list for your server
SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(serverName, trustedKeyPathList);

Kopírování šifrovaných dat pomocí sqlBulkCopy

Pomocí sqlBulkCopy můžete kopírovat data, která jsou už zašifrovaná a uložená v jedné tabulce, do jiné tabulky bez dešifrování dat. Postup:

  • Ujistěte se, že konfigurace šifrování cílové tabulky je stejná jako konfigurace zdrojové tabulky. Konkrétně obě tabulky musí mít zašifrované stejné sloupce a sloupce musí být šifrované pomocí stejných typů šifrování a stejných šifrovacích klíčů. Pokud je některý z cílových sloupců zašifrovaný jinak než odpovídající zdrojový sloupec, nebudete po operaci kopírování moct dešifrovat data v cílové tabulce. Data budou poškozena.
  • Nakonfigurujte připojení databáze ke zdrojové tabulce i cílové tabulce bez povolené funkce Always Encrypted.
  • AllowEncryptedValueModifications Nastavte možnost (viz SqlBulkCopyOptions).

Poznámka:

Při zadávání AllowEncryptedValueModifications buďte opatrní. Toto nastavení může vést k poškození databáze, protože zprostředkovatel dat Microsoft .NET pro SQL Server nekontroluje, jestli jsou data skutečně šifrovaná nebo jestli jsou správně zašifrovaná pomocí stejného typu šifrování, algoritmu a klíče jako cílový sloupec.

Tady je příklad, který kopíruje data z jedné tabulky do druhé. Předpokládá se, že sloupce SSN a BirthDate jsou zašifrovány.

static public void CopyTablesUsingBulk(string sourceTable, string targetTable)
{
    string sourceConnectionString = "Data Source=server63; Initial Catalog=Clinic; Integrated Security=true";
    string targetConnectionString = "Data Source=server64; Initial Catalog=Clinic; Integrated Security=true";
    using (SqlConnection connSource = new SqlConnection(sourceConnectionString))
    {
        connSource.Open();
        using (SqlCommand cmd = new SqlCommand(string.Format("SELECT [PatientID], [SSN], [FirstName], [LastName], [BirthDate] FROM {0}", sourceTable), connSource))
        {
            using (SqlDataReader reader = cmd.ExecuteReader())
            using (SqlBulkCopy copy = new SqlBulkCopy(targetConnectionString, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.AllowEncryptedValueModifications))
            {
                copy.EnableStreaming = true;
                copy.DestinationTableName = targetTable;
                copy.WriteToServer(reader);
            }
        }
    }
}

Referenční informace k rozhraní API Always Encrypted

Obor názvů:Microsoft.Data.SqlClient

Sestavení: Microsoft.Data.SqlClient.dll

Název Description
Třída SqlColumnEncryptionCertificateStoreProvider Zprostředkovatel úložiště klíčů pro Úložiště certifikátů Systému Windows.
Třída SqlColumnEncryptionCngProvider Zprostředkovatel úložiště klíčů pro rozhraní MICROSOFT Cryptography API: Next Generation (CNG).
Třída SqlColumnEncryptionCspProvider Zprostředkovatel úložiště klíčů pro poskytovatele kryptografických služeb založených na rozhraní MICROSOFT CAPI (CSP).
SqlColumnEncryptionKeyStoreProvider Class Základní třída poskytovatelů úložiště klíčů
SqlCommandColumnEncryptionSetting – výčet Nastavení pro řízení chování funkce Always Encrypted pro jednotlivé dotazy
SqlConnectionAttestationProtocol – výčet Určuje hodnotu protokolu Attestation Protocol při použití funkce Always Encrypted se zabezpečenými enklávy.
SqlConnectionColumnEncryptionSetting – výčet Nastavení pro povolení šifrování a dešifrování pro připojení k databázi
SqlConnectionStringBuilder.ColumnEncryptionSetting – vlastnost Získá a nastaví Always Encrypted v připojovacím řetězci.
SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled – vlastnost Povolí a zakáže ukládání metadat šifrovacích dotazů do mezipaměti.
SqlConnection.ColumnEncryptionKeyCacheTtl – vlastnost Získá a nastaví parametry time-to-live pro položky v mezipaměti šifrovacího klíče sloupce.
SqlConnection.ColumnEncryptionTrustedMasterKeyPaths – vlastnost Umožňuje nastavit seznam důvěryhodných cest klíčů pro databázový server. Pokud při zpracování dotazu aplikace ovladač obdrží cestu ke klíči, která není v seznamu, dotaz selže. Tato vlastnost poskytuje dodatečnou ochranu před útoky na zabezpečení, které zahrnují ohrožený SQL Server poskytující cesty k falešným klíčům, což může vést k úniku přihlašovacích údajů k úložišti klíčů.
SqlConnection.RegisterColumnEncryptionKeyStoreProviders Metoda Umožňuje registrovat poskytovatele vlastních úložišť klíčů. Je to slovník, který mapuje názvy poskytovatelů úložiště klíčů na implementace poskytovatele úložiště klíčů.
Konstruktor SqlCommand (String, SqlConnection, SqlTransaction, SqlCommandColumnEncryptionSetting) Umožňuje řídit chování funkce Always Encrypted pro jednotlivé dotazy.
SqlParameter.ForceColumnEncryption – vlastnost Vynucuje šifrování parametru. Pokud SQL Server informuje ovladač, že parametr nemusí být šifrovaný, dotaz pomocí parametru selže. Tato vlastnost poskytuje dodatečnou ochranu před útoky na zabezpečení, které zahrnují ohrožený SQL Server poskytující klientovi nesprávná šifrovací metadata, což může vést ke zpřístupnění dat.
Klíčové slovo připojovacího řetězce : Column Encryption Setting=enabled Povolí nebo zakáže funkci Always Encrypted pro připojení.

Viz také