Using SQL Server 2016, Visual Studio 2017, and .Net 4.7.1 framework. I have a table (tJobs
) with a column called TRAN_NO
. It is an `nvarchar(11). I prepared the table with "Always Encrypted". Enabled the"Enable Parameterization" checkbox in SQL Server. Changed the SSMS connection and added "Column Encryption Setting=enabled".
After AE wizard finishes, I see the column is now encrypted in SSMS. I export the public and private key for AE and copy them to my dev PC. I open certificate manager and import those keys to the dev PC.
I run the following in SSMS and it successfully updates the TRAN_NO column:
Declare @Tran_No nvarchar(11) = 'A124000054A'
Update CCJOB
Set TRAN_NO = @TRAN_NO
Where Job_No = '235877'
SQL profiler sends encrypted data for the TRAN_NO field. This because I have added the encryption connection string variable and parameterization in the options. So in SSMS it works as intended (see below).
sp_executesql N'DECLARE @Tran_No AS NVARCHAR (11) = @p5c6c097b89b449d184469863f8e8685c;
UPDATE CCJOB SET TRAN_NO = @Tran_No WHERE Job_No = ''235877'';
',N'@p5c6c097b89b449d184469863f8e8685c nvarchar(11)',@p5c6c097b89b449d184469863f8e8685c=0x0157D68B171F2B325C21CF0914EEC4D4E7A91EBC90B61531E19413E3F5F514EDE58F827C5E983F56A1612E15BB817A5B65A8284D3FDE121F5B0C3F5BDC25CC68A3EB8AF52E3A0D212E0C41A0DE60B7BE77
So far so good.
I open .Net 2017 application that uses this table and set the connection string:
Data Source=IC-SQL5;Integrated Security=SSPI;Initial Catalog=IC_CC2; Column Encryption Setting=enabled;
When I run the application it successfully pulls the TRAN_NO field from the DB, unencrypts it, and displays it in my textbox. Awesome. I love it.
The last thing I need is to write back changes to the DB when textbox changes. Must do through code. (side note: it doesn't work using the datasource binding control either and throws errors when trying to generate the update command)
I run the following update command in code:
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()
This is the stored procedure on the server
ALTER PROCEDURE [dbo].[spUpdate_CCJob2]
@JobNo VARCHAR(6),
@TRAN_NO NVARCHAR(11)
AS
UPDATE CCJOB
SET TRAN_NO = @TRAN_NO
WHERE Job_No = @JobNo;
I get the following error:
Operand type clash: varchar is incompatible with nchar(11) encrypted with (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')
I tried this code using ADO.NET provider and SqlClient
provider and get the same error message. Does not seem to be a provider issue.
I tried changing TRAN_NO
to NChar
, changing the size of the column, and every other combination I can think of.
When I send the stored proc through my .Net app using a parameterized query it sends the Tran_No in plaintext, even though I have the connection string set up properly. The documentation clearly states the provider should encrypt the Tran_No field when sending to MSSQL? SQL profiler clearly shows TRAN_NO is not encrypted (see below).
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'
Why isn't the provider encrypting the TRAN_NO field before sending to SQL Server?