Always Encrypted: защита конфиденциальных данных и хранение ключей шифрования в Azure Key VaultAlways Encrypted: Protect sensitive data and store encryption keys in Azure Key Vault

В этой статье показано, как защитить конфиденциальные данные в базе данных SQL с помощью шифрования данных, используя мастер настройки Always Encrypted в SQL Server Management Studio (SSMS).This article shows you how to secure sensitive data in a SQL database with data encryption using the Always Encrypted Wizard in SQL Server Management Studio (SSMS). Она также содержит инструкции, с помощью которых вы узнаете, как сохранить каждый ключ шифрования в хранилище ключей Azure.It also includes instructions that will show you how to store each encryption key in Azure Key Vault.

Always Encrypted — это новая технология шифрования данных, применяемая в Базе данных SQL Azure и SQL Server. Она помогает защитить конфиденциальные данные, которые хранятся на сервере, перемещаются между клиентом и сервером и просто используются.Always Encrypted is a new data encryption technology in Azure SQL Database and SQL Server that helps protect sensitive data at rest on the server, during movement between client and server, and while the data is in use. Always Encrypted гарантирует, что конфиденциальные данные никогда не отобразятся как открытый текст внутри системы баз данных.Always Encrypted ensures that sensitive data never appears as plaintext inside the database system. После настройки шифрования данных получить доступ к данным в виде открытого текста смогут только клиентские приложения и серверы приложений, у которых есть доступ к ключам.After you configure data encryption, only client applications or app servers that have access to the keys can access plaintext data. Дополнительные сведения см. в статье Always Encrypted (ядро СУБД).For detailed information, see Always Encrypted (Database Engine).

После настройки функции Always Encrypted для базы данных вы создадите клиентское приложение на языке C# для работы с зашифрованными данными, используя Visual Studio.After you configure the database to use Always Encrypted, you will create a client application in C# with Visual Studio to work with the encrypted data.

Выполнив шаги, приведенные в этой статье, вы узнаете, как настроить Always Encrypted для базы данных SQL Azure.Follow the steps in this article and learn how to set up Always Encrypted for an Azure SQL database. Здесь вы научитесь:In this article you will learn how to perform the following tasks:

предварительным требованиямPrerequisites

Для работы с этим руководством вам потребуется:For this tutorial, you'll need:

Включение доступа клиентского приложения к службе базы данных SQLEnable your client application to access the SQL Database service

Необходимо включить доступ клиентского приложения к службе базы данных SQL. Для этого нужно настроить приложение Azure Active Directory (AAD) и скопировать идентификатор приложения и ключ, которые понадобятся для аутентификации приложения.You must enable your client application to access the SQL Database service by setting up an Azure Active Directory (AAD) application and copying the Application ID and key that you will need to authenticate your application.

Чтобы получить идентификатор приложения и ключ, ознакомьтесь с процедурой в разделе Создание приложения Azure Active Directory и субъекта-службы с доступом к ресурсам с помощью портала.To get the Application ID and key, follow the steps in create an Azure Active Directory application and service principal that can access resources.

Создание хранилища ключей для хранения ваших ключейCreate a key vault to store your keys

Теперь, когда клиентское приложение настроено и у вас есть идентификатор приложения, пора создать хранилище ключей и настроить его политику доступа таким образом, чтобы ваше приложение могло обращаться к секретам в хранилище (ключам Always Encrypted).Now that your client app is configured and you have your application ID, it's time to create a key vault and configure its access policy so you and your application can access the vault's secrets (the Always Encrypted keys). Для создания главного ключа столбца и настройки шифрования с помощью SQL Server Management Studio необходимы разрешения create, get, list, sign, verify, wrapKey и unwrapKey.The create, get, list, sign, verify, wrapKey, and unwrapKey permissions are required for creating a new column master key and for setting up encryption with SQL Server Management Studio.

Можно быстро создать хранилище ключей, выполнив следующий сценарий.You can quickly create a key vault by running the following script. Подробное описание этих команд и дополнительные сведения о создании и настройке хранилища ключей см. в разделе что такое Azure Key Vault?.For a detailed explanation of these commands and more information about creating and configuring a key vault, see What is Azure Key Vault?.

Важно!

Модуль PowerShell Azure Resource Manager (RM) по-прежнему поддерживается базой данных SQL Azure, но вся будущая разработка предназначена для модуля AZ. SQL.The PowerShell Azure Resource Manager (RM) module is still supported by Azure SQL Database, but all future development is for the Az.Sql module. Модуль AzureRM продолжит принимать исправления ошибок до 2020 декабря.The AzureRM module will continue to receive bug fixes until at least December 2020. Аргументы для команд в модуле AZ и в модулях AzureRm существенно идентичны.The arguments for the commands in the Az module and in the AzureRm modules are substantially identical. Дополнительные сведения о совместимости см. в разделе Введение в новый модуль Azure PowerShell AZ.For more about their compatibility, see Introducing the new Azure PowerShell Az module.

$subscriptionName = '<subscriptionName>'
$userPrincipalName = '<username@domain.com>'
$applicationId = '<applicationId from AAD application>'
$resourceGroupName = '<resourceGroupName>' # use the same resource group name when creating your SQL Database below
$location = '<datacenterLocation>'
$vaultName = '<vaultName>'

Connect-AzAccount
$subscriptionId = (Get-AzSubscription -SubscriptionName $subscriptionName).Id
Set-AzContext -SubscriptionId $subscriptionId

New-AzResourceGroup -Name $resourceGroupName -Location $location
New-AzKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroupName -Location $location

Set-AzKeyVaultAccessPolicy -VaultName $vaultName -ResourceGroupName $resourceGroupName -PermissionsToKeys create,get,wrapKey,unwrapKey,sign,verify,list -UserPrincipalName $userPrincipalName
Set-AzKeyVaultAccessPolicy  -VaultName $vaultName  -ResourceGroupName $resourceGroupName -ServicePrincipalName $applicationId -PermissionsToKeys get,wrapKey,unwrapKey,sign,verify,list

Создание пустой базы данных SQLCreate a blank SQL database

  1. Войдите на портале Azure.Sign in to the Azure portal.

  2. Выберите Создать ресурс > Базы данных > База данных SQL.Go to Create a resource > Databases > SQL Database.

  3. Создайте пустую базу данных Clinic на новом или имеющемся сервере.Create a Blank database named Clinic on a new or existing server. Подробные инструкции по созданию базы данных на портале Azure см. в статье Краткое руководство. Начало работы с базой данных SQL Azure.For detailed directions about how to create a database in the Azure portal, see Your first Azure SQL database.

    Создание пустой базы данных

Позже в этом руководстве вам потребуется строка подключения, поэтому после создания базы данных Clinic перейдите к ней и скопируйте ее строку подключения.You will need the connection string later in the tutorial, so after you create the database, browse to the new Clinic database and copy the connection string. Вы можете получить строку подключения в любое время, но проще будет скопировать ее на портале Azure.You can get the connection string at any time, but it's easy to copy it in the Azure portal.

  1. Выберите Базы данных SQL > Clinic > Показать строки подключения к базам данных.Go to SQL databases > Clinic > Show database connection strings.

  2. Скопируйте строку подключения для ADO.NET.Copy the connection string for ADO.NET.

    Копирование строки подключения

Подключение к базе данных с помощью SQL Server Management Studio.Connect to the database with SSMS

Нам нужно открыть среду SQL Server Management Studio и подключиться к серверу через базу данных Clinic.Open SSMS and connect to the server with the Clinic database.

  1. Откройте среду SSMS.Open SSMS. (Щелкните Подключиться > Ядро СУБД, чтобы открыть окно Соединение с сервером, если оно еще не открыто.)(Go to Connect > Database Engine to open the Connect to Server window if it isn't open.)

  2. Введите имя сервера и учетные данные.Enter your server name and credentials. Имя сервера можно найти в колонке базы данных SQL и в строке подключения, которую вы скопировали ранее.The server name can be found on the SQL database blade and in the connection string you copied earlier. Введите полное имя сервера, включая database.windows.net.Type the complete server name, including database.windows.net.

    Копирование строки подключения

Если откроется окно Новое правило брандмауэра , войдите в Azure, и SSMS создаст новое правило брандмауэра для вас.If the New Firewall Rule window opens, sign in to Azure and let SSMS create a new firewall rule for you.

Создание таблицыCreate a table

В этом разделе вы создадите таблицу для хранения данных пациентов.In this section, you will create a table to hold patient data. Изначально в ней будет отсутствовать шифрование — его вы настроите в следующем разделе.It's not initially encrypted--you will configure encryption in the next section.

  1. Разверните узел Базы данных.Expand Databases.
  2. Щелкните правой кнопкой мыши базу данных Clinic и выберите пункт Создать запрос.Right-click the Clinic database and click New Query.
  3. Вставьте следующий сценарий Transact-SQL в окно нового запроса и нажмите кнопку Выполнить .Paste the following Transact-SQL (T-SQL) into the new query window and Execute it.
CREATE TABLE [dbo].[Patients](
         [PatientId] [int] IDENTITY(1,1),
         [SSN] [char](11) NOT NULL,
         [FirstName] [nvarchar](50) NULL,
         [LastName] [nvarchar](50) NULL,
         [MiddleName] [nvarchar](50) NULL,
         [StreetAddress] [nvarchar](50) NULL,
         [City] [nvarchar](50) NULL,
         [ZipCode] [char](5) NULL,
         [State] [char](2) NULL,
         [BirthDate] [date] NOT NULL
         PRIMARY KEY CLUSTERED ([PatientId] ASC) ON [PRIMARY] );
GO

Шифрование столбцов (настройка Always Encrypted)Encrypt columns (configure Always Encrypted)

В SSMS есть мастер, с помощью которого можно легко настроить функцию Always Encrypted. Он позволяет настроить главный ключ столбца, ключ шифрования столбца и зашифрованные столбцы.SSMS provides a wizard that helps you easily configure Always Encrypted by setting up the column master key, column encryption key, and encrypted columns for you.

  1. Разверните узел Базы данных > Clinic > Таблицы.Expand Databases > Clinic > Tables.

  2. Щелкните правой кнопкой мыши таблицу Patients и выберите пункт Зашифровать столбцы, чтобы открыть мастер настройки Always Encrypted.Right-click the Patients table and select Encrypt Columns to open the Always Encrypted wizard:

    Шифрование столбцов…

Мастер настройки Always Encrypted содержит следующие разделы: Выбор столбца, Настройка главного ключа, Проверка и Сводка.The Always Encrypted wizard includes the following sections: Column Selection, Master Key Configuration, Validation, and Summary.

Выполните действия на странице Выбор столбцов.Column Selection

На странице Введение нажмите кнопку Далее, чтобы открыть страницу Выбор столбца.Click Next on the Introduction page to open the Column Selection page. На этой странице можно будет выбрать столбцы для шифрования, тип шифрования и используемый ключ шифрования столбца (CEK) .On this page, you will select which columns you want to encrypt, the type of encryption, and what column encryption key (CEK) to use.

Для каждого пациента необходимо зашифровать данные в столбцах SSN и BirthDate.Encrypt SSN and BirthDate information for each patient. Для столбца SSN будет использоваться детерминированное шифрование, которое поддерживает уточняющие запросы на соответствие условию, операции объединения и группировки,The SSN column will use deterministic encryption, which supports equality lookups, joins, and group by. а для столбца BirthDate — случайное шифрование, которое не поддерживает какие-либо операции.The BirthDate column will use randomized encryption, which does not support operations.

Задайте для параметра Тип шифрования столбца SSN значение Детерминированное, а для столбца BirthDate — Случайное.Set the Encryption Type for the SSN column to Deterministic and the BirthDate column to Randomized. Щелкните Далее.Click Next.

Шифрование столбцов…

Настройка главного ключаMaster Key Configuration

На странице Настройка главного ключа можно настроить CMK и выбрать поставщик хранилища ключей, в котором будет находиться CMK.The Master Key Configuration page is where you set up your CMK and select the key store provider where the CMK will be stored. В настоящее время CMK можно хранить в хранилище сертификатов Windows, хранилище ключей Azure или аппаратном модуле безопасности (HSM).Currently, you can store a CMK in the Windows certificate store, Azure Key Vault, or a hardware security module (HSM).

В этом руководстве показано, как сохранить ключи в хранилище ключей Azure.This tutorial shows how to store your keys in Azure Key Vault.

  1. Выберите Хранилище ключей Azure.Select Azure Key Vault.
  2. Из раскрывающегося списка выберите нужное хранилище ключей.Select the desired key vault from the drop-down list.
  3. Щелкните Далее.Click Next.

Настройка главного ключа

ПроверкаValidation

Можно зашифровать столбцы сейчас или сохранить сценарий PowerShell и выполнить его позже.You can encrypt the columns now or save a PowerShell script to run later. Для целей этого руководства выберите Перейти к завершению и нажмите кнопку Далее.For this tutorial, select Proceed to finish now and click Next.

summarySummary

Убедитесь, что все параметры настроены правильно, и нажмите кнопку Готово , чтобы завершить настройку Always Encrypted.Verify that the settings are all correct and click Finish to complete the setup for Always Encrypted.

summary

Проверка действий мастераVerify the wizard's actions

После завершения работы мастера для базы данных будет настроена функция Always Encrypted.After the wizard is finished, your database is set up for Always Encrypted. Мастер выполнил следующие действия:The wizard performed the following actions:

  • Создал главный ключ столбца и сохранил его в хранилище ключей Azure.Created a column master key and stored it in Azure Key Vault.
  • Создал ключ шифрования столбца и сохранил его в хранилище ключей Azure.Created a column encryption key and stored it in Azure Key Vault.
  • Настройка шифрования для выбранных столбцов.Configured the selected columns for encryption. Сейчас в таблице Patients нет данных, но как только они появятся, они будут зашифрованы в выбранных столбцах.The Patients table currently has no data, but any existing data in the selected columns is now encrypted.

Чтобы убедиться, что ключи в SSMS созданы, разверните узлы Clinic > Безопасность > Ключи Always Encrypted.You can verify the creation of the keys in SSMS by expanding Clinic > Security > Always Encrypted Keys.

Создание клиентского приложения, которое работает с зашифрованными даннымиCreate a client application that works with the encrypted data

Теперь, когда функция Always Encrypted настроена, мы можем создать приложение, которое выполняет c зашифрованными столбцами операции вставки и выборки.Now that Always Encrypted is set up, you can build an application that performs inserts and selects on the encrypted columns.

Важно!

При передаче открытого текста на сервер со столбцами Always Encrypted приложение должно использовать объекты SqlParameter .Your application must use SqlParameter objects when passing plaintext data to the server with Always Encrypted columns. Передача значений литералов без использования объектов SqlParameter приведет к возникновению исключения.Passing literal values without using SqlParameter objects will result in an exception.

  1. Откройте Visual Studio и создайте консольное приложение C# (Visual Studio 2015 и более ранней версии) или консольное приложение (.NET Framework) (Visual Studio 2017 и более поздней версии).Open Visual Studio and create a new C# Console Application (Visual Studio 2015 and earlier) or Console App (.NET Framework) (Visual Studio 2017 and later). Убедитесь, что для проекта используется платформа .NET Framework версии 4.6 или более поздней.Make sure your project is set to .NET Framework 4.6 or later.
  2. Укажите имя проекта AlwaysEncryptedConsoleApp и нажмите кнопку ОК.Name the project AlwaysEncryptedConsoleAKVApp and click OK.
  3. Установите следующие пакеты NuGet, выбрав Сервис > Диспетчер пакетов NuGet > Консоль диспетчера пакетов.Install the following NuGet packages by going to Tools > NuGet Package Manager > Package Manager Console.

Выполните следующие две строки кода в консоли диспетчера пакетов:Run these two lines of code in the Package Manager Console:

Install-Package Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider
Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory

Изменение строки подключения для активации функции постоянного шифрованияModify your connection string to enable Always Encrypted

В этом разделе объясняется, как включить функцию Always Encrypted в строке подключения к базе данных.This section explains how to enable Always Encrypted in your database connection string.

Чтобы включить функцию Always Encrypted, необходимо добавить ключевое слово Column Encryption Setting в строку подключения и задать для него значение Enabled.To enable Always Encrypted, you need to add the Column Encryption Setting keyword to your connection string and set it to Enabled.

Это можно задать непосредственно в строке подключения или с помощью SqlConnectionStringBuilder.You can set this directly in the connection string, or you can set it by using SqlConnectionStringBuilder. В разделе ниже показано, как использовать SqlConnectionStringBuilderдля примера приложения.The sample application in the next section shows how to use SqlConnectionStringBuilder.

Активация функции постоянного шифрования в строке подключенияEnable Always Encrypted in the connection string

Добавьте в строку подключения следующее ключевое слово.Add the following keyword to your connection string.

Column Encryption Setting=Enabled

Включение функции Always Encrypted с помощью SqlConnectionStringBuilderEnable Always Encrypted with SqlConnectionStringBuilder

В коде ниже показано, как активировать функцию Always Encrypted, указав параметр SqlConnectionStringBuilder.ColumnEncryptionSetting со значением Enabled.The following code shows how to enable Always Encrypted by setting SqlConnectionStringBuilder.ColumnEncryptionSetting to Enabled.

// Instantiate a SqlConnectionStringBuilder.
SqlConnectionStringBuilder connStringBuilder = new SqlConnectionStringBuilder("replace with your connection string");

// Enable Always Encrypted.
connStringBuilder.ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled;

Регистрация поставщика хранилища ключей AzureRegister the Azure Key Vault provider

В следующем коде показано, как зарегистрировать поставщик хранилища ключей Azure с помощью драйвера ADO.NET.The following code shows how to register the Azure Key Vault provider with the ADO.NET driver.

private static ClientCredential _clientCredential;

static void InitializeAzureKeyVaultProvider() {
    _clientCredential = new ClientCredential(applicationId, clientKey);

    SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider(GetToken);

    Dictionary<string, SqlColumnEncryptionKeyStoreProvider> providers = new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>();

    providers.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);
    SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);
}

Пример консольного приложения с функцией постоянного шифрованияAlways Encrypted sample console application

В этом примере показано, как:This sample demonstrates how to:

  • Изменить строку подключения для активации функции постоянного шифрования.Modify your connection string to enable Always Encrypted.
  • Зарегистрируйте хранилище ключей Azure в качестве поставщика хранилища ключей приложения.Register Azure Key Vault as the application's key store provider.
  • Вставить данные в зашифрованные столбцы.Insert data into the encrypted columns.
  • Выбрать запись, выполнив фильтрацию по конкретному значению в зашифрованном столбце.Select a record by filtering for a specific value in an encrypted column.

Замените содержимое файла Program.cs кодом, приведенным ниже.Replace the contents of Program.cs with the following code. Замените строку подключения для глобальной переменной connectionString, расположенную в строке прямо над методом Main, действительной строкой подключения с портала Azure.Replace the connection string for the global connectionString variable in the line that directly precedes the Main method with your valid connection string from the Azure portal. Это единственное изменение, которое необходимо внести в этот код.This is the only change you need to make to this code.

Запустите приложение, чтобы увидеть функцию Always Encrypted в действии.Run the app to see Always Encrypted in action.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider;

namespace AlwaysEncryptedConsoleAKVApp {
    class Program {
        // Update this line with your Clinic database connection string from the Azure portal.
        static string connectionString = @"<connection string from the portal>";
        static string applicationId = @"<application ID from your AAD application>";
        static string clientKey = "<key from your AAD application>";

        static void Main(string[] args) {
            InitializeAzureKeyVaultProvider();

            Console.WriteLine("Signed in as: " + _clientCredential.ClientId);

            Console.WriteLine("Original connection string copied from the Azure portal:");
            Console.WriteLine(connectionString);

            // Create a SqlConnectionStringBuilder.
            SqlConnectionStringBuilder connStringBuilder =
                new SqlConnectionStringBuilder(connectionString);

            // Enable Always Encrypted for the connection.
            // This is the only change specific to Always Encrypted
            connStringBuilder.ColumnEncryptionSetting =
                SqlConnectionColumnEncryptionSetting.Enabled;

            Console.WriteLine(Environment.NewLine + "Updated connection string with Always Encrypted enabled:");
            Console.WriteLine(connStringBuilder.ConnectionString);

            // Update the connection string with a password supplied at runtime.
            Console.WriteLine(Environment.NewLine + "Enter server password:");
            connStringBuilder.Password = Console.ReadLine();

            // Assign the updated connection string to our global variable.
            connectionString = connStringBuilder.ConnectionString;

            // Delete all records to restart this demo app.
            ResetPatientsTable();

            // Add sample data to the Patients table.
            Console.Write(Environment.NewLine + "Adding sample patient data to the database...");

            InsertPatient(new Patient() {
                SSN = "999-99-0001",
                FirstName = "Orlando",
                LastName = "Gee",
                BirthDate = DateTime.Parse("01/04/1964")
            });
            InsertPatient(new Patient() {
                SSN = "999-99-0002",
                FirstName = "Keith",
                LastName = "Harris",
                BirthDate = DateTime.Parse("06/20/1977")
            });
            InsertPatient(new Patient() {
                SSN = "999-99-0003",
                FirstName = "Donna",
                LastName = "Carreras",
                BirthDate = DateTime.Parse("02/09/1973")
            });
            InsertPatient(new Patient() {
                SSN = "999-99-0004",
                FirstName = "Janet",
                LastName = "Gates",
                BirthDate = DateTime.Parse("08/31/1985")
            });
            InsertPatient(new Patient() {
                SSN = "999-99-0005",
                FirstName = "Lucy",
                LastName = "Harrington",
                BirthDate = DateTime.Parse("05/06/1993")
            });

            // Fetch and display all patients.
            Console.WriteLine(Environment.NewLine + "All the records currently in the Patients table:");

            foreach (Patient patient in SelectAllPatients()) {
                Console.WriteLine(patient.FirstName + " " + patient.LastName + "\tSSN: " + patient.SSN + "\tBirthdate: " + patient.BirthDate);
            }

            // Get patients by SSN.
            Console.WriteLine(Environment.NewLine + "Now lets locate records by searching the encrypted SSN column.");

            string ssn;

            // This very simple validation only checks that the user entered 11 characters.
            // In production be sure to check all user input and use the best validation for your specific application.
            do {
                Console.WriteLine("Please enter a valid SSN (ex. 999-99-0003):");
                ssn = Console.ReadLine();
            } while (ssn.Length != 11);

            // The example allows duplicate SSN entries so we will return all records
            // that match the provided value and store the results in selectedPatients.
            Patient selectedPatient = SelectPatientBySSN(ssn);

            // Check if any records were returned and display our query results.
            if (selectedPatient != null) {
                Console.WriteLine("Patient found with SSN = " + ssn);
                Console.WriteLine(selectedPatient.FirstName + " " + selectedPatient.LastName + "\tSSN: "
                    + selectedPatient.SSN + "\tBirthdate: " + selectedPatient.BirthDate);
            }
            else {
                Console.WriteLine("No patients found with SSN = " + ssn);
            }

            Console.WriteLine("Press Enter to exit...");
            Console.ReadLine();
        }

        private static ClientCredential _clientCredential;

        static void InitializeAzureKeyVaultProvider() {
            _clientCredential = new ClientCredential(applicationId, clientKey);

            SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider =
              new SqlColumnEncryptionAzureKeyVaultProvider(GetToken);

            Dictionary<string, SqlColumnEncryptionKeyStoreProvider> providers =
              new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>();

            providers.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);
            SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);
        }

        public async static Task<string> GetToken(string authority, string resource, string scope) {
            var authContext = new AuthenticationContext(authority);
            AuthenticationResult result = await authContext.AcquireTokenAsync(resource, _clientCredential);

            if (result == null)
                throw new InvalidOperationException("Failed to obtain the access token");
            return result.AccessToken;
        }

        static int InsertPatient(Patient newPatient) {
            int returnValue = 0;

            string sqlCmdText = @"INSERT INTO [dbo].[Patients] ([SSN], [FirstName], [LastName], [BirthDate])
     VALUES (@SSN, @FirstName, @LastName, @BirthDate);";

            SqlCommand sqlCmd = new SqlCommand(sqlCmdText);

            SqlParameter paramSSN = new SqlParameter(@"@SSN", newPatient.SSN);
            paramSSN.DbType = DbType.AnsiStringFixedLength;
            paramSSN.Direction = ParameterDirection.Input;
            paramSSN.Size = 11;

            SqlParameter paramFirstName = new SqlParameter(@"@FirstName", newPatient.FirstName);
            paramFirstName.DbType = DbType.String;
            paramFirstName.Direction = ParameterDirection.Input;

            SqlParameter paramLastName = new SqlParameter(@"@LastName", newPatient.LastName);
            paramLastName.DbType = DbType.String;
            paramLastName.Direction = ParameterDirection.Input;

            SqlParameter paramBirthDate = new SqlParameter(@"@BirthDate", newPatient.BirthDate);
            paramBirthDate.SqlDbType = SqlDbType.Date;
            paramBirthDate.Direction = ParameterDirection.Input;

            sqlCmd.Parameters.Add(paramSSN);
            sqlCmd.Parameters.Add(paramFirstName);
            sqlCmd.Parameters.Add(paramLastName);
            sqlCmd.Parameters.Add(paramBirthDate);

            using (sqlCmd.Connection = new SqlConnection(connectionString)) {
                try {
                    sqlCmd.Connection.Open();
                    sqlCmd.ExecuteNonQuery();
                }
                catch (Exception ex) {
                    returnValue = 1;
                    Console.WriteLine("The following error was encountered: ");
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(Environment.NewLine + "Press Enter key to exit");
                    Console.ReadLine();
                    Environment.Exit(0);
                }
            }
            return returnValue;
        }


        static List<Patient> SelectAllPatients() {
            List<Patient> patients = new List<Patient>();

            SqlCommand sqlCmd = new SqlCommand(
              "SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients]",
                new SqlConnection(connectionString));

            using (sqlCmd.Connection = new SqlConnection(connectionString))

            using (sqlCmd.Connection = new SqlConnection(connectionString)) {
                try {
                    sqlCmd.Connection.Open();
                    SqlDataReader reader = sqlCmd.ExecuteReader();

                    if (reader.HasRows) {
                        while (reader.Read()) {
                            patients.Add(new Patient() {
                                SSN = reader[0].ToString(),
                                FirstName = reader[1].ToString(),
                                LastName = reader["LastName"].ToString(),
                                BirthDate = (DateTime)reader["BirthDate"]
                            });
                        }
                    }
                }
                catch (Exception ex) {
                    throw;
                }
            }

            return patients;
        }

        static Patient SelectPatientBySSN(string ssn) {
            Patient patient = new Patient();

            SqlCommand sqlCmd = new SqlCommand(
                "SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE [SSN]=@SSN",
                new SqlConnection(connectionString));

            SqlParameter paramSSN = new SqlParameter(@"@SSN", ssn);
            paramSSN.DbType = DbType.AnsiStringFixedLength;
            paramSSN.Direction = ParameterDirection.Input;
            paramSSN.Size = 11;

            sqlCmd.Parameters.Add(paramSSN);

            using (sqlCmd.Connection = new SqlConnection(connectionString)) {
                try {
                    sqlCmd.Connection.Open();
                    SqlDataReader reader = sqlCmd.ExecuteReader();

                    if (reader.HasRows) {
                        while (reader.Read()) {
                            patient = new Patient() {
                                SSN = reader[0].ToString(),
                                FirstName = reader[1].ToString(),
                                LastName = reader["LastName"].ToString(),
                                BirthDate = (DateTime)reader["BirthDate"]
                            };
                        }
                    }
                    else {
                        patient = null;
                    }
                }
                catch (Exception ex) {
                    throw;
                }
            }
            return patient;
        }

        // This method simply deletes all records in the Patients table to reset our demo.
        static int ResetPatientsTable() {
            int returnValue = 0;

            SqlCommand sqlCmd = new SqlCommand("DELETE FROM Patients");
            using (sqlCmd.Connection = new SqlConnection(connectionString)) {
                try {
                    sqlCmd.Connection.Open();
                    sqlCmd.ExecuteNonQuery();

                }
                catch (Exception ex) {
                    returnValue = 1;
                }
            }
            return returnValue;
        }
    }

    class Patient {
        public string SSN { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDate { get; set; }
    }
}

Как проверить, что данные шифруютсяVerify that the data is encrypted

Вы можете быстро проверить, действительно ли данные на сервере зашифрованы. Для этого можно запросить данные таблицы Patients с помощью SSMS (используя текущее подключение, где не задан параметр Column Encryption Setting).You can quickly check that the actual data on the server is encrypted by querying the Patients data with SSMS (using your current connection where Column Encryption Setting is not yet enabled).

Выполните следующий запрос к базе данных Clinic.Run the following query on the Clinic database.

SELECT FirstName, LastName, SSN, BirthDate FROM Patients;

Вы увидите, что в зашифрованных столбцах не содержатся данные в виде открытого текста.You can see that the encrypted columns do not contain any plaintext data.

Новое консольное приложение

Чтобы получить доступ к данным в виде открытого текста, сначала убедитесь, что пользователь имеет необходимые разрешения в Azure Key Vault: get, unwrapKey и verify.To use SSMS to access the plaintext data, you first need to ensure that the user has proper permissions to the Azure Key Vault: get, unwrapKey, and verify. Дополнительные сведения см. в статье Создание и хранение главных ключей столбцов (постоянное шифрование).For detailed information, see Create and Store Column Master Keys (Always Encrypted).

Затем во время подключения добавьте параметр Column Encryption Setting=enabled.Then add the Column Encryption Setting=enabled parameter during your connection.

  1. В обозревателе объектов SSMS щелкните сервер правой кнопкой мыши и выберите пункт Отключить.In SSMS, right-click your server in Object Explorer and choose Disconnect.

  2. Щелкните Подключиться > Ядро СУБД, чтобы открыть окно Соединение с сервером, и нажмите кнопку Параметры.Click Connect > Database Engine to open the Connect to Server window and click Options.

  3. Щелкните Дополнительные параметры соединения и введите Column Encryption Setting=enabled.Click Additional Connection Parameters and type Column Encryption Setting=enabled.

    Новое консольное приложение

  4. Выполните следующий запрос к базе данных Clinic.Run the following query on the Clinic database.

    SELECT FirstName, LastName, SSN, BirthDate FROM Patients;
    

    Теперь в зашифрованных столбцах отображаются незашифрованные данные.You can now see the plaintext data in the encrypted columns. Новое консольное приложениеNew console application

Дополнительная информацияNext steps

После создания базы данных с функцией Always Encrypted вы можете сделать следующее:After you create a database that uses Always Encrypted, you may want to do the following: