参数化(始终加密)- 内部存储过程
Parameterization(Always Encrypted)- Inside stored proc
我有一个场景,我需要在 proc 中使用文字(硬编码字符串)来对付 "Always Encrypted" 列,因为这失败并出现以下错误,
Operand type clash: varchar is incompatible with nvarchar(20)
encrypted with (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
我还为连接启用了参数化和列加密设置。创建过程时仍然出现以下错误,
Procedure sp_describe_parameter_encryption, Line 1 [Batch Start Line
4] Statement(s) could not be prepared. An error occurred while
executing batch. Error message is: Internal error. Metadata for
parameter '@p3467a2cdc3d547a3be48f46dfc7e9580' in statement or
procedure<--my proc code here--> ' is missing in resultset returned by
sp_describe_parameter_encryption.
注意:如果我手动 运行 proc.But Proc 创建中的脚本是问题
,我仍然可以执行和插入
有人可以帮助修复或提供替代解决方案。
Always Encrypted 的主要目的是让 SQL 服务器(因此您的 DBA)无法解密您的敏感数据。为此,SQL 服务器绝对无法访问 加密密钥,并且无法加密和解密数据。所有加密和解密都由客户端(您的应用程序、SSMS 等)执行。为 Always Encrypted 启用参数化是 SSMS 的一项功能。启用后(并且您为连接指定 Column Encryption Setting=Enabled),SSMS 将检测脚本中声明的变量,将其转换为参数化查询并执行转换后的版本。这样,参数值将在客户端加密,SQL 服务器根本看不到它们的纯文本值。
在您的示例中,@Plaintext 不是在您的脚本中声明的变量,而是存储过程的局部变量。所以这段代码(值的分配)将在 SQL 服务器引擎本身中执行,并且由于它无法访问加密密钥,因此根本不可能加密该值。因此,您也需要将其作为存储过程的输入参数移动。在这种情况下,很容易给它一个默认值并在调用过程时忽略它,但默认值是存储在元数据中的东西并且是明文的(未加密)。必须有人对其进行加密,而唯一能做到这一点的就是客户端。因此,您需要从客户端传递它而不是将其设为默认值,即不可能在服务器中使用“硬编码值”。
如果这对您来说是一个主要障碍,Always Encrypted 可能不适合您的情况。如果您使用带有证书的列级加密,您将能够完成所有这些事情。但这破坏了 Always Encrypted 的主要优势——您的 DBA 无法访问您的秘密。
我找到了在过程中使用硬编码字符串的解决方法。
- 创建一个带有 nVarchar 列的 table(注意:加密的 nvarchar 不是 compatable 与加密的 varchar,而且您不能将较高数据长度的值分配给较低数据长度的加密值(例如,您无法将 nVarchar(max) 的加密 variable/column 分配给 nVarchar(20) 的加密列。因此请尽可能选择较小的大小。)
- 使用与正在考虑的列相同的加密类型和密钥对该列进行加密。
- 现在您可以使用 table 中的值来插入、更新、比较等。操作。您还可以在 coalesce 、 isnull 等函数中使用。
示例:
使用加密列
创建 table
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
瞧!!!现在只要稍作改动,您就可以做任何事情。
我有一个场景,我需要在 proc 中使用文字(硬编码字符串)来对付 "Always Encrypted" 列,因为这失败并出现以下错误,
Operand type clash: varchar is incompatible with nvarchar(20) encrypted with (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
我还为连接启用了参数化和列加密设置。创建过程时仍然出现以下错误,
Procedure sp_describe_parameter_encryption, Line 1 [Batch Start Line 4] Statement(s) could not be prepared. An error occurred while executing batch. Error message is: Internal error. Metadata for parameter '@p3467a2cdc3d547a3be48f46dfc7e9580' in statement or procedure<--my proc code here--> ' is missing in resultset returned by sp_describe_parameter_encryption.
注意:如果我手动 运行 proc.But Proc 创建中的脚本是问题
,我仍然可以执行和插入有人可以帮助修复或提供替代解决方案。
Always Encrypted 的主要目的是让 SQL 服务器(因此您的 DBA)无法解密您的敏感数据。为此,SQL 服务器绝对无法访问 加密密钥,并且无法加密和解密数据。所有加密和解密都由客户端(您的应用程序、SSMS 等)执行。为 Always Encrypted 启用参数化是 SSMS 的一项功能。启用后(并且您为连接指定 Column Encryption Setting=Enabled),SSMS 将检测脚本中声明的变量,将其转换为参数化查询并执行转换后的版本。这样,参数值将在客户端加密,SQL 服务器根本看不到它们的纯文本值。
在您的示例中,@Plaintext 不是在您的脚本中声明的变量,而是存储过程的局部变量。所以这段代码(值的分配)将在 SQL 服务器引擎本身中执行,并且由于它无法访问加密密钥,因此根本不可能加密该值。因此,您也需要将其作为存储过程的输入参数移动。在这种情况下,很容易给它一个默认值并在调用过程时忽略它,但默认值是存储在元数据中的东西并且是明文的(未加密)。必须有人对其进行加密,而唯一能做到这一点的就是客户端。因此,您需要从客户端传递它而不是将其设为默认值,即不可能在服务器中使用“硬编码值”。
如果这对您来说是一个主要障碍,Always Encrypted 可能不适合您的情况。如果您使用带有证书的列级加密,您将能够完成所有这些事情。但这破坏了 Always Encrypted 的主要优势——您的 DBA 无法访问您的秘密。
我找到了在过程中使用硬编码字符串的解决方法。
- 创建一个带有 nVarchar 列的 table(注意:加密的 nvarchar 不是 compatable 与加密的 varchar,而且您不能将较高数据长度的值分配给较低数据长度的加密值(例如,您无法将 nVarchar(max) 的加密 variable/column 分配给 nVarchar(20) 的加密列。因此请尽可能选择较小的大小。)
- 使用与正在考虑的列相同的加密类型和密钥对该列进行加密。
- 现在您可以使用 table 中的值来插入、更新、比较等。操作。您还可以在 coalesce 、 isnull 等函数中使用。
示例:
使用加密列
创建 tableCREATE 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
瞧!!!现在只要稍作改动,您就可以做任何事情。