Aracılığıyla paylaş


SQL Server için Microsoft .NET Veri Sağlayıcısı ile Always Encrypted kullanma

Şunlar için geçerlidir: .NET Framework .NET .NET Standard

Bu makalede, Always Encrypted veya güvenli kuşatmalar içeren Always Encrypted ve SQL Server için Microsoft .NET Veri Sağlayıcısı kullanarak .NET uygulamaları geliştirme hakkında bilgi sağlanır.

Always Encrypted, istemci uygulamalarının hassas verileri şifrelemesine ve verileri veya şifreleme anahtarlarını SQL Server veya Azure SQL Veritabanı'na hiçbir zaman göstermemesini sağlar. SQL Server için Microsoft .NET Veri Sağlayıcısı gibi Always Encrypted özellikli bir sürücü, istemci uygulamasındaki hassas verileri saydam bir şekilde şifreleyerek ve şifresini çözerek bu güvenliği sağlar. Sürücü, hassas veritabanı sütunlarına hangi sorgu parametrelerinin karşılık olduğunu otomatik olarak belirler (Always Encrypted kullanılarak korunur) ve verileri sunucuya geçirmeden önce bu parametrelerin değerlerini şifreler. Benzer şekilde, sürücü sorgu sonuçlarında şifrelenmiş veritabanı sütunlarından alınan verilerin şifresini saydam bir şekilde çözer. Daha fazla bilgi için bkz . Always Encrypted kullanarak uygulama geliştirme ve Güvenli kuşatmalarla Always Encrypted kullanarak uygulama geliştirme.

Önkoşullar

  • Veritabanınızda Always Encrypted'ı yapılandırın. Bu işlem Always Encrypted anahtarlarını sağlamayı ve seçili veritabanı sütunları için şifrelemeyi ayarlamayı içerir. Always Encrypted yapılandırılmış bir veritabanınız yoksa Öğretici: Always Encrypted'ı kullanmaya başlama başlığı altındaki yönergeleri izleyin.
  • Always Encrypted'ı güvenli kuşatmalarla kullanıyorsanız daha fazla önkoşul için bkz . Güvenli kuşatmalarla Always Encrypted kullanarak uygulama geliştirme .
  • Geliştirme makinenizde gerekli .NET platformunun yüklü olduğundan emin olun. Microsoft.Data.SqlClient ile Always Encrypted özelliği hem .NET Framework hem de .NET Core için desteklenir. .NET Framework 4.6 veya üzeri ya da .NET Core 2.1 veya üzeri sürümlerin geliştirme ortamınızda hedef .NET platform sürümü olarak yapılandırıldığından emin olun. Microsoft.Data.SqlClient sürüm 2.1.0 ve üzeri ile Always Encrypted özelliği .NET Standard 2.0 için de desteklenir. Always Encrypted'ı güvenli kuşatmalarla kullanmak için .NET Standard 2.1 gereklidir. Doğrulama olmadan VBS bölmelerini kullanmak istiyorsanız, Microsoft.Data.SqlClient sürüm 4.1 veya üzeri gereklidir. Visual Studio kullanıyorsanız Çerçeve hedeflemeye genel bakış bölümüne bakın.

Aşağıdaki tabloda, Always Encrypted'ı Microsoft.Data.SqlClient ile kullanmak için gerekli .NET platformları özetlenmektedir.

Always Encrypted Desteği Güvenli Kapanım ile Always Encrypted Desteği Hedef Çerçeve Microsoft.Data.SqlClient Sürümü İşletim Sistemi
Yes Yes .NET Framework 4.6+ 1.1.0+ Windows
Yes Yes .NET Core 2.1+ 2.1.0+1 Windows, Linux, macOS
Yes Hayı .NET Standard 2.0 2.1.0+ Windows, Linux, macOS
Yes Yes .NET Standard 2.1+ 2.1.0+ Windows, Linux, macOS

Uyarı

1 Microsoft.Data.SqlClient 2.1.0 sürümünden önce Always Encrypted yalnızca Windows'ta desteklenir.

Uygulama sorguları için Always Encrypted'i etkinleştirme

Parametrelerin şifrelenmesini ve şifrelenmiş sütunları hedefleyen sorgu sonuçlarının şifresini çözmeyi etkinleştirmenin en kolay yolu, bağlantı dizesi anahtar sözcüğü değerini Column Encryption Settingetkin olarak ayarlamaktır.

Aşağıdaki örnekte Always Encrypted'i etkinleştiren bir bağlantı dizesi kullanılır:

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

Aşağıdaki kod parçacığı, SqlConnectionStringBuilder.ColumnEncryptionSetting Özelliğini kullanan eşdeğer bir örnektir.

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 tek tek sorgular için de etkinleştirilebilir. Aşağıdaki Always Encrypted'ın performans etkisini denetleme bölümüne bakın. Always Encrypted'ın etkinleştirilmesi şifreleme veya şifre çözme işlemlerinin başarılı olması için yeterli değildir. Ayrıca şunları da yapmanız gerekir:

  • Uygulama, veritabanındaki Always Encrypted anahtarları hakkındaki meta verilere erişmek için gereken HERHANGİ BİR SÜTUN ANAHTAR TANIMINI GÖRÜNTÜLE ve HERHANGİ BİR SÜTUN ŞİFRELEME ANAHTAR TANIMINI GÖRÜNTÜLE veritabanı izinlerine sahiptir. Ayrıntılar için Always Encrypted (Veritabanı Altyapısı) bölümündeki Veritabanı İzinleri bölümüne bakın.
  • Uygulama, sorgulanan veritabanı sütunlarını şifreleyen sütun şifreleme anahtarlarını koruyan sütun ana anahtarına erişebilir.

Güvenli kuşatmalarla Always Encrypted'ı etkinleştirme

Sürücü, Microsoft.Data.SqlClient 1.1.0 sürümünden başlayarak güvenli kuşatmalarla Always Encrypted'ı destekler.

Kuşatmalar kullanarak uygulama geliştirme hakkında genel bilgi için bkz. Güvenli kuşatmalarla Always Encrypted kullanarak uygulama geliştirme.

Bir veritabanı bağlantısı için kapanım hesaplamalarını etkinleştirmek için Always Encrypted'ı etkinleştirmeye ek olarak aşağıdaki bağlantı dizesi anahtar sözcüklerini ayarlamanız gerekir (önceki bölümde açıklandığı gibi):

  • Attestation Protocol - bir kanıtlama protokolü belirtir.

    • Bu anahtar sözcük belirtilmezse, bağlantıda güvenli kuşatmalar devre dışı bırakılır.
    • SQL Server'ı Sanallaştırma tabanlı güvenlik (VBS) kuşatmalarıyla ve Konak Koruyucu Hizmeti (HGS) ile kullanıyorsanız, bu anahtar sözcüğün değeri olmalıdır HGS.
    • Azure SQL Veritabanı'nı Intel SGX kuşatmalarıyla ve Microsoft Azure Kanıtlama ile kullanıyorsanız, bu anahtar sözcüğün değeri olmalıdır AAS.
    • VBS kuşatmalarıyla Azure SQL Veritabanı veya SQL Server kullanıyorsanız ve kanıtlamayı kullanmak istemiyorsanız, bu anahtar sözcüğün değeri None olmalıdır. 4.1 veya üzeri bir sürüm gerektirir.

    Uyarı

    'Yok' (kanıtlama yok) şu anda Azure SQL Veritabanı'ndaki VBS kuşatmalarında desteklenen tek seçenektir.

  • Enclave Attestation URL - bir kanıtlama URL'si (kanıtlama hizmet uç noktası) belirtir. Kanıtlama hizmeti yöneticinizden ortamınız için bir kanıtlama URL'si almanız gerekir.

    • Eğer SQL Server ve Konak Koruyucu Hizmet (HGS) kullanıyorsanız, HGS kanıtlama URL'sini belirlemek ve paylaşmak için 'a ve'e bakın.
    • Azure SQL Veritabanı ve Microsoft Azure Kanıtlama'yı kullanıyorsanız, kanıtlama politikanız için kanıtlama URL'sini belirleme başlığına bakın.
    • Kanıtlama Protokolü kullanıyorsanız None kanıtlama URL'si gerekmez.

Adım adım öğretici için bkz Tutorial: Güvenli bölgelerle Always Encrypted kullanarak .NET uygulaması geliştirme.

Şifrelenmiş sütunlardaki verileri alma ve değiştirme

Uygulama sorguları için Always Encrypted'ı etkinleştirdikten sonra, şifrelenmiş veritabanı sütunlarındaki verileri almak veya değiştirmek için standart SqlClient API'lerini (bkz. ADO.NET'de Verileri Alma ve Değiştirme) veya Microsoft.Data.SqlClient Ad Alanında tanımlanan SQL Server API'leri için Microsoft .NET Veri Sağlayıcısı'nı kullanabilirsiniz. Uygulamanız gerekli veritabanı izinlerine sahipse ve sütun ana anahtarına erişebiliyorsa, SQL Server için Microsoft .NET Veri Sağlayıcısı şifrelenmiş sütunları hedefleyen tüm sorgu parametrelerini şifreler ve şifrelenmiş sütunlardan alınan verilerin şifresini çözer ve veritabanı şemasındaki sütunlar için ayarlanan SQL Server veri türlerine karşılık gelen .NET türlerinin düz metin değerlerini döndürür. Always Encrypted etkin değilse, şifrelenmiş sütunları hedefleyen parametrelere sahip sorgular başarısız olur. Sorguda şifrelenmiş sütunları hedefleyen parametre olmadığı sürece sorgular yine de şifrelenmiş sütunlardan veri alabilir. Ancak , SQL Server için Microsoft .NET Veri Sağlayıcısı şifrelenmiş sütunlardan alınan değerlerin şifresini çözmeyi denemez ve uygulama ikili şifrelenmiş verileri (bayt dizileri olarak) alır.

Aşağıdaki tabloda, Always Encrypted'ın etkinleştirilip etkinleştirilmediğine bağlı olarak sorguların davranışı özetlenir:

Sorgu özelliği Always Encrypted etkindir ve uygulama anahtarlara ve anahtar meta verilerine erişebilir Always Encrypted etkindir ve uygulama anahtarlara veya anahtar meta verilerine erişemez Always Encrypted devre dışı
Şifrelenmiş sütunları hedefleyen parametreleri olan sorgular. Parametre değerleri saydam olarak şifrelenir. Hata Hata
Şifrelenmiş sütunları hedefleyen parametreler olmadan şifrelenmiş sütunlardan veri alan sorgular. Şifrelenmiş sütunlardan elde edilen sonuçların şifresi saydam olarak çözülür. Uygulama, şifrelenmiş sütunlar için yapılandırılan SQL Server türlerine karşılık gelen .NET veri türlerinin düz metin değerlerini alır. Hata Şifrelenmiş sütunlardan elde edilen sonuçların şifresi çözülmez. Uygulama, şifrelenmiş değerleri bayt dizileri (bayt[]) olarak alır.

Aşağıdaki örneklerde şifrelenmiş sütunlardaki verilerin alınması ve değiştirilmesi gösterilmektedir. Örneklerde aşağıdaki şemaya sahip hedef tablo varsayılır. SSN ve BirthDate sütunları şifrelenir.

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

Veri ekleme örneği

Bu örnek, Patients tablosuna bir satır ekler. Aşağıdaki ayrıntıları not edin:

  • Örnek kodda şifrelemeye özgü bir şey yoktur. SQL Server için Microsoft .NET Veri Sağlayıcısı, şifrelenmiş sütunları hedefleyen parametreleri otomatik olarak algılar ve şifrelerparamSSNparamBirthdate. Bu davranış, şifrelemeyi uygulama için saydam hale getirir.
  • Şifrelenmiş sütunlar da dahil olmak üzere veritabanı sütunlarına eklenen değerler SqlParameter nesneleri olarak geçirilir. SqlParameter kullanımı, şifrelenmemiş sütunlara değer gönderirken isteğe bağlıdır (SQL eklemenin önlenmesine yardımcı olduğu için kesinlikle önerilir), şifrelenmiş sütunları hedefleyen değerler için gereklidir. veya sütunlarına eklenen değerler, sorgu ifadesine gömülü değişmez değerler olarak aktarılırsa, SQL Server için Microsoft .NET Veri Sağlayıcısı hedef şifrelenmiş sütunlardaki değerleri belirleyemez ve bu nedenle sorgu başarısız olur ve değerleri şifreleyemez.> Sonuç olarak, sunucu bunları şifrelenmiş sütunlarla uyumsuz olarak reddeder.
  • Sütunu hedefleyen SSN parametrenin veri türü, char/varchar SQL Server veri türüne eşlenen bir ANSI (Unicode olmayan) dizesine ayarlanır. Parametrenin türü nchar/nvarchar ile eşlenen bir Unicode dizesine (Dize) ayarlandıysa, Always Encrypted şifrelenmiş nchar/nvarchar değerlerinden şifrelenmiş karakter/varchar değerlerine dönüştürmeleri desteklemediğinden sorgu başarısız olur. Veri türü eşlemeleri hakkında bilgi için bkz. SQL Server Veri Türü Eşlemeleri.
  • Sütuna BirthDate eklenen parametrenin veri türü, .NET türlerinin SqlParameter.DbType Özelliği kullanılırken uygulanan SQL Server veri türlerine örtük eşlemesi yerine SqlParameter.SqlDbType Özelliği kullanılarak hedef SQL Server veri türüne açıkça ayarlanır. Varsayılan olarak DateTime Yapısı, datetime SQL Server veri türüyle eşleştirilir. Sütunun BirthDate veri türü tarih olduğu için ve Always Encrypted, şifrelenmiş tarih saat değerlerinin şifrelenmiş tarih değerlerine dönüştürülmesini desteklemediğinden, varsayılan eşlemenin kullanılması bir hataya yol açar.
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();
}

Düz metin verisi alma örneği

Aşağıdaki örnek, şifrelenmiş değerlere göre verileri filtrelemeyi ve şifrelenmiş sütunlardan düz metin verilerini almayı gösterir.

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());
            }
        }
    }
}

Uyarı

  • WHERE yan tümcesinde SSN sütununa filtre uygulamak için kullanılan değerin SqlParameter kullanılarak geçirilmesi gerekir, böylece SQL Server için Microsoft .NET Veri Sağlayıcısı bunu veritabanına göndermeden önce otomatik olarak şifreleyebilir.

  • SQL Server için Microsoft .NET Veri Sağlayıcısı ve SSN sütunlarından BirthDate alınan verilerin şifresini saydam bir şekilde çözeceği için, program tarafından yazdırılan tüm değerler düz metin biçiminde olacaktır.

  • Sorgular , belirleyici şifreleme kullanılarak şifrelenirse sütunlar üzerinde eşitlik karşılaştırmaları gerçekleştirebilir.

Şifrelenmiş verilerin alımı örneği

Always Encrypted etkinleştirilmemişse, sorgu şifrelenmiş sütunları hedefleyen parametreleri olmadığı sürece, sorgu şifrelenmiş sütunlardan verileri almaya devam edebilir.

Aşağıdaki örnek, şifrelenmiş sütunlardan ikili şifrelenmiş verilerin nasıl alınduğunu gösterir.

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]));
            }
        }
    }
}

Uyarı

  • Bağlantı dizesinde Always Encrypted etkinleştirilmediğinden, sorgu ve'nin SSNBirthDate şifrelenmiş değerlerini bayt dizileri olarak döndürür (program değerleri dizelere dönüştürür).

  • Always Encrypted devre dışı bırakılmış şifrelenmiş sütunlardan veri alan sorgunun parametreleri olabilir, ancak parametrelerin hiçbiri şifrelenmiş bir sütunu hedeflemez. Yukarıdaki sorgu LastName'e göre filtrelenir ve bu filtre veritabanında şifrelenmez. Eğer sorgu SSN veya BirthDate ile filtrelenirse, sorgu başarısız olur.

Şifrelenmiş sütunları sorgularken sık karşılaşılan sorunlardan kaçınma

Bu bölümde, .NET uygulamalarından şifrelenmiş sütunları sorgularken karşılaşılan yaygın hata kategorileri ve bunlardan kaçınmaya yönelik birkaç yönerge açıklanmaktadır.

Desteklenmeyen veri türü dönüştürme hataları

Always Encrypted, şifrelenmiş veri türleri için birkaç dönüştürmeyi destekler. Desteklenen tür dönüştürmelerinin ayrıntılı listesi için bkz . Always Encrypted . Veri türü dönüştürme hatalarını önlemek için aşağıdakileri yapın:

  • Şifrelenmiş sütunları hedefleyen parametre türlerini ayarlayarak parametrenin SQL Server veri türünün hedef sütunun türüyle tam olarak aynı olmasını veya parametrenin SQL Server veri türünün sütunun hedef türüne dönüştürülmesi desteklenir. SqlParameter.SqlDbType Özelliğini kullanarak .NET veri türlerinin belirli SQL Server veri türlerine eşlemini zorunlu kılabilirsiniz.
  • Ondalık ve sayısal SQL Server veri türlerinin sütunlarını hedefleyen parametrelerin duyarlığı ve ölçeğinin, hedef sütun için yapılandırılan duyarlık ve ölçekle aynı olduğunu doğrulayın.
  • datetime2, datetimeoffset veya time SQL Server veri türlerinin sütunlarını hedefleyen parametrelerin duyarlık değerinin hedef sütun için duyarlıktan büyük olmadığını doğrulayın (hedef sütundaki değerleri değiştiren sorgularda).

Şifrelenmiş değerler yerine düz metin geçirme hataları

Şifrelenmiş sütunu hedefleyen tüm değerlerin uygulama içinde şifrelenmesi gerekir. Şifrelenmiş bir sütunda düz metin değerine göre ekleme/değiştirme veya filtreleme girişimi aşağıdaki gibi bir hatayla sonuçlanır:

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'

Bu tür hataları önlemek için şunlardan emin olun:

  • Always Encrypted, şifrelenmiş sütunları hedefleyen uygulama sorguları için etkinleştirilir (bağlantı dizesi için veya belirli bir sorgunun SqlCommand nesnesinde).
  • Şifrelenmiş sütunları hedefleyen verileri göndermek için SqlParameter kullanırsınız. Aşağıdaki örnekte, sabit değeri bir SqlParameter nesnesine geçirmek yerine şifrelenmiş bir sütunda (SSN) sabit/değişmez değere göre yanlış filtreleyen bir sorgu gösterilmektedir.
using (SqlCommand cmd = connection.CreateCommand())
{
    cmd.CommandText = @"SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE SSN = '795-73-9838'";
    cmd.ExecuteNonQuery();
}

Sütun anahtar deposu ile çalışma

Bir parametre değerini şifrelemek veya sorgu sonuçlarındaki verilerin şifresini çözmek için SQL Server için Microsoft .NET Veri Sağlayıcısı'nın hedef sütun için yapılandırılmış bir sütun şifreleme anahtarı alması gerekir. Sütun şifreleme anahtarları, veritabanı meta verilerinde şifrelenmiş biçimde depolanır. Her sütun şifreleme anahtarının, sütun şifreleme anahtarını şifrelemek için kullanılan karşılık gelen bir sütun ana anahtarı vardır. Veritabanı meta verileri sütun ana anahtarlarını depolamaz; yalnızca belirli bir sütun ana anahtarını içeren bir anahtar deposu hakkındaki bilgileri ve anahtarın anahtar deposundaki konumunu içerir.

Bir sütun şifreleme anahtarının düz metin değerini almak için, SQL Server için Microsoft .NET Veri Sağlayıcısı önce hem sütun şifreleme anahtarı hem de ilgili sütun ana anahtarı hakkındaki meta verileri alır. Ardından meta verilerdeki bilgileri kullanarak sütun ana anahtarını içeren anahtar deposuyla iletişim kurar ve şifrelenmiş sütun şifreleme anahtarının şifresini çözer. SQL Server için Microsoft .NET Veri Sağlayıcısı, sqlColumnEncryptionKeyStoreProvider sınıfından türetilen bir sınıfın örneği olan bir sütun ana anahtar deposu sağlayıcısı kullanarak bir anahtar deposuyla iletişim kurar.

Sütun şifreleme anahtarı alma işlemi:

  1. Bir sorgu için Always Encrypted etkinleştirildiyse, SQL Server için Microsoft .NET Veri Sağlayıcısı , sorgunun parametreleri varsa şifrelenmiş sütunları hedefleyen parametreler için şifreleme meta verilerini almak üzere sys.sp_describe_parameter_encryption saydam olarak çağırır. Sorgu sonuçlarında yer alan şifrelenmiş veriler için SQL Server, şifreleme meta verilerini otomatik olarak ekler. Sütun ana anahtarıyla ilgili bilgiler şunları içerir:

    • Sütun ana anahtarını içeren bir anahtar depoyu kapsülleyen bir anahtar deposu sağlayıcısının adı.
    • Anahtar deposundaki sütun ana anahtarının konumunu belirten anahtar yolu.

    Sütun şifreleme anahtarıyla ilgili bilgiler şunları içerir:

    • Bir sütun şifreleme anahtarının şifrelenmiş değeri.
    • Sütun şifreleme anahtarını şifrelemek için kullanılan algoritmanın adı.
  2. SQL Server için Microsoft .NET Veri Sağlayıcısı, iç veri yapısında SqlColumnEncryptionKeyStoreProvider sınıfından türetilen bir sınıfın örneği olan sağlayıcı nesnesini aramak için sütun ana anahtar deposu sağlayıcısının adını kullanır.

  3. Sütun şifreleme anahtarının şifresini çözmek için, SQL Server için Microsoft .NET Veri Sağlayıcısı yöntemini çağırır SqlColumnEncryptionKeyStoreProvider.DecryptColumnEncryptionKey() ve sütun ana anahtarı yolunu, sütun şifreleme anahtarının şifrelenmiş değerini ve şifrelenmiş sütun şifreleme anahtarını üretmek için kullanılan şifreleme algoritmasının adını geçirir.

Yerleşik sütun ana anahtar deposu sağlayıcılarını kullanma

SQL Server için Microsoft .NET Veri Sağlayıcısı, belirli sağlayıcı adlarıyla önceden kaydedilmiş aşağıdaki yerleşik sütun ana anahtar deposu sağlayıcılarıyla birlikte gelir (sağlayıcıyı aramak için kullanılır). Bu yerleşik anahtar deposu sağlayıcıları yalnızca Windows'ta desteklenir.

Class Description Sağlayıcı (arama) adı Platform
SqlColumnEncryptionCertificateStoreProvider Sınıfı Windows Sertifika Deposu için bir sağlayıcı. MSSQL SERTİFİKA DEPOSU Windows
SqlColumnEncryptionCngProvider Sınıfı Microsoft Şifreleme API'sini destekleyen bir anahtar deposu sağlayıcısı : Yeni Nesil (CNG) API'si. Genellikle, bu tür bir depo, dijital anahtarları koruyan ve yöneten ve şifreleme işleme sağlayan fiziksel bir cihaz olan bir donanım güvenlik modülüdür. MSSQL_CNG_STORE Windows
SqlColumnEncryptionCspProvider Sınıfı Microsoft Şifreleme API'sini (CAPI) destekleyen bir anahtar deposu sağlayıcısı. Genellikle, bu tür bir depo, dijital anahtarları koruyan ve yöneten ve şifreleme işleme sağlayan fiziksel bir cihaz olan bir donanım güvenlik modülüdür. MSSQL_CSP_PROVIDER Windows

Bu sağlayıcıları kullanmak için uygulama kodunda herhangi bir değişiklik yapmanız gerekmez, ancak aşağıdaki ayrıntıları not edin:

  • Siz (veya DBA'nız) sütun ana anahtar meta verilerinde yapılandırılan sağlayıcı adının doğru olduğundan ve sütun ana anahtar yolunun belirli bir sağlayıcı için geçerli olan anahtar yolu biçimiyle uyumlu olduğundan emin olmanız gerekir. CREATE COLUMN MASTER KEY (Transact-SQL) deyimini verirken geçerli sağlayıcı adlarını ve anahtar yollarını otomatik olarak oluşturan SQL Server Management Studio gibi araçları kullanarak anahtarları yapılandırmanız önerilir. Daha fazla bilgi için bkz . SQL Server Management Studio kullanarak Always Encrypted'ı yapılandırma ve PowerShell kullanarak Always Encrypted'ı yapılandırma.
  • Uygulamanızın anahtar deposundaki anahtara erişebildiğinden emin olun. Bu işlem, kullandığınız anahtar deposuna bağlı olarak, uygulamanıza anahtara ve/veya anahtar deposuna erişim izni verme veya anahtar deposuna özgü diğer yapılandırma adımlarını gerçekleştirme işlemini içerebilir. Örneğin, CNG veya CAPI uygulayan bir anahtar deposuna erişmek için (donanım güvenlik modülü gibi), mağazanız için CNG veya CAPI uygulayan bir kitaplığın uygulama makinenizde yüklü olduğundan emin olmanız gerekir. Ayrıntılar için bkz. Always Encrypted için sütun ana anahtarları oluşturma ve depolama.

Azure Key Vault sağlayıcısını kullanma

Azure Key Vault, Always Encrypted için sütun ana anahtarlarını depolamak ve yönetmek için kullanışlı bir seçenektir (özellikle de uygulamalarınız Azure'da barındırılıyorsa). SQL Server için Microsoft .NET Veri Sağlayıcısı, Azure Key Vault için yerleşik bir sütun ana anahtar deposu sağlayıcısı içermez, ancak uygulamanızla kolayca tümleştirebileceğiniz bir NuGet paketi (Microsoft.Data.SqLClient.AlwaysEncrypted.AzureKeyVaultProvider) olarak kullanılabilir. Ayrıntılar için bkz . Always Encrypted - Veri şifrelemesi ile SQL Veritabanı'ndaki hassas verileri koruma ve şifreleme anahtarlarınızı Azure Key Vault'ta depolama.

Class Description Sağlayıcı (arama) adı Platform
SqlColumnEncryptionAzureKeyVaultProvider Sınıfı Azure Key Vault sağlayıcısı. AZURE_KEY_VAULT Windows, Linux, macOS

.NET Desteklenebilirliği

Sürüm Microsoft.Data.SqlClient sürümü .NET platformları
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+

v3.0.0'dan başlayarak, Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProviderSqlConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection veya SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand API'lerini kullanarak sağlayıcıyı kaydederken sütun şifreleme anahtarı önbelleğe alma özelliklerini destekler.

v2.0.0 sürümünden Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider başlayarak, Azure Key Vault ile kimlik doğrulaması gerçekleştirmek için yeni Azure.Core ve Azure.Identity API'leri destekler. TokenCredential uygulamasının bir örneği, Azure Key Vault sağlayıcı nesnesini başlatmak için artık SqlColumnEncryptionAzureKeyVaultProvider oluşturucularına geçirilebilir.

Uyarı

, Microsoft.Data.SqLClient.AlwaysEncrypted.AzureKeyVaultProviderAzure Key Vault'ta hem Kasaları hem de Yönetilen HSM'leri destekler.

Azure Key Vault ile şifreleme/şifre çözmeyi gösteren örnekler için bkz. Always Encrypted ile çalışan Azure Key Vault ve güvenli kuşatmalarla Always Encrypted ile çalışan Azure Key Vault.

Özel sütun ana anahtar deposu sağlayıcısı uygulama

Sütun ana anahtarlarını var olan bir sağlayıcı tarafından desteklenmeyen bir anahtar deposunda depolamak istiyorsanız, SqlColumnEncryptionKeyStoreProvider sınıfını genişleterek ve aşağıdaki yöntemlerden birini kullanarak sağlayıcıyı kaydederek özel bir sağlayıcı uygulayabilirsiniz:

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);
        // ...
    }
}

Sütun şifreleme anahtarı önbellek önceliği

Bu bölüm , SQL Server için Microsoft .NET Veri Sağlayıcısı'nın 3.0 ve üzeri sürümleri için geçerlidir.

Bağlantı veya komut örneğine kayıtlı özel anahtar deposu sağlayıcıları tarafından şifresi çözülen sütun şifreleme anahtarları (CEK), SQL Server için Microsoft .NET Veri Sağlayıcısı tarafından önbelleğe alınmaz. Özel anahtar deposu sağlayıcıları kendi CEK önbelleğe alma mekanizmalarını uygulamalıdır.

v3.0.0 itibaren Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider her Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider örneğinin kendi CEK önbelleğe alma uygulaması mevcut. Bir bağlantı veya komut örneğine kaydedildiğinde, Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider örneği tarafından şifresi çözülen CEK'ler, bu örnek kapsamdan çıktığında temizlenir.

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
        }
    }
}

Uyarı

Özel anahtar deposu sağlayıcıları tarafından uygulanan CEK önbelleğe alma, anahtar deposu sağlayıcı örneği SqlConnection.RegisterColumnEncryptionKeyStoreProviders yöntemi kullanılarak sürücüye genel olarak kaydedildiyse sürücü tarafından devre dışı bırakılır. Herhangi bir CEK önbelleğe alma uygulaması, CEK'yi önbelleğe almadan önce SqlColumnEncryptionKeyStoreProvider.ColumnEncryptionKeyCacheTtl değerine başvurmalıdır ve değer sıfır olduğunda önbelleğe almamalıdır. Kullanıcılar anahtar önbelleğe almayı yapılandırmaya çalışırken, yinelenen önbelleğe almayı ve olası kullanıcı karışıklığını önleyecektir.

Özel sütun ana anahtar deposu sağlayıcısı kaydetme

Bu bölüm, sağlayıcının 3.0 ve üzeri sürümleri için geçerlidir.

Özel ana anahtar deposu sağlayıcıları sürücüye üç farklı katmanda kaydedilebilir. Üç kaydın önceliği aşağıdaki gibidir:

  • Komut başına kayıt boş olup olmadığı kontrol edilecektir.
  • Komut başına kayıt boşsa, bağlantı başına kayıt boş değilse denetlenecektir.
  • Bağlantı başına kayıt boşsa genel kayıt kontrol edilecektir.

Herhangi bir anahtar deposu sağlayıcısı kayıt düzeyinde bulunduktan sonra, sürücü sağlayıcı aramak için diğer kayıtlara geri dönmez . Sağlayıcılar kayıtlıysa ancak uygun sağlayıcı bir düzeyde bulunamazsa, yalnızca denetlenen kayıttaki kayıtlı sağlayıcıları içeren bir özel durum oluşturulur.

Windows Sertifika Deposu, CNG Deposu ve CSP için kullanılabilen yerleşik sütun ana anahtar deposu sağlayıcıları önceden kaydedilir.

Üç kayıt düzeyi, şifrelenmiş verileri sorgularken farklı senaryoları destekler. Bir uygulamanın kullanıcısının, sütun ana anahtarını içeren anahtar deposunda kimlik doğrulaması yaparak gerekli sütun ana anahtarını sağlayabildiği durumlarda düz metin verilerine erişebilmesini sağlamak için uygun yöntem kullanılabilir.

Bir SqlConnection örneğini birden çok kullanıcı arasında paylaşan uygulamalar SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand kullanmak isteyebilir. Şifrelenmiş bir sütuna erişmek için sorgu yürütmeden önce her kullanıcının sqlcommand örneğine bir anahtar deposu sağlayıcısı kaydetmesi gerekir. Anahtar deposu sağlayıcısı, kullanıcının verilen kimlik bilgilerini kullanarak anahtar deposundaki gerekli sütun ana anahtarına erişebiliyorsa sorgu başarılı olur.

Her kullanıcı için bir SqlConnection örneği oluşturan uygulamalar SqlConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection kullanmak isteyebilir. Bu yöntemle kaydedilen anahtar deposu sağlayıcıları, şifrelenmiş verilere erişen tüm sorgular için bağlantı tarafından kullanılabilir.

SqlConnection.RegisterColumnEncryptionKeyStoreProviders kullanılarak kaydedilen anahtar deposu sağlayıcıları, anahtar deposunda kimlik doğrulaması yaparken uygulama tarafından verilen kimliği kullanır.

Aşağıdaki örnek, bir bağlantı örneğine kayıtlı özel sütun ana anahtar deposu sağlayıcılarının önceliğini gösterir:

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);
        }
    }
}

Aşağıdaki örnekte, bir komut örneğine kayıtlı özel sütun ana anahtar deposu sağlayıcılarının önceliği gösterilmektedir:

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);
            }
        }
    }
}

Programlı anahtar sağlama için sütun ana anahtar deposu sağlayıcılarını kullanma

SQL Server için Microsoft .NET Veri Sağlayıcısı şifrelenmiş sütunlara eriştiğinde, sütun şifreleme anahtarlarının şifresini çözmek için doğru sütun ana anahtar deposu sağlayıcısını saydam bir şekilde bulur ve çağırır. Normal uygulama kodunuz genellikle sütun ana anahtar deposu sağlayıcılarını doğrudan çağırmaz. Bununla birlikte, always Encrypted anahtarlarını program aracılığıyla oluşturmak ve yönetmek için bir sağlayıcının örneğini oluşturabilir ve çağırabilirsiniz: şifrelenmiş bir sütun şifreleme anahtarı oluşturmak ve bir sütun şifreleme anahtarının şifresini çözmek için (örneğin, sütun ana anahtarı döndürme). Daha fazla bilgi için bkz. Always Encrypted için anahtar yönetimine genel bakış. Kendi anahtar yönetimi araçlarınızı uygulamak yalnızca özel anahtar deposu sağlayıcısı kullanıyorsanız gerekli olabilir. Yerleşik sağlayıcıların bulunduğu anahtar depolarında veya Azure Key Vault'ta depolanan anahtarları kullanırken, anahtarları yönetmek ve sağlamak için SQL Server Management Studio veya PowerShell gibi mevcut araçları kullanabilirsiniz. Aşağıdaki örnekte, bir sütun şifreleme anahtarı oluşturma ve anahtarı bir sertifikayla şifrelemek için SqlColumnEncryptionCertificateStoreProvider sınıfını kullanma gösterilmektedir.

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);
}

Always Encrypted'ın performans etkisini denetleme

Always Encrypted bir istemci tarafı şifreleme teknolojisi olduğundan, performans ek yükünün çoğu veritabanında değil istemci tarafında gözlemlenir. Şifreleme ve şifre çözme işlemlerinin maliyeti dışında, istemci tarafındaki diğer performans yükü kaynakları şunlardır:

  • Sorgu parametrelerinin meta verilerini almak için veritabanına fazladan gidiş dönüşler.
  • Bir sütun ana anahtarına erişmek için bir sütun ana anahtar deposuna çağrılar.

Bu bölümde SQL Server için Microsoft .NET Veri Sağlayıcısı'ndaki yerleşik performans iyileştirmeleri ve yukarıdaki iki faktörün performans üzerindeki etkisini nasıl denetleyebileceğiniz açıklanmaktadır.

Sorgu parametreleri için meta verileri almak için gidiş dönüşleri denetleme

Always Encrypted bir bağlantı için etkinleştirildiyse, SQL Server için Microsoft .NET Veri Sağlayıcısı varsayılan olarak her parametreli sorgu için sys.sp_describe_parameter_encryption çağırır ve sorgu deyimini (parametre değerleri olmadan) SQL Server'a geçirir. sys.sp_describe_parameter_encryption , herhangi bir parametrenin şifrelenmesi gerekip gerekmediğini öğrenmek için sorgu deyimini analiz eder ve bu durumda her biri için SQL Server için Microsoft .NET Veri Sağlayıcısı'nın parametre değerlerini şifrelemesine olanak sağlayacak şifrelemeyle ilgili bilgileri döndürür. Yukarıdaki davranış, istemci uygulaması için yüksek düzeyde saydamlık sağlar. Şifrelenmiş sütunları hedefleyen değerler SqlParameter nesnelerinde SQL Server için Microsoft .NET Veri Sağlayıcısı'na geçirildiği sürece uygulamanın (ve uygulama geliştiricisinin) hangi sorguların şifrelenmiş sütunlara eriştiğini bilmesi gerekmez.

Sorgu meta verileri önbelleğe alma

SQL Server için Microsoft .NET Veri Sağlayıcısı, her sorgu deyimi için sys.sp_describe_parameter_encryption sonuçlarını önbelleğe alır. Bu nedenle, aynı sorgu deyimi birden çok kez yürütülürse, sürücü sys.sp_describe_parameter_encryption yalnızca bir kez çağırır. Sorgu deyimleri için şifreleme meta verileri önbelleğe alma, veritabanından meta verileri getirmenin performans maliyetini önemli ölçüde azaltır. Önbelleğe alma varsayılan olarak etkindir. SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled özelliğini false olarak ayarlayarak parametre meta verilerini önbelleğe almayı devre dışı bırakabilirsiniz, ancak aşağıda açıklanan gibi nadir durumlar dışında bunu yapmanız önerilmez:

İki farklı şeması olan bir veritabanını düşünün: s1 ve s2. Her şema aynı ada sahip bir tablo içerir: t. s1.t ve s2.t tablolarının tanımları, şifreleme ile ilgili özellikler dışında, aynıdır: s1.t tablosundaki c adlı sütun şifrelenmezken, bu sütun s2.t tablosunda şifrelenmiştir. Veritabanının iki kullanıcısı vardır: u1 ve u2. Kullanıcıların varsayılan şemasıdır u1s1. için u2 varsayılan şemadır s2. .NET uygulaması, veritabanına iki bağlantı açar; bir bağlantıda u1 kullanıcısının kimliğine, diğer bağlantıda ise u2 kullanıcısının kimliğine bürünür. Uygulama, kullanıcı c için bağlantı üzerinden sütunu hedefleyen u1 bir parametre içeren bir sorgu gönderir (sorgu şemayı belirtmediğinden, varsayılan kullanıcı şeması varsayılır). Ardından uygulama, kullanıcı için bağlantı üzerinden aynı sorguyu u2 gönderir. Sorgu meta verileri önbelleğe alma etkinleştirilirse, ilk sorgudan sonra önbellek sorgu parametresinin hedeflediği sütunun c şifrelenmediğini gösteren meta verilerle doldurulur. İkinci sorgu aynı sorgu deyimine sahip olduğundan, önbellekte depolanan bilgiler kullanılır. Sonuç olarak, sürücü, hedef sütun s2.t.c şifrelenmiş olduğundan parametresini şifrelemeden sorguyu gönderir, bu da yanlıştır ve parametrenin düz metin değerini sunucuya sızdıracaktır. Sunucu bu uyumsuzluğu algılar ve sürücüyü önbelleği yenilemeye zorlar, bu nedenle uygulama sorguyu doğru şifrelenmiş parametre değeriyle saydam bir şekilde yeniden gönderir. Böyle bir durumda, hassas değerlerin sunucuya sızmasını önlemek için önbelleğe alma devre dışı bırakılmalıdır.

Always Encrypted'i sorgu düzeyinde ayarlama

Parametreli sorgular için şifreleme meta verilerini almanın performans etkisini denetlemek için, bağlantı için ayarlamak yerine tek tek sorgular için Always Encrypted'ı etkinleştirebilirsiniz. Bu şekilde, sys.sp_describe_parameter_encryption yalnızca şifrelenmiş sütunları hedefleyen parametreleri olduğunu bildiğiniz sorgular için çağrıldığından emin olabilirsiniz. Bununla birlikte, bunu yaparak şifreleme saydamlığını azalttığınızı unutmayın: Veritabanı sütunlarınızın şifreleme özelliklerini değiştirirseniz, uygulamanızın kodunu şema değişiklikleriyle uyumlu hale getirmek için değiştirmeniz gerekebilir.

Uyarı

Always Encrypted'ın sorgu düzeyinde ayarlanması, parametre şifrelemesi meta veri önbelleğinin performans avantajını sınırlar.

Bireysel sorguların Always Encrypted davranışını denetlemek için, SqlCommand oluşturucusunu ve SqlCommandColumnEncryptionSetting oluşturucusunu kullanmanız gerekir. Bazı yararlı yönergeler şunlardır:

  • İstemci uygulaması çoğu sorguda şifreli sütunlara erişim sağlarsa:
    • Sütun Şifreleme Ayarı bağlantı dizesi anahtar sözcüğünü Etkin olarak ayarlayın.
    • Şifrelenmiş sütunlara erişmeyen tek tek sorgular için SqlCommandColumnEncryptionSetting değerini Devre Dışı olarak ayarlayın. Bu ayar hem çağrı sys.sp_describe_parameter_encryption hem de sonuç kümesindeki değerlerin şifresini çözme girişimini devre dışı bırakır.
    • Şifreleme gerektiren parametreleri olmayan ancak şifrelenmiş sütunlardan veri alan tek tek sorgular için SqlCommandColumnEncryptionSetting değerini ResultSetOnly olarak ayarlayın. Bu ayar , sys.sp_describe_parameter_encryption ve parametre şifreleme çağrılarını devre dışı bırakır. Sorgu, şifreleme sütunlarından sonuçların şifresini çözebilir.
  • Bir istemci uygulamasının yürüttüğü sorguların çoğu şifrelenmiş sütunlara erişmiyorsa:
    • Sütun Şifreleme Ayarı bağlantı dizesi anahtarını Devre Dışı olarak ayarlayın.
    • Şifrelenmesini gerektiren parametreleri olan tek tek sorgular için SqlCommandColumnEncryptionSetting değerini Etkin olarak ayarlayın. Bu ayar hem çağırma sys.sp_describe_parameter_encryption hem de şifrelenmiş sütunlardan alınan tüm sorgu sonuçlarının şifresinin çözülmesini etkinleştirir.
    • Şifreleme gerektiren parametreleri olmayan ancak şifrelenmiş sütunlardan veri alan sorgular için SqlCommandColumnEncryptionSetting değerini ResultSetOnly olarak ayarlayın. Bu ayar , sys.sp_describe_parameter_encryption ve parametre şifreleme çağrılarını devre dışı bırakır. Sorgu, şifreleme sütunlarından sonuçların şifresini çözebilir.

Aşağıdaki örnekte, veritabanı bağlantısı için Always Encrypted devre dışı bırakılmıştır. Uygulama tarafından oluşturulan sorgu, şifrelenmemiş LastName sütununu hedefleyen bir parametre içerir. Sorgu, her ikisi de şifrelenmiş olan SSN ve BirthDate sütunlarından veri alır. Böyle bir durumda, şifreleme meta verilerini almak için sys.sp_describe_parameter_encryption çağrılması gerekmez. Ancak, uygulamanın şifrelenmiş iki sütundan düz metin değerleri alabilmesi için sorgu sonuçlarının şifresinin çözülmesinin etkinleştirilmesi gerekir. Emin olmak için SqlCommandColumnEncryptionSettingResultSetOnly ayarı kullanılır.

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());
            }
        }
    }
}

Sütun şifreleme anahtarı önbelleğe alma

Sütun şifreleme anahtarlarının şifresini çözmek üzere bir sütun ana anahtar deposuna yapılan çağrı sayısını azaltmak için, SQL Server için Microsoft .NET Veri Sağlayıcısı düz metin sütun şifreleme anahtarlarını bellekte önbelleğe alır. Sağlayıcı, veritabanı meta verilerinden şifrelenmiş sütun şifreleme anahtarı değerini aldıktan sonra, sürücü önce şifrelenmiş anahtar değerine karşılık gelen düz metin sütun şifreleme anahtarını bulmaya çalışır. Sürücü, yalnızca önbellekte şifrelenmiş sütun şifreleme anahtarı değerini bulamıyorsa, sütun ana anahtarını içeren anahtar depoyu çağırır.

Önbellek girdileri, güvenlik nedeniyle yapılandırılabilir bir yaşam süresi aralığından sonra çıkarılır. Varsayılan yaşam süresi değeri 2 saattir. Sütun şifreleme anahtarlarının uygulamada düz metin olarak ne kadar süreyle önbelleğe alınabileceği konusunda daha katı güvenlik gereksinimleriniz varsa, SqlConnection.ColumnEncryptionKeyCacheTtl özelliğini kullanarak bunu değiştirebilirsiniz.

SqlConnection.RegisterColumnEncryptionKeyStoreProvidersOnConnection ve SqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand kullanılarak kaydedilen özel anahtar deposu sağlayıcılarının şifresi çözülmüş sütun şifreleme anahtarları SQL Server için Microsoft .NET Veri Sağlayıcısı tarafından önbelleğe alınmaz. Bunun yerine, özel anahtar deposu sağlayıcılarının kendi önbelleğe alma mekanizmalarını uygulaması gerekir. Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider v3.0.0 ve üzeri kendi önbelleğe alma uygulamasıyla birlikte gelir.

Aynı uygulamanın farklı kullanıcılarının birden çok sorgu yürütebileceği senaryoları desteklemek için, özel anahtar deposu sağlayıcıları bir kullanıcıya eşlenebilir ve bu kullanıcıya özgü bir bağlantı veya komut örneğine kaydedilebilir. Aşağıdaki örnek, örneğinin Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider aynı kullanıcı için farklı SqlCommand nesneler arasında nasıl yeniden kullanılabilmesini göstermektedir. Sütun şifreleme anahtarı önbelleği birden çok sorguda kalıcı olur ve anahtar deposuna gidiş dönüş sayısını azaltır:

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
    }
}

Güvenliği aşılmış bir SQL Server için ek korumayı etkinleştirme

Varsayılan olarak, SQL Server için Microsoft .NET Veri Sağlayıcısı veritabanındaki hangi sütunların şifrelendiği ve nasıl şifrelendiği hakkında meta veriler sağlamak için veritabanı sistemine (SQL Server veya Azure SQL Veritabanı) dayanır. Şifreleme meta verileri , SQL Server için Microsoft .NET Veri Sağlayıcısı'nın sorgu parametrelerini şifrelemesine ve uygulamadan herhangi bir giriş yapmadan sorgu sonuçlarının şifresini çözmesine olanak tanır ve bu da uygulamada gereken değişiklik sayısını büyük ölçüde azaltır. Ancak, SQL Server işleminin gizliliği ihlal edilirse ve bir saldırgan SQL Server'ın SQL Server için Microsoft .NET Veri Sağlayıcısı'na gönderdiği meta verilerle oynanırsa, saldırgan hassas bilgileri çalabilir. Bu bölümde, daha düşük saydamlık karşılığında bu tür saldırılara karşı ek bir koruma düzeyi sağlamaya yardımcı olan API'ler açıklanmaktadır.

Parametre Şifrelemesi Zorlama

SQL Server için Microsoft .NET Veri Sağlayıcısı SQL Server'a parametreli bir sorgu göndermeden önce, SQL Server'dan (sys.sp_describe_parameter_encryption çağırarak) sorgu deyimini çözümlemesini ve sorgudaki hangi parametrelerin şifrelenmesi gerektiği hakkında bilgi vermesini ister. Güvenliği aşılmış bir SQL Server örneği, veritabanında şifrelenmiş olsa bile parametrenin şifrelenmiş bir sütunu hedeflemediğini belirten meta veriler göndererek SQL Server için Microsoft .NET Veri Sağlayıcısı'nı yanıltabilir. Sonuç olarak, SQL Server için Microsoft .NET Veri Sağlayıcısı parametre değerini şifrelemez ve güvenliği aşılmış SQL Server örneğine düz metin olarak gönderir.

Böyle bir saldırıyı önlemek için bir uygulama, parametresi için SqlParameter.ForceColumnEncryption Özelliğini true olarak ayarlayabilir. Bu ayar, sunucudan aldığı meta veriler parametrenin şifrelenmesinin gerekmediğini gösteriyorsa SQL Server için Microsoft .NET Veri Sağlayıcısı'nın özel durum oluşturmasına neden olur.

SqlParameter.ForceColumnEncryption özelliğinin kullanılması güvenliğin geliştirilmesine yardımcı olsa da, istemci uygulaması için şifreleme saydamlığını da azaltır. Şifrelenmiş sütun kümesini değiştirmek için veritabanı şemasını güncelleştirirseniz, uygulama değişiklikleri de yapmanız gerekebilir.

Aşağıdaki kod örneği, sosyal güvenlik numaralarının veritabanına düz metin olarak gönderilmesini önlemek için SqlParameter.ForceColumnEncryption özelliğinin kullanılmasını gösterir.

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.
    }
}

Güvenilen sütun ana anahtar yollarını yapılandırma

SQL Server'ın şifrelenmiş sütunları hedefleyen sorgu parametreleri için döndürdüğü şifreleme meta verileri ve şifreleme sütunlarından alınan sonuçlar için anahtar deposunu ve anahtarın anahtar deposundaki konumunu tanımlayan ana sütun anahtarının anahtar yolunu içerir. SQL Server örneğinin güvenliği aşılırsa, SQL Server için Microsoft .NET Veri Sağlayıcısı'nı bir saldırgan tarafından denetlenen konuma yönlendiren anahtar yolunu gönderebilir. Bu işlem, anahtar deposu uygulamanın kimlik doğrulamasını gerektiriyorsa anahtar deposu kimlik bilgilerinin sızmasına neden olabilir.

Bu tür saldırıları önlemek için uygulama, SqlConnection.ColumnEncryptionTrustedMasterKeyPaths özelliğini kullanarak belirli bir sunucu için güvenilen anahtar yollarının listesini belirtebilir. SQL Server için Microsoft .NET Veri Sağlayıcısı güvenilen anahtar yolu listesinin dışında bir anahtar yolu alırsa, bir özel durum oluşturur.

Güvenilen anahtar yollarının ayarlanması uygulamanızın güvenliğini artırsa da, sütun ana anahtarınızı her döndürdüğünüzde (sütun ana anahtarı yolu değiştiğinde) kodu veya/ve uygulamanın yapılandırmasını değiştirmeniz gerekir.

Aşağıdaki örnekte, güvenilen sütun ana anahtar yollarının nasıl yapılandırılır gösterilmektedir:

// 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);

SqlBulkCopy kullanarak şifrelenmiş verileri kopyalama

SqlBulkCopy ile verilerin şifresini çözmeden zaten şifrelenmiş ve bir tabloda depolanan verileri başka bir tabloya kopyalayabilirsiniz. Bunu yapmak için:

  • Hedef tablonun şifreleme yapılandırmasının kaynak tablonun yapılandırmasıyla aynı olduğundan emin olun. Özellikle, her iki tabloda da aynı sütunlar şifrelenmeli ve sütunlar aynı şifreleme türleri ve aynı şifreleme anahtarları kullanılarak şifrelenmelidir. Hedef sütunlardan herhangi biri karşılık gelen kaynak sütunundan farklı şekilde şifrelenirse, kopyalama işleminden sonra hedef tablodaki verilerin şifresini çözemezsiniz. Veriler bozulur.
  • Always Encrypted etkinleştirilmeden hem kaynak tabloya hem de hedef tabloya veritabanı bağlantılarını yapılandırın.
  • AllowEncryptedValueModifications seçeneğini ayarlayın (bkz. SqlBulkCopyOptions).

Uyarı

AllowEncryptedValueModifications belirtirken dikkatli olun. SQL Server için Microsoft .NET Veri Sağlayıcısı verilerin gerçekten şifrelenip şifrelenmediğini veya hedef sütunla aynı şifreleme türü, algoritma ve anahtar kullanılarak doğru şekilde şifrelenip şifrelenmediğini denetlemediğinden bu ayar veritabanının bozulmasına neden olabilir.

Burada verileri bir tablodan diğerine kopyalayan bir örnek verilmiştir. SSN ve BirthDate sütunlarının şifrelendiği varsayılır.

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 referansı

Ad Alanı:Microsoft.Data.SqlClient

Derleme: Microsoft.Data.SqlClient.dll

İsim Description
SqlColumnEncryptionCertificateStoreProvider Sınıfı Windows Sertifika Deposu için bir anahtar deposu sağlayıcısı.
SqlColumnEncryptionCngProvider Sınıfı Microsoft Şifreleme API'si için bir anahtar deposu sağlayıcısı: Yeni Nesil (CNG).
SqlColumnEncryptionCspProvider Sınıfı Microsoft CAPI tabanlı Şifreleme Hizmeti Sağlayıcıları (CSP) için bir anahtar deposu sağlayıcısı.
SqlColumnEncryptionKeyStoreProvider Sınıfı Anahtar deposu sağlayıcılarının temel sınıfı.
SqlCommandColumnEncryptionSetting Sabit Listesi Tek tek sorgular için Always Encrypted davranışını denetleme ayarları.
SqlConnectionAttestationProtocol Numaralandırması Güvenli kuşatmalarla Always Encrypted kullanılırken Kanıtlama Protokolü için bir değer belirtir
SqlConnectionColumnEncryptionSetting Sabit Listesi Veritabanı bağlantısı için şifrelemeyi ve şifre çözmeyi etkinleştirme ayarları.
SqlConnectionStringBuilder.ColumnEncryptionSetting Özelliği Bağlantı dizesinde Always Encrypted'ı alır ve ayarlar.
SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled Özelliği Şifreleme sorgusu meta verilerini önbelleğe almayı etkinleştirir ve devre dışı bırakır.
SqlConnection.ColumnEncryptionKeyCacheTtl Özelliği Sütun şifreleme anahtarı önbelleğindeki girdilerin yaşam süresini alır ve ayarlar.
SqlConnection.ColumnEncryptionTrustedMasterKeyPaths Özelliği Veritabanı sunucusu için güvenilen anahtar yollarının listesini ayarlamanıza olanak tanır. Bir uygulama sorgusu işlenirken sürücü listede olmayan bir anahtar yolu alırsa, sorgu başarısız olur. Bu özellik, güvenliği aşılmış bir SQL Server'ın sahte anahtar yolları sağlamasını içeren ve anahtar deposu kimlik bilgilerinin sızmasına neden olabilecek güvenlik saldırılarına karşı ek koruma sağlar.
SqlConnection.RegisterColumnEncryptionKeyStoreProviders Yöntemi Özel anahtar deposu sağlayıcılarını kaydetmenizi sağlar. Anahtar deposu sağlayıcı adlarını anahtar deposu sağlayıcı uygulamalarıyla eşleyen bir sözlüktür.
SqlCommand Oluşturucu (String, SqlConnection, SqlTransaction, SqlCommandColumnEncryptionSetting) Tek tek sorgular için Always Encrypted davranışını denetlemenizi sağlar.
SqlParameter.ForceColumnEncryption Özelliği Bir parametrenin şifrelenmesini zorlar. SQL Server sürücüye parametrenin şifrelenmesinin gerekmediğini bildirirse, parametresini kullanan sorgu başarısız olur. Bu özellik, istemciye yanlış şifreleme meta verileri sağlayan güvenliği aşılmış bir SQL Server içeren güvenlik saldırılarına karşı ek koruma sağlar ve bu da verilerin açığa çıkmasına neden olabilir.
bağlantı dizesi anahtar sözcüğü: Column Encryption Setting=enabled Bağlantı için Always Encrypted işlevselliğini etkinleştirir veya devre dışı bırakır.

Ayrıca bakınız