SQL Server Always encrypt collation incompatibility on insert - c#

I have a Windows Forms application that has been working for a long time as is and now I have to encrypt/decrypt some columns in the database. I made all the configurations on my database, configured my columns to be encrypted, changed column's datatype to nvarchar(max) from varchar(max), created a certificate on Windows store, exported the cert for the client and now I am trying to do the job on client side.
I changed windows form application framework to 4.6, added Column Encryption Setting=enabled to my connection string, updated the .dbml designer but I still get the following error when trying to insert a value:
Operand type clash: varchar(8000) 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 = 'MCM_V2') collation_name = 'Greek_CI_AS' is incompatible with varchar(50) 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 = 'mydb') collation_name = 'Greek_BIN2'
I am using Linq for queries

You seem to be using non-BIN2 collation. Always Encrypted currently only supports BIN2 collations.
From official documentation:
Always Encrypted is not supported for the columns with the below
characteristics (e.g. the Encrypted WITH clause cannot be used in
CREATE TABLE/ALTER TABLE for a column, if any of the following
conditions apply to the column):
...
String (varchar, char, etc.)
columns with non-bin2 collations

Related

How to query data when columns are encrypted in SQL Server 2016

I've been trying to find solution in this problem. I encrypted my columns from my database in SQL Server 2016 . In order to read the data I already set the parameters "Column Encryption Setting=Enabled"; I know I don't have problem in my certificate because I was able to query like SELECT * FROM TABLE, but I wasn't able to query using a WHERE condition. For example
"SELECT column FROM Table WHERE column='abc'" something like that.
The Error is:
"Operand type clash: varchar is incompatible with varchar(8000)
encrypted with (encryption_type = 'DETERMINISTIC',... and so on"
I don't know why I can't retrieve the data from the encrypted column.
I assume you have encrypted your column using the Always Encrypted feature of SQL Server.
With Always Encrypted SQL Server does not know the keys for encrypting and decrypting your data. It's the job of your client application to encrypt data before sending it to SQL Server.
When you execute this query:
SELECT column FROM Table WHERE column='abc'
you are asking SQL Server to compare the non-encrypted varchar 'abc' to the encrypted values found in your encrypted column. This will fail - as you've noted yourself.
Your client application must encrypt the value you want to use in your WHERE clause before sending it off to SQL Server.
If you're using SSMS you can do this by enabling parameterization for always encrypted. You can enable this in SSMS under Query>>Query options>>Execution>>Advanced>>Enable Parameterization for Always Encrypted.
Once this is enabled you'll be able to filter your table like this:
DECLARE #MyValue VARCHAR(100) = 'abc';
SELECT [Column] FROM [Table] WHERE [Column] = #MyValue;
What happens behind the scenes is that SSMS encrypts the value of the #MyValue parameter for you before sending it off to SQL Server. It is important that you declare and initialize the parameter at once. Otherwise SSMS is unable to encrypt the value before sending the query to SQL Server.
You can read more about parameterization for always encrypted here. Feel free to comment below if the above explanation is unclear to you.
You need to use DECRYPTBYKEY
SELECT *
FROM Table WHERE convert(varchar,DecryptByKey(column))='abc'
The way you use this function depends on if you are using symmetric keys and a hash, or just a key, etc.

Update/Insert rows in SQL table with encrypted columns using LinqToSQL - Always Encrypt

I am trying to get a hands-on on Always Encrypt feature of SQL Server 2016. I am using an existing application and database to do this.
I have a table [User], where i have encrypted the 'Password' column with 'Deterministic' type. I have made the connection string changes and I am able to retrieve all the rows. I have created the repository for this table.
I am trying to insert and update rows in this table with LinqToSQL using InsertOnSubmit() and SubmitChanges().
But whenever I try to insert new rows or update existing rows, I get the error:
Msg 206, Level 16, State 2, Line 7 Operand type clash: varchar is
incompatible with varchar(20) 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 = 'BRO_UAT')
collation_name = 'Latin1_General_BIN2'
I have read articles where using Stored Procs and parameterization has solved the issue. But, as I mentioned earlier, this is an existing project, and I have used LinqToSql and do not want to change the code. Insertion/Update works fine if the column is not encrypted!
Am I missing some setting?Please point me towards the right direction.
Change your column to nvarchar and check.
Also now even storing the password is not the best approach, store a signature instead and validate that signature when validating the password.
Check the link for the same.
https://social.msdn.microsoft.com/Forums/en-US/77bb69f0-590e-40f5-b5e9-714bf590e008/how-to-handle-encrypted-column?forum=linqtosql

SQL encryption only returning first character

I have the following query
UPDATE mytable
SET col1 = ENCRYPTBYPASSPHRASE ('Key', col2)
FROM mytable
when I decrypt it using
SELECT CONVERT(VARCHAR(20), DECRYPTBYPASSPHRASE ('Key', col1))
FROM mytable
The result returned is only the first character, for example if the field contains "Computer" the result is only "C".
col2 is probably nvarchar not varchar. Try
SELECT CONVERT(NVARCHAR(20), DECRYPTBYPASSPHRASE ('Key', col1))
FROM mytable
In nvarchar the code points for standard ASCII letters are the same as for ASCII but padded out with a 0x00 byte.
When you cast that to varchar that it is treated as a null character that terminates the string.
After investigation I had come to many issues so I will post what I came across, so anyone can benefit from it.
If you changed to data type of the SQL column to varbinary then make sure that when you decrypt the data, you use the same old data type. That is if you had a column of varchar that contains data and then you changed it to varbinary, you must decrypt it using varchar, if you use nvarchar ,you will get garbage data.
You must encrypt and decrypt using the same way. That is if you are loading the password from a stored procedure and use it in encrypting,and the SAME EXACT password is loaded using a function for decryption, u will also get garbage data (I tested it but I did not know why is this behaviour!)may be internally there is some difference between how data is returned from SP and functions.
Hope this helps anyone out there !
Use CONVERT with data type and size of the value you are encrypting updating.
Looks like EncryptByKey does not recognize the data properly as per column schema.
Try as below
ENCRYPTBYKEY(KEY_GUID('<Key Name>'), CONVERT(varchar(20),col1))

Why generated MD5 hash in sql server are not equal? [duplicate]

This question already has answers here:
TSQL md5 hash different to C# .NET md5
(4 answers)
Closed 8 years ago.
I have a table in SQL Server 2008 R2 that contain two field (WordHash, Word). This Hash field generated in C# and I need regenerate hash code for Word field in sql server.
But my problem is that generated MD5 hash in sql server and C# are different. I found below code to resolve this problem but still I have same problem.
SQL code:
CONVERT(NVARCHAR(32),HASHBYTES('MD5', 'some word'), 2)
After putting this code block to my query, I saw some wired result! This is my result:
My Query:
SELECT
[WordHash],
convert(nvarchar(32),HASHBYTES('MD5', 'Analytics'),2) AS TestHash,
convert(nvarchar(32),HASHBYTES('MD5', [Word]),2) AS SqlHash
FROM myTable
Result:
WordHash: A768CAA988605A2846599CF7E2D0C26A
TestHash: A768CAA988605A2846599CF7E2D0C26A
SqlHash F4AFA5FEF805F7F5163EC6402BAF61FF
Note that the 'Analytics' is one of records data in database.
Why TestHash & SqlHash are different while they generated from same code!?
The issue is NVARCHAR and VARCHAR get hashed to different values. Both HASHBYTES('MD5', 'Analytics'), and [WordHash] are hashes of VARCHAR values but [Word] is a NVARCHAR.
select HASHBYTES('MD5', 'Analytics'), 'varchar'
union
select HASHBYTES('MD5', N'Analytics'), 'nvarchar'
--outputs
------------------------------------- --------
0xA768CAA988605A2846599CF7E2D0C26A varchar
0xF4AFA5FEF805F7F5163EC6402BAF61FF nvarchar
To fix this you must either change [Word] to be VARCHAR or re-compute [WordHash] using NVARCHAR values.
Some useful further reading: Comparing SQL Server HASHBYTES function and .Net hashing

Encrypt in SQL server and read/decrpyt client-side

Ive written in sql :
CREATE SYMMETRIC KEY SecureSymmetricKey
WITH ALGORITHM = TRIPLE_DES
ENCRYPTION BY PASSWORD = 'StrongPassword';
DECLARE #str NVARCHAR(1000)
SET #str = 'lala';
OPEN SYMMETRIC KEY SecureSymmetricKey
DECRYPTION BY PASSWORD = 'StrongPassword';
DECLARE #encrypted_str VARBINARY(MAX)
SET #encrypted_str =
EncryptByKey(Key_GUID('SecureSymmetricKey'), #str);
the encrypted_str value is in a table now.
how can i read it in c# ? ( and decrypt in c# )
You don't "decrypt" it in C#. Decrypt it in the select statement on the way back out.
You need to encrypt and decrypt at the same layer of your application stack; if you encrypt at the SQL Server layer, you need to decrypt before returning the data to your application.
If you want to decrypt it in the C# application, you need to encrypt it there first, and store the encrypted values in the database.

Categories

Resources