【发布时间】:2019-11-25 19:29:14
【问题描述】:
使用 SQL Server 2016、Visual Studio 2017 和 .Net 4.7.1 框架。我有一个表 (tJobs),其中有一列名为 TRAN_NO。它是一个`nvarchar(11)。我准备了“始终加密”的表格。启用 SQL Server 中的“启用参数化”复选框。更改了 SSMS 连接并添加了“Column Encryption Setting=enabled”。
AE 向导完成后,我看到列现在已在 SSMS 中加密。我导出 AE 的公钥和私钥并将它们复制到我的开发 PC。我打开证书管理器并将这些密钥导入开发 PC。
我在 SSMS 中运行以下命令,它成功更新了 TRAN_NO 列:
Declare @Tran_No nvarchar(11) = 'A124000054A'
Update CCJOB
Set TRAN_NO = @TRAN_NO
Where Job_No = '235877'
SQL 探查器为 TRAN_NO 字段发送加密数据。这是因为我在选项中添加了加密连接字符串变量和参数化。所以在 SSMS 中它按预期工作(见下文)。
sp_executesql N'DECLARE @Tran_No AS NVARCHAR (11) = @p5c6c097b89b449d184469863f8e8685c;
更新 CCJOB SET TRAN_NO = @Tran_No WHERE Job_No = ''235877'';
”,N '@ p5c6c097b89b449d184469863f8e8685c nvarchar的(11)',@ p5c6c097b89b449d184469863f8e8685c = 0x0157D68B171F2B325C21CF0914EEC4D4E7A91EBC90B61531E19413E3F5F514EDE58F827C5E983F56A1612E15BB817A5B65A8284D3FDE121F5B0C3F5BDC25CC68A3EB8AF52E3A0D212E0C41A0DE60B7BE77 P>
到目前为止一切顺利。
我打开使用此表的 .Net 2017 应用程序并设置连接字符串:
Data Source=IC-SQL5;Integrated Security=SSPI;Initial Catalog=IC_CC2; Column Encryption Setting=enabled;
当我运行应用程序时,它成功地从数据库中提取 TRAN_NO 字段,对其进行解密,并将其显示在我的文本框中。惊人的。我喜欢它。
我需要做的最后一件事是在文本框更改时将更改写回数据库。必须通过代码完成。 (旁注:使用数据源绑定控件也不起作用,并在尝试生成更新命令时抛出错误)
我在代码中运行以下更新命令:
Dim sStr As String = "Data Source=IC-SQL5;Integrated Security=SSPI;Initial Catalog=IC_CC2; Column Encryption Setting=enabled"
Dim oCN As New SqlClient.SqlConnection(sStr)
Dim oCom As New SqlClient.SqlCommand("spUpdate_CCJOB2", oCN)
oCom.CommandType = CommandType.StoredProcedure
oCN.Open()
oCom.Parameters.AddWithValue("@JOBNO", "235877")
Dim param3 = oCom.CreateParameter()
param3.ParameterName = "@TRAN_NO"
param3.DbType = SqlDbType.NVarChar = 11
param3.Direction = ParameterDirection.Input
param3.Value = "987654321"
oCom.Parameters.Add(param3)
oCom.ExecuteNonQuery()
这是服务器上的存储过程
ALTER PROCEDURE [dbo].[spUpdate_CCJob2]
@JobNo VARCHAR(6),
@TRAN_NO NVARCHAR(11)
AS
UPDATE CCJOB
SET TRAN_NO = @TRAN_NO
WHERE Job_No = @JobNo;
我收到以下错误:
操作数类型冲突:varchar 与使用 (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK_Auto1', column_encryption_key_database_name = 'IC_CC2') 加密的 nchar(11) 不兼容
我使用 ADO.NET 提供程序和 SqlClient 提供程序尝试了此代码,并得到了相同的错误消息。似乎不是提供商问题。
我尝试将TRAN_NO 更改为NChar,更改列的大小,以及我能想到的所有其他组合。
当我使用参数化查询通过我的 .Net 应用程序发送存储过程时,即使我正确设置了连接字符串,它也会以纯文本形式发送 Tran_No。文档明确指出提供者在发送到 MSSQL 时应该加密 Tran_No 字段? SQL 分析器清楚地显示 TRAN_NO 未加密(见下文)。
exec sp_describe_parameter_encryption N'EXEC [spUpdate_CCJOB2] @JOBNO=@JOBNO, @TRAN_NO=@TRAN_NO',N'@JOBNO varchar(6),@TRAN_NO varchar(11)' exec spUpdate_CCJOB2 @JOBNO='235877',@TRAN_NO='A124000054A'
为什么提供程序在发送到 SQL Server 之前不加密 TRAN_NO 字段?
【问题讨论】:
-
看看这个页面:docs.microsoft.com/en-us/sql/relational-databases/security/… 我想它会回答你的一些问题。 TL;DR - 不要使用 .AddWithValue。
-
感谢您的信息。我在这方面找不到任何有助于我的情况的东西。我确实删除了 AddWithValue 并创建了一个参数。没有更改错误消息。
-
您是否查看了标题为
Errors due to passing plaintext instead of encrypted values的部分...因为其中描述的错误似乎正是您面临的问题。 -
是的,但是,给出的示例是如何不发送查询。我正在使用参数来发送查询。我读到的是,提供者在传递给存储过程之前获取明文值并加密数据。我编辑了我的帖子以显示 SSMS 确实加密了该字段,但 .Net 代码不加密该字段。我确定我错过了一些东西,但看不到它。谢谢