Параметризация (всегда зашифрованная) - внутри хранимой процедуры - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть сценарий, в котором мне нужно иметь литералы (жестко закодированные строки) внутри proc, используемые для столбцов «Always Encrypted», так как это завершается ошибкой со следующей ошибкой,

Столкновение с типом операнда: varchar несовместим с nvarchar (20) зашифровано с помощью (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK_Auto4', column_encryption_key_database_name = 'DBName')

Я пытаюсь выполнить параметризацию для Always Encrypted в сохраненном процессе, аналогично приведенному ниже

GO
    CREATE PROCEDURE InsertProc  
    @Var1 nVarchar(20)  
    As  
    BEGIN     
        DECLARE @Plaintext nvarchar(20)='testText' 

        INSERT INTO testClass(EncryptedCol1,EncryptedCol2,NonEncryptedCol)
        VALUES (@Plaintext,@Var1,default)
    END

Я также включил параметризацию и также включил настройку шифрования столбца для соединения. По-прежнему появляется следующая ошибка при создании процедуры,

Процедура sp_describe_parameter_encryption, строка 1 [Стартовая строка запуска 4] Заявление (я) не может быть подготовлено. Ошибка произошла во время выполнение партии. Сообщение об ошибке: Внутренняя ошибка. Метаданные для параметр '@ p3467a2cdc3d547a3be48f46dfc7e9580' в заявлении или процедура <- мой код процедуры здесь -> 'отсутствует в наборе результатов, возвращаемых sp_describe_parameter_encryption.

ПРИМЕЧАНИЕ: я все еще мог бы выполнить и вставить, если я вручную запустил скрипт, который находится внутри proc.Но проблема с созданием Proc

Может кто-нибудь помочь исправить или предоставить альтернативное решение.

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Я нашел способ использования жестко закодированных строк в процедурах.

  1. Создайте таблицу со столбцом nVarchar (Примечание: зашифрованный nvarchar не совместим с зашифрованным varchar. Кроме того, вы не можете назначить значение с большей длиной данных для зашифрованных значений с меньшей длиной данных (например, вы не можете назначить зашифрованную переменную / столбец nVarchar (max) для зашифрованного столбца nVarchar (20)). Поэтому выберите меньший размер, насколько это возможно.)
  2. Зашифруйте столбец с тем же типом шифрования и ключом, что и у рассматриваемого столбца.
  3. Теперь вы можете использовать значение из таблицы для вставки, обновления, сравнения и т. Д. операции. Вы также можете использовать такие функции, как coalesce, isnull и т. Д.

Пример:

Создать таблицу с зашифрованным столбцом

CREATE TABLE [dbo].[Encrypted_nVarchar_256](
    [SNo] [smallint] IDENTITY(-32768,1) NOT NULL,
    [EncryptValue] [nvarchar](256) COLLATE Latin1_General_BIN2 
ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK_key], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
        [Value_Description] [nvarchar](256) NULL,
     CONSTRAINT [Pk_Enc_nVar_256] PRIMARY KEY CLUSTERED 
    (
        [SNo] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

Вставьте текст в зашифрованный столбец значение, которое вы хотели бы использовать в процедурах.

DECLARE @EncryptValue  nvarchar(256) ='';
INSERT INTO Encrypted_nVarchar_256(EncryptValue,[Value_Description]) VALUES(@EncryptValue,'Empty string')
DECLARE @EncryptValue1  nvarchar(256) ='Some string you would like to hard code';
INSERT INTO Encrypted_nVarchar_256(EncryptValue,[Value_Description]) VALUES(@EncryptValue1,'Your description')
--more rows as you need
GO

Теперь вы можете потреблять в хранимой процедуре

 CREATE PROCEDURE InsertProc  
    @Var1 nVarchar(20)  
    As  
    BEGIN    
        --Passing hard coded ''(Empty string) as insert value
        INSERT INTO testTable(EncryptedCol1,EncryptedCol2,NonEncryptedCol)
        SELECT TOP 1 EncryptValue,@Var1,"some string" FROM Encrypted_nVarchar_256 where Sno=-32768
        --Comparing some hard coded string
        SELECT * from  testTable
        where EncryptedCol1=(SELECT TOP 1 EncryptValue FROM Encrypted_nVarchar_256 
 where Sno=-32768)
         --Using in functions
         SELECT COALESCE(EncryptedCol1,(SELECT TOP 1 EncryptValue FROM Encrypted_nVarchar_256  where Sno=-32768)) as [new col name] from  testable

    END

Вуаля !!! теперь вы можете сделать что-нибудь с небольшим поворотом.

0 голосов
/ 02 ноября 2018

Основная цель Always Encrypted - сделать так, чтобы SQL Server (а следовательно, ваши администраторы баз данных) не могли расшифровать ваши конфиденциальные данные. Для этого SQL Server абсолютно не имеет доступа к своим ключам шифрования и не может шифровать и дешифровать данные. Все шифрование и дешифрование выполняется клиентом (вашим приложением, SSMS и т. Д.). Включить параметрирование для Always Encrypted - это функция SSMS. Когда он включен (и вы указываете параметр шифрования столбца = Включено для вашего соединения), SSMS обнаружит объявленные переменные в вашем скрипте, преобразует его в параметризованный запрос и выполняет его преобразованную версию. Таким образом, значения параметров будут зашифрованы на клиенте, и SQL Server вообще не увидит их значения в виде простого текста.

В вашем примере @Plaintext - это не переменная, объявленная в вашем скрипте, а локальная переменная для хранимой процедуры. Таким образом, этот код (присвоение значения) будет выполняться в самом движке SQL Server, и поскольку он не имеет доступа к ключам шифрования, просто невозможно зашифровать значение. Поэтому вам нужно переместить это как входной параметр для процедуры сохранения. В этом случае будет заманчиво присвоить ему значение по умолчанию и опустить его при вызове процедуры, но значением по умолчанию является то, что хранится в метаданных, и оно является простым (не зашифрованным). Кто-то должен зашифровать это, и единственный, кто может сделать это, является клиентом. Следовательно, вам нужно передать его от клиента и не делать его значением по умолчанию, то есть невозможно использовать «жестко запрограммированные значения» на сервере.

Если это является серьезным препятствием для вас, вероятно, Always Encrypted - не та технология, которая подходит для вашего случая. Если вы используете, скажем, шифрование на уровне столбцов с сертификатами, вы сможете делать все эти вещи. Но это сводит на нет главное преимущество Always Encrypted - неспособность вашего администратора баз данных получить доступ к вашим секретам.

...