Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Van toepassing op: .NET Framework
.NET
Standard
In dit artikel vindt u informatie over het ontwikkelen van .NET-toepassingen met always encrypted of Always Encrypted met beveiligde enclaves en de Microsoft .NET-gegevensprovider voor SQL Server.
Met Always Encrypted kunnen clienttoepassingen gevoelige gegevens versleutelen en nooit de gegevens of de versleutelingssleutels onthullen aan SQL Server of Azure SQL Database. Een always encrypted-stuurprogramma, zoals de Microsoft .NET-gegevensprovider voor SQL Server, bereikt deze beveiliging door gevoelige gegevens in de clienttoepassing transparant te versleutelen en ontsleutelen. Het stuurprogramma bepaalt automatisch welke queryparameters overeenkomen met gevoelige databasekolommen (beveiligd met Always Encrypted) en versleutelt de waarden van deze parameters voordat de gegevens worden doorgegeven aan de server. Op dezelfde manier ontsleutelt de driver transparant gegevens die zijn opgehaald uit versleutelde databasekolommen in queryresultaten. Zie Toepassingen ontwikkelen met Always Encrypted en Toepassingen ontwikkelen met Always Encrypted met beveiligde enclaves voor meer informatie.
Vereiste voorwaarden
- Configureer Always Encrypted voor uw database. Dit proces omvat het inrichten van Always Encrypted-sleutels en het instellen van versleuteling voor geselecteerde databasekolommen. Als u nog geen database met Always Encrypted hebt geconfigureerd, volgt u de aanwijzingen in de zelfstudie: Aan de slag met Always Encrypted.
- Als u Always Encrypted gebruikt met beveiligde enclaves, raadpleegt u Toepassingen ontwikkelen met Always Encrypted met beveiligde enclaves voor meer vereisten.
- Zorg ervoor dat het vereiste .NET-platform is geïnstalleerd op uw ontwikkelcomputer. Met Microsoft.Data.SqlClient wordt de functie Always Encrypted ondersteund voor zowel .NET Framework als .NET Core. Zorg ervoor dat .NET Framework 4.6 of hoger of .NET Core 2.1 of hoger is geconfigureerd als de doelversie van het .NET-platform in uw ontwikkelomgeving. Met Microsoft.Data.SqlClient versie 2.1.0 en hoger wordt de functie Always Encrypted ook ondersteund voor .NET Standard 2.0. Als u Always Encrypted wilt gebruiken met beveiligde enclaves, is .NET Standard 2.1 vereist. Als u VBS-enclaves wilt gebruiken zonder attestation, is Microsoft.Data.SqlClient versie 4.1 of hoger vereist. Als u Visual Studio gebruikt, raadpleegt u het overzicht van framework-targeting.
De volgende tabel bevat een overzicht van de vereiste .NET-platforms voor het gebruik van Always Encrypted met Microsoft.Data.SqlClient.
| Ondersteuning voor Always Encrypted | Ondersteuning voor Always Encrypted met Secure Enclave | Doelraamwerk | Microsoft.Data.SqlClient-versie | Besturingssysteem |
|---|---|---|---|---|
| Yes | Yes | .NET Framework 4.6+ | 1.1.0+ | Windows |
| Yes | Yes | .NET Core 2.1+ | 2.1.0+1 | Windows, Linux, macOS |
| Yes | Nee. | .NET Standard 2.0 | 2.1.0+ | Windows, Linux, macOS |
| Yes | Yes | .NET Standard 2.1+ | 2.1.0+ | Windows, Linux, macOS |
Opmerking
1 Vóór Microsoft.Data.SqlClient versie 2.1.0 wordt Always Encrypted alleen ondersteund in Windows.
Always Encrypted inschakelen voor toepassingsquery's
De eenvoudigste manier om de versleuteling van parameters en de ontsleuteling van queryresultaten die gericht zijn op versleutelde kolommen in te schakelen, is door de waarde van het trefwoord voor de Column Encryption Setting verbindingsreeks in te stellen op ingeschakeld.
In het volgende voorbeeld wordt een verbindingsreeks gebruikt waarmee Always Encrypted wordt ingeschakeld:
string connectionString = "Data Source=server63; Initial Catalog=Clinic; Integrated Security=true; Column Encryption Setting=enabled";
SqlConnection connection = new SqlConnection(connectionString);
Het volgende codefragment is een equivalent voorbeeld met behulp van de eigenschap 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();
Always Encrypted kan ook worden ingeschakeld voor afzonderlijke query's. Zie de sectie De prestatie-impact van Always Encrypted beheren hieronder. Het inschakelen van Always Encrypted is niet voldoende om versleuteling of ontsleuteling te voltooien. U moet er ook voor zorgen dat:
- De toepassing heeft de databasemachtigingen ELKE KOLOMHOOFDSLEUTELDEFINITIE WEERGEVEN en ELKE KOLOMVERSLEUTELINGSSLEUTELDEFINITIE WEERGEVEN, die vereist zijn voor toegang tot de metagegevens over Always Encrypted-sleutels in de database. Zie de sectie Databasemachtigingen in Always Encrypted (Database Engine) voor meer informatie.
- De toepassing heeft toegang tot de kolomhoofdsleutel die de kolomversleutelingssleutels beveiligt, waarmee de kolommen van de opgevraagde database worden versleuteld.
Always Encrypted inschakelen met beveiligde enclaves
Vanaf Microsoft.Data.SqlClient versie 1.1.0 ondersteunt het stuurprogramma Always Encrypted met beveiligde enclaves.
Zie Toepassingen ontwikkelen met Always Encrypted met beveiligde enclaves voor algemene informatie over het ontwikkelen van toepassingen met behulp van enclaves.
Als u enclaveberekeningen voor een databaseverbinding wilt inschakelen, moet u de volgende trefwoorden voor verbindingsreeksen instellen, naast het inschakelen van Always Encrypted (zoals uitgelegd in de vorige sectie):
Attestation Protocol- geeft een attestation-protocol op.- Als dit trefwoord niet is opgegeven, worden beveiligde enclaves uitgeschakeld op de verbinding.
- Als u SQL Server gebruikt met VBS-enclaves (Virtualization-based Security) en Host Guardian Service (HGS), moet de waarde van dit trefwoord zijn
HGS. - Als u Azure SQL Database gebruikt met Intel SGX-enclaves en Microsoft Azure Attestation, moet de waarde van dit trefwoord zijn
AAS. - Als u Azure SQL Database of SQL Server gebruikt met VBS-enclaves en attestation wilt afgoden, moet de waarde van dit trefwoord zijn
None. Vereist versie 4.1 of hoger.
Opmerking
Geen (geen attestation) is de enige optie die momenteel wordt ondersteund voor VBS-enclaves in Azure SQL Database.
Enclave Attestation URL- geeft een attestation-URL (een attestation-service-eindpunt) op. U moet een attestation-URL voor uw omgeving verkrijgen van uw attestation-servicebeheerder.- Als u SQL Server en Host Guardian Service (HGS) gebruikt, raadpleegt u De HGS-attestation-URL bepalen en delen.
- Als u Azure SQL Database en Microsoft Azure Attestation gebruikt, raadpleegt u De attestation-URL voor uw attestation-beleid bepalen.
- Als u het
NoneAttestation Protocol gebruikt, is er geen attestation-URL vereist.
Zie Zelfstudie: Een .NET-toepassing ontwikkelen met Always Encrypted met beveiligde enclaves voor een stapsgewijze zelfstudie.
Gegevens ophalen en wijzigen in versleutelde kolommen
Zodra u Always Encrypted hebt ingeschakeld voor toepassingsquery's, kunt u standaard SQLClient-API's gebruiken (zie Gegevens ophalen en wijzigen in ADO.NET) of de Microsoft .NET-gegevensprovider voor SQL Server-API's , gedefinieerd in de Microsoft.Data.SqlClient-naamruimte, om gegevens op te halen of te wijzigen in versleutelde databasekolommen. Als uw toepassing beschikt over de vereiste databasemachtigingen en toegang heeft tot de hoofdsleutel van de kolom, versleutelt de Microsoft .NET-gegevensprovider voor SQL Server alle queryparameters die zijn gericht op versleutelde kolommen en ontsleutelt de gegevens die zijn opgehaald uit versleutelde kolommen en retourneert ze waarden zonder opmaak van .NET-typen die overeenkomen met de SQL Server-gegevenstypen die zijn ingesteld voor de kolommen in het databaseschema. Als Always Encrypted niet is ingeschakeld, mislukken query's met parameters die zijn gericht op versleutelde kolommen. Query's kunnen nog steeds gegevens ophalen uit versleutelde kolommen zolang de query geen parameters heeft die zijn gericht op versleutelde kolommen. De Microsoft .NET-gegevensprovider voor SQL Server probeert echter geen waarden te ontsleutelen die zijn opgehaald uit versleutelde kolommen en de toepassing ontvangt binaire versleutelde gegevens (als bytematrices).
De volgende tabel bevat een overzicht van het gedrag van query's, afhankelijk van of Always Encrypted is ingeschakeld of niet:
| Querykenmerk | Always Encrypted is ingeschakeld en de toepassing heeft toegang tot de sleutels en sleutelmetagegevens | Always Encrypted is ingeschakeld en de toepassing heeft geen toegang tot de sleutels of sleutelmetagegevens | Always Encrypted is uitgeschakeld |
|---|---|---|---|
| Query's met parameters die zijn gericht op versleutelde kolommen. | Parameterwaarden worden transparant versleuteld. | Fout | Fout |
| Query's die gegevens ophalen uit versleutelde kolommen zonder parameters die zijn gericht op versleutelde kolommen. | Resultaten van versleutelde kolommen worden transparant ontsleuteld. De applicatie ontvangt onversleutelde waarden van de .NET-gegevenstypen die bij de SQL Server-typen horen die zijn geconfigureerd voor de versleutelde kolommen. | Fout | Resultaten van versleutelde kolommen worden niet ontsleuteld. De toepassing ontvangt versleutelde waarden als bytematrices (byte[]). |
De volgende voorbeelden illustreren het ophalen en wijzigen van gegevens in versleutelde kolommen. In de voorbeelden wordt verondersteld dat de doeltabel het onderstaande schema heeft. De SSN kolommen en BirthDate kolommen worden versleuteld.
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
Voorbeeld van het invoegen van gegevens
In dit voorbeeld wordt een rij ingevoegd in de tabel Patiënten. Let op de volgende details:
- Er is niets specifieks voor versleuteling in de voorbeeldcode. De Microsoft .NET-gegevensprovider voor SQL Server detecteert en versleutelt automatisch de
paramSSNenparamBirthdateparameters die zijn gericht op versleutelde kolommen. Dit gedrag maakt versleuteling transparant voor de toepassing. - De waarden die zijn ingevoegd in databasekolommen, inclusief de versleutelde kolommen, worden doorgegeven als SqlParameter-objecten . Hoewel het gebruik van SqlParameter optioneel is bij het verzenden van waarden naar niet-versleutelde kolommen (hoewel het ten zeerste wordt aanbevolen omdat sql-injectie wordt voorkomen), is het vereist voor waarden die zijn gericht op versleutelde kolommen. Als de waarden die in de
SSNBirthDatequery-instructie zijn ingevoegd, worden doorgegeven als letterlijke waarden die zijn ingesloten in de query-instructie, mislukt de query omdat de Microsoft .NET-gegevensprovider voor SQL Server de waarden in de versleutelde doelkolommen niet zou kunnen bepalen, zodat de waarden niet zouden worden versleuteld. Als gevolg hiervan weigert de server deze als niet compatibel met de versleutelde kolommen. - Het gegevenstype van de parameter die op de
SSNkolom is gericht, is ingesteld op een ANSI-tekenreeks (niet-Unicode), die is toegewezen aan het gegevenstype char/varchar SQL Server. Als het type van de parameter is ingesteld op een Unicode-tekenreeks (String), die wordt toegewezen aan nchar/nvarchar, mislukt de query omdat Always Encrypted geen ondersteuning biedt voor conversies van versleutelde nchar/nvarchar-waarden naar versleutelde char/varchar-waarden. Zie SQL Server Gegevenstype-toewijzingen voor meer informatie over gegevenstype-toewijzingen. - Het gegevenstype van de parameter die in de
BirthDatekolom is ingevoegd, wordt expliciet ingesteld op het sql Server-doelgegevenstype met behulp van de eigenschap SqlParameter.SqlDbType, in plaats van te vertrouwen op de impliciete toewijzing van .NET-typen aan SQL Server-gegevenstypen die worden toegepast wanneer u de eigenschap SqlParameter.DbType gebruikt. De Datum/tijd-structuur wordt standaard toegewezen aan het gegevenstype datetime SQL Server. Omdat het gegevenstype van deBirthDatekolom datum is en Always Encrypted geen ondersteuning biedt voor een conversie van versleutelde datum/tijd-waarden naar versleutelde datumwaarden, resulteert het gebruik van de standaardtoewijzing in een fout.
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();
}
Voorbeeld van het ophalen van platte tekstgegevens
In het volgende voorbeeld ziet u hoe u gegevens filtert op basis van versleutelde waarden en gegevens uit versleutelde kolommen opvragen.
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());
}
}
}
}
Opmerking
De waarde die in de WHERE-component wordt gebruikt om te filteren op de
SSNkolom moet worden doorgegeven met behulp van SqlParameter, zodat de Microsoft .NET-gegevensprovider voor SQL Server deze transparant kan versleutelen voordat deze naar de database wordt verzonden.Alle waarden die door het programma worden afgedrukt, worden zonder opmaak weergegeven, omdat de Microsoft .NET-gegevensprovider voor SQL Server de gegevens transparant ontsleutelt die zijn opgehaald uit de
SSNenBirthDatekolommen.Query's kunnen gelijkheidsvergelijkingen uitvoeren voor kolommen als ze zijn versleuteld met behulp van deterministische versleuteling.
Voorbeeld van versleutelde gegevens ophalen
Als Always Encrypted niet is ingeschakeld, kan een query nog steeds gegevens ophalen uit versleutelde kolommen, zolang de query geen parameters heeft die zijn gericht op versleutelde kolommen.
In het volgende voorbeeld ziet u hoe u binaire versleutelde gegevens ophaalt uit versleutelde kolommen.
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]));
}
}
}
}
Opmerking
Omdat Always Encrypted niet is ingeschakeld in de verbindingsreeks, retourneert de query versleutelde waarden van
SSNenBirthDateals bytematrices (het programma converteert de waarden naar tekenreeksen).Een query die gegevens opvraagt uit versleutelde kolommen waarvoor Always Encrypted is uitgeschakeld, kan parameters bevatten, zolang geen van de parameters zich richt op een versleutelde kolom. De bovenstaande query filtert op LastName, die niet is versleuteld in de database. Indien de query gefilterd is op
SSNofBirthDate, dan mislukt de query.
Het voorkomen van veelvoorkomende problemen bij het uitvoeren van query's op versleutelde kolommen
In deze sectie worden veelvoorkomende foutencategorieën beschreven bij het uitvoeren van query's op versleutelde kolommen vanuit .NET-toepassingen en een paar richtlijnen voor het voorkomen van deze kolommen.
Fouten bij het converteren van niet-ondersteunde gegevenstypen
Always Encrypted ondersteunt enkele conversies voor versleutelde gegevenstypen. Zie Always Encrypted voor een gedetailleerde lijst met ondersteunde typeconversies. Ga als volgt te werk om conversiefouten van gegevenstypen te voorkomen:
- Stel de typen parameters in die zijn gericht op versleutelde kolommen, zodat het sql Server-gegevenstype van de parameter exact hetzelfde is als het type doelkolom, of een conversie van het SQL Server-gegevenstype van de parameter naar het doeltype van de kolom wordt ondersteund. U kunt de gewenste toewijzing van .NET-gegevenstypen afdwingen voor specifieke SQL Server-gegevenstypen met behulp van de eigenschap SqlParameter.SqlDbType.
- Controleer of de precisie en schaal van parameters die zijn gericht op kolommen van de decimale en numerieke SQL Server-gegevenstypen hetzelfde zijn als de precisie en schaal die zijn geconfigureerd voor de doelkolom.
- Controleer of de precisie van parameters die zijn gericht op kolommen datetime2, datetimeoffset of time SQL Server-gegevenstypen niet groter zijn dan de precisie voor de doelkolom (in query's waarmee waarden in de doelkolom worden gewijzigd).
Fouten vanwege het doorgeven van tekst zonder opmaak in plaats van versleutelde waarden
Elke waarde die is gericht op een versleutelde kolom, moet in de toepassing worden versleuteld. Een poging om een tekst zonder opmaak in te voegen/te wijzigen of te filteren op een versleutelde kolom resulteert in een fout zoals deze:
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'
Om dergelijke fouten te voorkomen, moet u het volgende controleren:
- Always Encrypted is ingeschakeld voor toepassingsquery's die gericht zijn op versleutelde kolommen (voor de verbindingsreeks of in het SqlCommand-object voor een specifieke query).
- U gebruikt SqlParameter om gegevens te verzenden die zijn gericht op versleutelde kolommen. In het volgende voorbeeld ziet u een query die onjuist filtert op een letterlijke/constante op een versleutelde kolom (SSN) in plaats van de letterlijke waarde in een SqlParameter-object door te geven.
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = @"SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE SSN = '795-73-9838'";
cmd.ExecuteNonQuery();
}
Werken met hoofdsleutelarchieven voor kolommen
Als u een parameterwaarde wilt versleutelen of gegevens wilt ontsleutelen in queryresultaten, moet de Microsoft .NET-gegevensprovider voor SQL Server een kolomversleutelingssleutel verkrijgen die is geconfigureerd voor de doelkolom. Kolomversleutelingssleutels worden opgeslagen in versleutelde vorm in de metagegevens van de database. Elke kolomversleutelingssleutel heeft een bijbehorende kolomhoofdsleutel die is gebruikt voor het versleutelen van de kolomversleutelingssleutel. De metagegevens van de database slaan de kolomhoofdsleutels niet op. Deze bevat alleen de informatie over een sleutelarchief met een bepaalde hoofdsleutel van de kolom en de locatie van de sleutel in het sleutelarchief.
Als u een niet-versleutelde waarde van een kolomversleutelingssleutel wilt verkrijgen, verkrijgt de Microsoft .NET-gegevensprovider voor SQL Server eerst de metagegevens over zowel de kolomversleutelingssleutel als de bijbehorende kolomhoofdsleutel. Vervolgens worden de gegevens in de metagegevens gebruikt om contact op te maken met het sleutelarchief met de hoofdsleutel van de kolom en om de versleutelde versleutelingssleutel voor kolommen te ontsleutelen. De Microsoft .NET-gegevensprovider voor SQL Server communiceert met een sleutelarchief met behulp van een hoofdsleutelarchiefprovider voor kolommen. Dit is een exemplaar van een klasse die is afgeleid van de klasse SqlColumnEncryptionKeyStoreProvider.
Het proces voor het verkrijgen van een kolomversleutelingssleutel:
Als Always Encrypted is ingeschakeld voor een query, roept de Microsoft .NET-gegevensprovider voor SQL Server transparant sys.sp_describe_parameter_encryption aan om versleutelingsmetagegevens op te halen voor parameters die zijn gericht op versleutelde kolommen, als de query parameters heeft. Voor versleutelde gegevens in de resultaten van een query voegt SQL Server automatisch versleutelingsmetagegevens toe. De informatie over de hoofdsleutel van de kolom bevat:
- De naam van een sleutelarchiefprovider die een sleutelarchief inkapselt met de kolomhoofdsleutel.
- Het sleutelpad dat de locatie van de kolomhoofdsleutel in het sleutelarchief aangeeft.
De informatie over de kolomversleutelingssleutel omvat:
- De versleutelde waarde van een kolomversleutelingssleutel.
- De naam van het algoritme dat is gebruikt voor het versleutelen van de kolomversleutelingssleutel.
De Microsoft .NET-gegevensprovider voor SQL Server gebruikt de naam van de provider van het hoofdsleutelarchief van de kolom om het providerobject op te zoeken. Dit is een exemplaar van een klasse die is afgeleid van de klasse SqlColumnEncryptionKeyStoreProvider, in een interne gegevensstructuur.
Om de kolomversleutelingssleutel te ontsleutelen, roept de Microsoft .NET-gegevensprovider voor SQL Server de
SqlColumnEncryptionKeyStoreProvider.DecryptColumnEncryptionKey()methode aan, waarbij het pad naar de hoofdsleutel van de kolom, de versleutelde waarde van de kolomversleutelingssleutel en de naam van het versleutelingsalgoritmen voor de versleutelde kolom worden doorgegeven.
Ingebouwde sleutelarchiefproviders voor kolommen gebruiken
De Microsoft .NET-gegevensprovider voor SQL Server wordt geleverd met de volgende ingebouwde hoofdsleutelopslagproviders voor kolommen, die vooraf zijn geregistreerd bij de specifieke providernamen (gebruikt om de provider op te zoeken). Deze ingebouwde sleutelopslagproviders worden alleen ondersteund op Windows.
| Class | Description | Providernaam (opzoeknaam) | Platform |
|---|---|---|---|
| SqlColumnEncryptionCertificateStoreProvider-klasse | Een provider voor de Windows-certificaatopslag. | MSSQL_CERTIFICATE_STORE | Windows |
| SqlColumnEncryptionCngProvider Klasse | Een provider voor een sleutelarchief dat ondersteuning biedt voor Microsoft Cryptography API: Next Generation (CNG) API. Normaal gesproken is een opslag van dit type een hardwarebeveiligingsmodule: een fysiek apparaat dat digitale sleutels beschermt en beheert en cryptoverwerking biedt. | MSSQL_CNG_STORE | Windows |
| Klasse SqlColumnEncryptionCspProvider | Een provider voor een sleutelarchief dat ondersteuning biedt voor Microsoft Cryptography API (CAPI). Normaal gesproken is een opslag van dit type een hardwarebeveiligingsmodule: een fysiek apparaat dat digitale sleutels beschermt en beheert en cryptoverwerking biedt. | MSSQL_CSP_PROVIDER | Windows |
U hoeft geen wijzigingen in de toepassingscode aan te brengen om deze providers te kunnen gebruiken, maar let op de volgende details:
- U (of uw DBA) moet ervoor zorgen dat de providernaam, die is geconfigureerd in de metagegevens van de kolomhoofdsleutel, juist is en het pad naar de hoofdsleutel van de kolom voldoet aan de indeling van het sleutelpad die geldig is voor een bepaalde provider. Het is raadzaam dat u de sleutels configureert met behulp van hulpprogramma's zoals SQL Server Management Studio, waarmee automatisch de geldige providernamen en sleutelpaden worden gegenereerd bij het uitgeven van de instructie CREATE COLUMN MASTER KEY (Transact-SQL). Voor meer informatie, zie Always Encrypted configureren met behulp van SQL Server Management Studio en Always Encrypted configureren met behulp van PowerShell.
- Zorg ervoor dat uw toepassing toegang heeft tot de sleutel in het sleutelarchief. Dit proces kan betrekking hebben op het verlenen van toegang tot uw toepassing tot de sleutel en/of het sleutelarchief, afhankelijk van het sleutelarchief of het uitvoeren van andere configuratiestappen voor het sleutelarchief. Als u bijvoorbeeld toegang wilt krijgen tot een sleutelarchief dat CNG of CAPI implementeert (zoals een hardwarebeveiligingsmodule), moet u ervoor zorgen dat een bibliotheek die CNG of CAPI voor uw winkel implementeert, is geïnstalleerd op uw toepassingscomputer. Zie Kolomhoofdsleutels maken en opslaan voor Always Encrypted-voor meer informatie.
De Azure Key Vault-provider gebruiken
Azure Key Vault is een handige optie voor het opslaan en beheren van kolomhoofdsleutels voor Always Encrypted (met name als uw toepassingen worden gehost in Azure). De Microsoft .NET-gegevensprovider voor SQL Server bevat geen ingebouwde hoofdsleutelarchiefprovider voor Azure Key Vault, maar is beschikbaar als een NuGet-pakket (Microsoft.Data.SqLClient.AlwaysEncrypted.AzureKeyVaultProvider) dat u eenvoudig kunt integreren met uw toepassing. Zie Always Encrypted - Gevoelige gegevens beveiligen in SQL Database met gegevensversleuteling en uw versleutelingssleutels opslaan in Azure Key Vault voor meer informatie.
| Class | Description | Providernaam (opzoeknaam) | Platform |
|---|---|---|---|
| SqlColumnEncryptionAzureKeyVaultProvider-klasse | Provider voor Azure Key Vault. | AZURE_KEY_VAULT | Windows, Linux, macOS |
.NET-ondersteuning
| Versie | Microsoft.Data.SqlClient-versie | .NET-platforms |
|---|---|---|
| 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+, .NET Core 2.1+ .NET Standard 2.0+ |
| 1.2.0 | 1.0.19269.1+ 2.1.0+ |
.NET Framework 4.6+, .NET Core 2.1+ .NET Standard 2.0+ |
| 1.1.0 | 1.0.19269.1+ | .NET Framework 4.6+, .NET Core 2.1+ |
| 1.0.0 | 1.0.19269.1+ | .NET Framework 4.6+, .NET Core 2.1+ |
Vanaf v3.0.0 ondersteunt de Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider cachemogelijkheden voor kolomversleutelingssleutels bij het registreren van de provider met behulp van SQLConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection of SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand-API's .
Vanaf v2.0.0 ondersteunt de Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider nieuwe Azure.Core en Azure.Identity API's om verificatie uit te voeren met Azure Key Vault. Er kan nu een exemplaar van TokenCredential implementatie worden doorgegeven aan SqlColumnEncryptionAzureKeyVaultProvider constructors om het Azure Key Vault-providerobject te initialiseren.
Opmerking
De Microsoft.Data.SqLClient.AlwaysEncrypted.AzureKeyVaultProvider ondersteunt zowel kluizen als beheerde HSM's in Azure Key Vault.
Voor voorbeelden die versleuteling/ontsleuteling met Azure Key Vault demonstreren, raadpleegt u Azure Key Vault die werkt met Always Encrypted en Azure Key Vault die werken met Always Encrypted met beveiligde enclaves.
Een aangepaste provider voor kolom-hoofdsleutelopslag implementeren
Als u kolomhoofdsleutels wilt opslaan in een sleutelarchief dat niet wordt ondersteund door een bestaande provider, kunt u een aangepaste provider implementeren door de klasse SqlColumnEncryptionKeyStoreProvider uit te breiden en de provider te registreren met een van de volgende methoden:
- SqlConnection.RegisterColumnEncryptionKeyStoreProviders
- SqlConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection (toegevoegd in versie 3.0.0)
- SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand (toegevoegd in versie 3.0.0)
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);
// ...
}
}
Prioriteit van cache voor kolomversleutelingssleutel
Deze sectie is van toepassing op versie 3.0 en hoger van de Microsoft .NET-gegevensprovider voor SQL Server.
De kolomversleutelingssleutels (CEK) die zijn ontsleuteld door aangepaste sleutelarchiefproviders die zijn geregistreerd op een verbinding of opdrachtexemplaren, worden niet in de cache opgeslagen door de Microsoft .NET-gegevensprovider voor SQL Server. Aangepaste sleutelarchiefproviders moeten hun eigen CEK-cachingmechanisme implementeren.
Vanaf v3.0.0 van de Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider heeft elk exemplaar zijn eigen CEK-caching-implementatie. Wanneer geregistreerd op een verbinding of opdrachtinstantie, worden CEKs die door een exemplaar van Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider worden ontsleuteld, gewist wanneer dat exemplaar buiten scope valt.
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
}
}
}
Opmerking
CEK-caching, geïmplementeerd door aangepaste sleutelarchiefproviders, wordt door het stuurprogramma uitgeschakeld als het exemplaar van de sleutelarchiefprovider wereldwijd in het stuurprogramma is geregistreerd met behulp van de methode SqlConnection.RegisterColumnEncryptionKeyStoreProviders. Elke CEK-caching-implementatie moet verwijzen naar de waarde van SqlColumnEncryptionKeyStoreProvider.ColumnEncryptionKeyCacheTtl voordat een CEK in de cache wordt opgeslagen en niet in de cache opgeslagen als de waarde nul is. Dit voorkomt dubbele caching en mogelijke verwarring van gebruikers wanneer ze sleutelcaching proberen te configureren.
Een aangepaste kolom-hoofdsleutel-opslagprovider registreren
Deze sectie is van toepassing op versie 3.0 en hoger van de provider.
Aangepaste hoofdsleutelopslagproviders kunnen worden geregistreerd bij het stuurprogramma op drie verschillende lagen. De prioriteit van de drie registraties is als volgt:
- De registratie per opdracht wordt gecontroleerd indien deze niet leeg is.
- Als de registratie per opdracht leeg is, wordt gecontroleerd of de registratie per verbinding niet leeg is.
- Als de registratie per verbinding leeg is, wordt de globale registratie gecontroleerd.
Zodra een sleutelopslagprovider eenmaal op registratieniveau gevonden is, valt het stuurprogramma niet terug op de andere registraties om naar een provider te zoeken. Als providers zijn geregistreerd maar de juiste provider niet op een bepaald niveau wordt gevonden, wordt er een uitzondering opgeworpen die alleen de geregistreerde providers bevat die in de gecontroleerde registratie zijn opgenomen.
De ingebouwde providers van hoofdsleutelarchieven voor kolommen die beschikbaar zijn voor het Windows Certificaatarchief, het CNG-archief en de CSP zijn al geregistreerd.
De drie registratieniveaus ondersteunen verschillende scenario's bij het opvragen van versleutelde gegevens. De juiste methode kan worden gebruikt om ervoor te zorgen dat een gebruiker van een toepassing toegang heeft tot de platte tekst gegevens als zij de vereiste kolom mastersleutel kunnen verstrekken door authenticatie uit te voeren tegen de sleutelopslag met de kolom mastersleutel.
Toepassingen die een SqlConnection-exemplaar tussen meerdere gebruikers delen, willen mogelijk SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand gebruiken. Elke gebruiker moet een sleutelarchiefprovider registreren op een SqlCommand-exemplaar voordat een query wordt uitgevoerd voor toegang tot een versleutelde kolom. Als de sleutelarchiefprovider toegang heeft tot de vereiste kolomhoofdsleutel in het sleutelarchief met behulp van de opgegeven referenties van de gebruiker, slaagt de query.
Toepassingen die een SqlConnection-exemplaar voor elke gebruiker maken, willen mogelijk SqlConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection gebruiken. Sleutelopslagproviders die bij deze methode zijn geregistreerd, kunnen door de verbinding worden gebruikt voor elke query die toegang heeft tot versleutelde gegevens.
Sleutellocatieproviders die zijn geregistreerd met SqlConnection.RegisterColumnEncryptionKeyStoreProviders, gebruiken de identiteit die door de toepassing wordt opgegeven bij het authenticeren van de sleutellocatie.
In het volgende voorbeeld ziet u de prioriteit van aangepaste providers voor kolom-hoofdsleutelopslag die zijn geregistreerd op een verbindingsexemplaar:
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);
}
}
}
In het volgende voorbeeld ziet u de voorrang van providers voor de hoofdssleutelopslag van aangepaste kolommen die zijn geregistreerd op een opdrachtinstantie.
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);
}
}
}
}
Providers van kolomhoofdsleutelarchief gebruiken voor programmatische sleutelinrichting
Wanneer de Microsoft .NET-gegevensprovider voor SQL Server toegang krijgt tot versleutelde kolommen, vindt en roept deze transparant de juiste kolom-hoofdsleutelarchiefprovider aan om kolomversleutelingssleutels te ontsleutelen. Gewoonlijk roept uw toepassingscode geen providers van kolomhoofdsleutelarchieven aan. U kunt echter een provider expliciet instantiëren en aanroepen om programmatisch Always Encrypted-sleutels te maken en te beheren: om een versleutelde sleutel voor kolomversleuteling te genereren en een kolomversleutelingssleutel te ontsleutelen (bijvoorbeeld als onderdeel van de rotatie van de hoofdsleutel van de kolom). Zie Overzicht van sleutelbeheer voor Always Encrypted voor meer informatie. Het implementeren van uw eigen hulpprogramma's voor sleutelbeheer is mogelijk alleen vereist als u een aangepaste sleutelarchiefprovider gebruikt. Wanneer u sleutels gebruikt die zijn opgeslagen in sleutelsarchieven, waarvoor ingebouwde providers bestaan en of in Azure Key Vault, kunt u bestaande hulpprogramma's, zoals SQL Server Management Studio of PowerShell, gebruiken om sleutels te beheren en in te richten. In het onderstaande voorbeeld ziet u hoe u een kolomversleutelingssleutel genereert en de klasse SqlColumnEncryptionCertificateStoreProvider gebruikt om de sleutel te versleutelen met een certificaat.
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);
}
De invloed van de prestaties van Always Encrypted beheren
Omdat Always Encrypted een versleutelingstechnologie aan de clientzijde is, wordt de meeste overhead aan de clientzijde waargenomen, niet in de database. Naast de kosten van versleutelings- en ontsleutelingsbewerkingen zijn andere bronnen van prestatieoverhead aan de clientzijde:
- Extra retouren naar de database om metagegevens voor queryparameters op te halen.
- Roept een kolomhoofdsleutelarchief aan om toegang te krijgen tot een kolomhoofdsleutel.
In deze sectie worden de ingebouwde prestatieoptimalisaties in Microsoft .NET Data Provider voor SQL Server beschreven en wordt beschreven hoe u de impact van de bovenstaande twee factoren op prestaties kunt beheren.
Rondreizen beheren om metagegevens voor queryparameters op te halen
Als Always Encrypted is ingeschakeld voor een verbinding, roept de Microsoft .NET-gegevensprovider voor SQL Server standaard sys.sp_describe_parameter_encryption aan voor elke geparameteriseerde query, waarbij de query-instructie (zonder parameterwaarden) wordt doorgegeven aan SQL Server. sys.sp_describe_parameter_encryption analyseert de query-instructie om erachter te komen of er parameters moeten worden versleuteld. Als dat het geval is, retourneert deze de versleutelingsgerelateerde informatie waarmee de Microsoft .NET-gegevensprovider voor SQL Server parameterwaarden kan versleutelen. Het bovenstaande gedrag zorgt voor een hoog transparantieniveau voor de clienttoepassing. De toepassing (en de ontwikkelaar van de toepassing) hoeven zich niet bewust te zijn van welke query's toegang hebben tot versleutelde kolommen, zolang de waarden die zijn gericht op versleutelde kolommen worden doorgegeven aan de Microsoft .NET-gegevensprovider voor SQL Server in SqlParameter-objecten.
Cacheopslag van querymetagegevens
De Microsoft .NET-gegevensprovider voor SQL Server slaat de resultaten van sys.sp_describe_parameter_encryption voor elke query-instructie in de cache op. Dus als dezelfde query-instructie meerdere keren wordt uitgevoerd, roept het stuurprogramma sys.sp_describe_parameter_encryption slechts één keer aan. Caching van versleutelingsmetagegevens voor queryinstructies vermindert de prestatiekosten van het ophalen van metagegevens uit de database aanzienlijk. Caching is standaard ingeschakeld. U kunt de cache van parametermetagegevens uitschakelen door de eigenschap SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled in te stellen op false, maar dit wordt niet aanbevolen, behalve in zeldzame gevallen, zoals hieronder wordt beschreven:
Overweeg een database met twee verschillende schema's: s1 en s2. Elk schema bevat een tabel met dezelfde naam: t. De definities van de tabellen s1.t en s2.t zijn identiek, behalve wat betreft eigenschappen die met versleuteling te maken hebben: een kolom met de naam c in s1.t is niet versleuteld, terwijl deze wel versleuteld is in s2.t. De database heeft twee gebruikers: u1 en u2. Het standaardschema voor de u1 gebruikers is s1. Het standaardschema is u2s2. Een .NET-toepassing opent twee verbindingen met de database, door de u1 gebruiker te imiteren op de ene verbinding en de u2 gebruiker op de andere verbinding. De toepassing verzendt een query met een parameter die is gericht op de c kolom via de verbinding voor de gebruiker u1 (de query geeft het schema niet op, dus wordt ervan uitgegaan dat het standaardgebruikersschema wordt gebruikt). Vervolgens verzendt de toepassing dezelfde query via de verbinding voor de u2 gebruiker. Als caching van querymetagegevens is ingeschakeld, wordt de cache na de eerste query gevuld met metagegevens die aangeven welke c kolom, die de queryparameterdoelen heeft, niet is versleuteld. Omdat de tweede query dezelfde query-instructie heeft, worden de gegevens die in de cache zijn opgeslagen, gebruikt. Als gevolg hiervan verzendt het stuurprogramma de query zonder de parameter te versleutelen (wat onjuist is, aangezien de doelkolom s2.t.c versleuteld is), waardoor de onversleutelde waarde van de parameter naar de server wordt gelekt. De server detecteert die incompatibiliteit en dwingt het stuurprogramma om de cache te vernieuwen, zodat de toepassing de query transparant opnieuw verzendt met de correct versleutelde parameterwaarde. In dat geval moet caching worden uitgeschakeld om te voorkomen dat gevoelige waarden naar de server worden gelekt.
Always Encrypted instellen op queryniveau
Als u de invloed van de prestaties van het ophalen van versleutelingsmetagegevens voor geparameteriseerde query's wilt beheren, kunt u Always Encrypted inschakelen voor afzonderlijke query's in plaats van deze in te stellen voor de verbinding. Op deze manier kunt u ervoor zorgen dat sys.sp_describe_parameter_encryption alleen wordt aangeroepen voor query's die u weet dat parameters zijn gericht op versleutelde kolommen. Houd er echter rekening mee dat u hierdoor de transparantie van versleuteling vermindert: als u versleutelingseigenschappen van uw databasekolommen wijzigt, moet u mogelijk de code van uw toepassing wijzigen om deze uit te lijnen met de schemawijzigingen.
Opmerking
Het instellen van Always Encrypted op queryniveau beperkt het prestatievoordeel van het opslaan van metagegevens voor parameterversleuteling.
Als u het always encrypted-gedrag van afzonderlijke query's wilt beheren, moet u deze constructor van SqlCommand en SqlCommandColumnEncryptionSetting gebruiken. Hier volgen enkele nuttige richtlijnen:
- Als de meeste query's die door een clienttoepassing worden uitgevoerd, toegang krijgen tot versleutelde kolommen:
- Stel het trefwoord kolomversleutelingsinstelling in op Ingeschakeld.
- Stel SqlCommandColumnEncryptionSetting in op Uitgeschakeld voor afzonderlijke query's die geen toegang hebben tot versleutelde kolommen. Met deze instelling worden zowel sys.sp_describe_parameter_encryption aanroepen als pogingen om waarden in de resultatenset te ontsleutelen uitgeschakeld.
- Stel SqlCommandColumnEncryptionSetting in op ResultSetOnly voor afzonderlijke query's waarvoor geen parameters zijn vereist voor versleuteling, maar haal gegevens op uit versleutelde kolommen. Met deze instelling wordt het aanroepen van sys.sp_describe_parameter_encryption en parameterversleuteling uitgeschakeld. De query kan de resultaten van versleutelingskolommen ontsleutelen.
- Als de meeste query's door een clienttoepassing worden uitgevoerd, hebben ze geen toegang tot versleutelde kolommen:
- Stel het trefwoord kolomversleutelingsinstelling in op Uitgeschakeld.
- Stel SqlCommandColumnEncryptionSetting in opIngeschakeld voor afzonderlijke query's met parameters die moeten worden versleuteld. Met deze instelling kunnen zowel sys.sp_describe_parameter_encryption worden aangeroepen als de ontsleuteling van queryresultaten die zijn opgehaald uit versleutelde kolommen.
- Stel SqlCommandColumnEncryptionSetting in op ResultSetOnly voor query's die geen parameters hebben waarvoor versleuteling is vereist, maar haal gegevens op uit versleutelde kolommen. Met deze instelling wordt het aanroepen van sys.sp_describe_parameter_encryption en parameterversleuteling uitgeschakeld. De query kan de resultaten van versleutelingskolommen ontsleutelen.
In het onderstaande voorbeeld is Always Encrypted uitgeschakeld voor de databaseverbinding. De query die door de applicatie wordt verzonden heeft een parameter die gericht is op de LastName-kolom die niet is versleuteld. De query haalt gegevens op uit de SSN en BirthDate kolommen die beide zijn versleuteld. In dat geval is het aanroepen van sys.sp_describe_parameter_encryption voor het ophalen van versleutelingsmetagegevens niet vereist. De ontsleuteling van de queryresultaten moet echter worden ingeschakeld, zodat de toepassing waarden voor tekst zonder opmaak kan ontvangen van de twee versleutelde kolommen. De instelling SqlCommandColumnEncryptionSettingResultSetOnly wordt gebruikt om ervoor te zorgen.
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());
}
}
}
}
Caching van kolomversleutelingssleutels
Om het aantal aanroepen naar een kolomhoofdsleutelarchief te verminderen om kolomversleutelingssleutels te ontsleutelen, slaat de Microsoft .NET-gegevensprovider voor SQL Server de versleutelingssleutels voor kolommen in het geheugen op in de cache. Nadat de provider de waarde van de versleutelde kolom-encryptiesleutel van de databasemetagegevens heeft ontvangen, probeert de driver eerst de onversleutelde kolom-encryptiesleutel te vinden die overeenkomt met de versleutelde sleutelwaarde. Het stuurprogramma roept het sleutelarchief met de kolomhoofdsleutel alleen aan als de versleutelde waarde voor kolomversleutelingssleutel niet in de cache kan worden gevonden.
De cachevermeldingen worden om veiligheidsredenen verwijderd na een configureerbaar time-to-live-interval. De standaardwaarde voor time-to-live is 2 uur. Als u strengere beveiligingsvereisten hebt over hoelang kolomversleutels in platte tekst in de cache kunnen worden opgeslagen in de toepassing, kunt u dit wijzigen met behulp van de eigenschap SqlConnection.ColumnEncryptionKeyCacheTtl.
Aangepaste sleutelopslagproviders die zijn geregistreerd met SqlConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection en SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand zullen hun ontsleutelde kolomversleutelingssleutels niet in de cache van de Microsoft .NET-gegevensprovider voor SQL Server hebben. In plaats daarvan moeten aangepaste sleutelarchiefproviders hun eigen cachingmechanisme implementeren.
Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
v3.0.0 en hoger wordt geleverd met een eigen caching-implementatie.
Ter ondersteuning van scenario's waarbij verschillende gebruikers van dezelfde toepassing meerdere query's kunnen uitvoeren, kunnen aangepaste sleutelarchiefproviders worden toegewezen aan een gebruiker en geregistreerd op een verbindings- of opdrachtexemplaren die specifiek zijn voor die gebruiker. In het volgende voorbeeld ziet u hoe een exemplaar van Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider kan worden hergebruikt bij verschillende SqlCommand objecten voor dezelfde gebruiker. De cache voor kolomversleutelingssleutels blijft behouden voor meerdere query's, waardoor het aantal retouren naar het sleutelarchief wordt verminderd:
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
}
}
Extra beveiliging inschakelen voor een geïnfecteerde SQL Server
De Microsoft .NET-gegevensprovider voor SQL Server is standaard afhankelijk van het databasesysteem (SQL Server of Azure SQL Database) om metagegevens te verstrekken over welke kolommen in de database worden versleuteld en hoe. Met de versleutelingsmetagegevens kan de Microsoft .NET-gegevensprovider voor SQL Server queryparameters versleutelen en queryresultaten ontsleutelen zonder invoer van de toepassing, waardoor het aantal wijzigingen dat nodig is in de toepassing aanzienlijk wordt verminderd. Als het SQL Server-proces echter wordt aangetast en een aanvaller knoeit met de metagegevens die SQL Server naar de Microsoft .NET-gegevensprovider voor SQL Server verzendt, kan de aanvaller mogelijk gevoelige informatie stelen. In deze sectie worden API's beschreven die u helpen een extra beveiligingsniveau te bieden tegen dit type aanval, tegen de prijs van verminderde transparantie.
Parameterversleuteling afdwingen
Voordat de Microsoft .NET-gegevensprovider voor SQL Server een geparameteriseerde query naar SQL Server verzendt, wordt SQL Server gevraagd (door sys.sp_describe_parameter_encryption aan te roepen) om de query-instructie te analyseren en informatie op te geven over welke parameters in de query moeten worden versleuteld. Een gecompromitteerd SQL Server-exemplaar kan de Microsoft .NET-gegevensprovider voor SQL Server misleiden door metagegevens te verzenden die aangeven dat de parameter geen versleutelde kolom target, ook al is de kolom in de database versleuteld. Als gevolg hiervan zou de Microsoft .NET-gegevensprovider voor SQL Server de parameterwaarde niet versleutelen en zou deze als tekst zonder opmaak naar het gecompromitteerde SQL Server-exemplaar worden verzonden.
Om dergelijke aanvallen te voorkomen, kan een toepassing de eigenschap SqlParameter.ForceColumnEncryption voor de parameter instellen op true. Deze instelling zorgt ervoor dat de Microsoft .NET-gegevensprovider voor SQL Server een uitzondering genereert als de metagegevens die zijn ontvangen van de server aangeeft dat de parameter niet hoeft te worden versleuteld.
Hoewel het gebruik van de eigenschap SqlParameter.ForceColumnEncryption helpt de beveiliging te verbeteren, vermindert het ook de transparantie van versleuteling voor de clienttoepassing. Als u het databaseschema bijwerkt om de set versleutelde kolommen te wijzigen, moet u mogelijk ook toepassingswijzigingen aanbrengen.
Het volgende codevoorbeeld illustreert het gebruik van de eigenschap SqlParameter.ForceColumnEncryption om te voorkomen dat burgerservicenummers in tekst zonder opmaak naar de database worden verzonden.
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.
}
}
Basissleutelpaden voor vertrouwde kolommen configureren
De encryptiemetadata die SQL Server retourneert voor queryparameters gericht op versleutelde kolommen en voor de resultaten die worden opgehaald uit versleutelde kolommen, omvat het pad van de kolomhoofdsleutel die de sleutelopslag en de locatie van de sleutel in de sleutelopslag identificeert. Als het SQL Server-exemplaar is aangetast, kan het sleutelpad worden verzonden dat de Microsoft .NET-gegevensprovider voor SQL Server omstuurt naar de locatie die wordt beheerd door een aanvaller. Dit proces kan leiden tot het lekken van referenties voor het sleutelarchief als voor het sleutelarchief de toepassing zich moet verifiëren.
Om dergelijke aanvallen te voorkomen, kan de toepassing de lijst met vertrouwde sleutelpaden voor een bepaalde server opgeven met behulp van de eigenschap SqlConnection.ColumnEncryptionTrustedMasterKeyPaths. Als de Microsoft .NET-gegevensprovider voor SQL Server een sleutelpad buiten de lijst met vertrouwde sleutelpaden ontvangt, wordt er een uitzondering gegenereerd.
Hoewel het instellen van vertrouwde sleutelpaden de beveiliging van uw toepassing verbetert, moet u de code of/en de configuratie van de toepassing wijzigen wanneer u de hoofdsleutel van de kolom roteert (wanneer het pad van de kolomhoofdsleutel verandert).
In het volgende voorbeeld ziet u hoe u hoofdsleutelpaden voor vertrouwde kolommen configureert:
// 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);
Versleutelde gegevens kopiëren met SqlBulkCopy
Met SqlBulkCopy kunt u gegevens, die al zijn versleuteld en opgeslagen in de ene tabel, naar een andere tabel kopiëren zonder de gegevens te ontsleutelen. Ga als volgende te werk:
- Zorg ervoor dat de versleutelingsconfiguratie van de doeltabel identiek is aan de configuratie van de brontabel. Beide tabellen moeten met name dezelfde kolommen hebben die zijn versleuteld en de kolommen moeten worden versleuteld met dezelfde versleutelingstypen en dezelfde versleutelingssleutels. Als een van de doelkolommen anders is versleuteld dan de bijbehorende bronkolom, kunt u de gegevens in de doeltabel niet ontsleutelen na de kopieerbewerking. De gegevens zijn beschadigd.
- Configureer zowel databaseverbindingen met de brontabel als de doeltabel zonder Always Encrypted ingeschakeld.
- Stel de
AllowEncryptedValueModificationsoptie in (zie SqlBulkCopyOptions).
Opmerking
Wees voorzichtig bij het opgeven van AllowEncryptedValueModifications. Deze instelling kan leiden tot beschadigde database omdat de Microsoft .NET-gegevensprovider voor SQL Server niet controleert of de gegevens inderdaad zijn versleuteld of als deze correct zijn versleuteld met hetzelfde versleutelingstype, algoritme en sleutel als de doelkolom.
Hier volgt een voorbeeld waarmee gegevens uit de ene tabel naar de andere worden gekopieerd. De SSN en BirthDate kolommen worden ervan uitgegaan dat ze worden versleuteld.
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);
}
}
}
}
Always Encrypted-API-verwijzing
Naamruimte:Microsoft.Data.SqlClient
Assembly: Microsoft.Data.SqlClient.dll
| Naam | Description |
|---|---|
| SqlColumnEncryptionCertificateStoreProvider-klasse | Een sleutelopslagprovider voor het Windows-certificaatarchief. |
| SqlColumnEncryptionCngProvider Klasse | Een sleutelopslagprovider voor de Microsoft Cryptography API: Next Generation (CNG). |
| Klasse SqlColumnEncryptionCspProvider | Een certificaatopslagprovider voor cryptografische serviceproviders (CSP) gebaseerd op Microsoft CAPI. |
| SqlColumnEncryptionKeyStoreProvider-klasse | Basisklasse van de sleutelopslagproviders. |
| Opsomming SqlCommandColumnEncryptionSetting | Instellingen voor het beheren van het gedrag van Always Encrypted voor afzonderlijke query's. |
| SqlConnectionAttestationProtocol-opgave | Hiermee geeft u een waarde op voor Attestation Protocol bij het gebruik van Always Encrypted met beveiligde enclaves |
| SqlConnectionColumnEncryptionSetting Opsomming | Instellingen voor het inschakelen van versleuteling en ontsleuteling voor een databaseverbinding. |
| Eigenschap SqlConnectionStringBuilder.ColumnEncryptionSetting | Hiermee wordt Always Encrypted in de verbindingsreeks opgeslagen en ingesteld. |
| Eigenschap SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled | Hiermee schakelt u caching van metagegevens van versleutelingsquery's in en uit. |
| SqlConnection-eigenschap ColumnEncryptionKeyCacheTtl | Hiermee haalt en stelt u de levensduur in voor vermeldingen in de cache van kolomversleutelingssleutels. |
| Eigenschap SqlConnection.ColumnEncryptionTrustedMasterKeyPaths | Hiermee kunt u een lijst met vertrouwde sleutelpaden instellen voor een databaseserver. Als tijdens het verwerken van een toepassingsquery het stuurprogramma een sleutelpad ontvangt dat niet in de lijst staat, mislukt de query. Deze eigenschap biedt extra bescherming tegen beveiligingsaanvallen die betrekking hebben op een gecompromitteerde SQL Server die valse sleutelpaden biedt, wat kan leiden tot het lekken van referenties voor het sleutelarchief. |
| SqlConnection.RegisterColumnEncryptionKeyStoreProviders Methode | U kunt aangepaste sleutelopslagproviders registreren. Het is een woordenboek dat de namen van sleutelarchiefproviders koppelt aan de implementaties van sleutelarchiefproviders. |
| SqlCommand Constructor (String, SqlConnection, SqlTransaction, SqlCommandColumnEncryptionSetting) | Hiermee kunt u het gedrag van Always Encrypted voor afzonderlijke query's beheren. |
| Eigenschap SqlParameter.ForceColumnEncryption | Hiermee wordt versleuteling van een parameter afgedwongen. Als SQL Server het stuurprogramma informeert dat de parameter niet hoeft te worden versleuteld, mislukt de query met behulp van de parameter. Deze eigenschap biedt extra bescherming tegen beveiligingsaanvallen waarbij een geïnfecteerde SQL Server onjuiste versleutelingsmetagegevens aan de client biedt, wat kan leiden tot openbaarmaking van gegevens. |
trefwoord verbindingsreeks : Column Encryption Setting=enabled |
Hiermee schakelt u Always Encrypted-functionaliteit voor de verbinding in of uit. |
Zie ook
- Altijd versleuteld
- Always Encrypted met beveiligde enclaves
- SQL Database-zelfstudie: Gevoelige gegevens beveiligen met Always Encrypted
- Zelfstudie: Een .NET-toepassing ontwikkelen met Always Encrypted met beveiligde enclaves
- Voorbeeld: Azure Key Vault die werkt met Always Encrypted
- Voorbeeld: Azure Key Vault die werkt met Always Encrypted met beveiligde enclaves