【问题标题】:Cannot Insert into SQL Server AlwaysEncrypted Table with Linq无法使用 Linq 插入 SQL Server AlwaysEncrypted 表
【发布时间】:2018-01-15 01:08:16
【问题描述】:

我绝对不会想到这一点,所以请,欢迎任何建议。

我正在运行带有两个加密表的 SQL Server 2016:

hr_client

[id] [int] IDENTITY(1,1) NOT NULL,
[employee_id] [nvarchar](20) NULL,
[honorific] [nvarchar](20) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[first_name] [nvarchar](60) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[last_name] [nvarchar](60) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[gender] [char](1) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[date_of_birth] [date] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[national_insurance] [nvarchar](9) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[start_date] [date] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[end_date] [date] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[position] [int] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[department] [int] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[manager] [nvarchar](20) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[grade] [nvarchar](20) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[salary] [decimal](10, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[status] [int] NULL,
[modify_date] [datetime] NULL,
[user_modify] [nvarchar](20) NULL,
[active] [bit] NULL,
[type] [nvarchar](20) NULL

hr_grade

[id] [int] IDENTITY(1,1) NOT NULL,
[grade_id] [nvarchar](20) NULL,
[description] [nvarchar](30) NULL,
[min_rate] [decimal](10, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[max_rate] [decimal](10, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[overtime_1] [decimal](5, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[overtime_2] [decimal](5, 2) ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [EXAMPLE_KEY_NAME], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
[modify_date] [datetime] NULL,
[user_modify] [varchar](20) NULL,
[comments] [varchar](max) NULL,
[status] [int] NULL,
[active] [bit] NULL,
[type] [nvarchar](20) NULL,
[position] [int] NULL,

我已经设置了 Column Master 和 Column Encryption Keys(当前存储在 SQL Server 上)。我还设置了存储过程以从这两个表中插入和选择数据。数据按预期加密,可以使用存储过程插入和返回数据(在 SSMS 中都可以正常工作)。

为了访问数据,我创建了一个运行在我们内部 IIS Web 服务器上的 ASP MVC 应用程序。该应用程序的目标是 4.6.1,我使用 LinqToSql dbml 进行 SQL 连接和命令。连接字符串如下:

Data Source=EXAMPLE_IP;Column Encryption Setting=enabled;Initial Catalog=hr;Persist Security Info=True;User ID=EXAMPLE_USER;

数据可以毫无问题地插入到 hr_grade 表中并从中选择。

但是我只能从 hr_client 表中选择,并且 INSERT(直接或通过存储过程)因以下错误而失败:

Operand type clash: 
nvarchar(4000) encrypted with (
    encryption_type = 'RANDOMIZED', 
    encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', 
    column_encryption_key_name = 'EXAMPLE_KEY_NAME', 
    column_encryption_key_database_name = 'hr'
) is incompatible with nvarchar(20) encrypted with (
    encryption_type = 'RANDOMIZED', 
    encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', 
    column_encryption_key_name = 'EXAMPLE_KEY_NAME', 
    column_encryption_key_database_name = 'hr')

现在我能看到的唯一明显区别是 hr_client 表有 NVARCHAR 列,我的应用程序似乎不喜欢这些列。

有什么想法/建议吗?

【问题讨论】:

  • I 可以看到的唯一明显区别是 NVARCHAR(4000) 与 NVARCHAR(20)。不会尝试重现您的设置,请理解。
  • 嗯,是的,这很明显,但我没有在任何地方声明 NVARCHAR(4000)。对数据库字段的每次调用都使用各自的字段类型和参数

标签: c# asp.net sql-server linq always-encrypted


【解决方案1】:

您应该使用分析器进行验证,但我怀疑 Linq2SQL 正在声明一个 nvarchar(4000) 类型的参数以插入到 nvarchar(20) 列中。使用客户端加密时,SqlParameter 类型和长度必须与目标列匹配,因为 SQL Server 无法对值执行任何服务器端转换。

您可能必须直接使用 EF 或 ADO.NET。

【讨论】:

  • 我很担心,我更愿意在 Linq 中解决这个问题,因为它更容易使用。谢谢你的建议,我去看看profiler
  • EF 6 确实不比 L2S 难。
  • 抱歉,我不是一般的意思,我只是针对我,因为我已经习惯了 Linq
  • 您完全正确,Linq 会自动将字符串值分配给它们的(软)最大大小的 nvarchar(4000)。通常这不是问题,但由于 AlwaysEncrypted 执行加密客户端,因此无法进行隐式转换。感觉像是一种解决方法,但我已将我的字段修改为 nvarchar(4000) 并且现在可以正常工作
  • 我刚刚测试过,客户端没有将密文填充到全长,因此将列声明为 nvarchar(20) 和 nvarchar(4000) 之间没有真正的成本差异。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
  • 2013-01-11
相关资源
最近更新 更多