I want to crypt a string with C# in the same way as sql server does.
Crypting '12345' with sql server with
DECLARE #string nvarchar(510) = '12345';
SELECT CAST(HASHBYTES('SHA2_512',#string) AS NVARCHAR(510)) AS CryptString;
it outputs: ₜ䇨鏟⠚㐶�᧺绯飴춊띕ோ讓㎎譌㬇⩮絙ぉ寷褂敠⮅ᙫ﹫덞ۏ赸.
If I try anything in C# I recieve only alphanumeric chars.
Any ideas on how to get the same output?
Related
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.
I'm trying to move authentication from the stored procedure to EF. The SQL itself is returning 2 results. How should I validate them?
The value is to be checked against the value stored in the table
ECC2065575DCBF977CD923996C598C3DC481404E
SQL syntax:
Declare #Password AS NVARCHAR(256) = 'Quest_2016'
DECLARE #PasswordSalt AS NVARCHAR(5) = 'LCY''n'
DECLARE #PasswordWithSalt AS NVARCHAR(261) = #Password + #PasswordSalt
print #PasswordWithSalt
result:1 Quest_2016LCY'n
print HASHBYTES(N'SHA1', #PasswordWithSalt )
result 2: 0xECC2065575DCBF977CD923996C598C3DC481404E-----
print HASHBYTES(N'SHA1', 'Quest_2016LCY''n')
result 3: 0x5E85AB2ED11CDB696BC0544131D7C8571F4F8FA8-----
Also just what how this can be implemented in C#
sql hashbytes
The problem with those two queries is that the string values are the same but the bytes are not.
The first query
print HASHBYTES(N'SHA1', #PasswordWithSalt )
uses unicode encoding to get the bytes so every character is 2 bytes (0x510075006500730074005F0032003000310036004C004300590027006E00).
The second query
print HASHBYTES(N'SHA1', 'Quest_2016LCY''n')
uses ASCII so that every character is one byte.
To have the same result in the second example prefix the String with N'. It will tell SQL server that this is a unicode string
print HASHBYTES(N'SHA1', N'Quest_2016LCY''n')
produces the hash 0xECC2065575DCBF977CD923996C598C3DC481404E
In C# you can also use SHA1 to get the hash of the string and here also you need to be specific about the byte encoding
byte[] data = Encoding.Unicode.GetBytes(#"Quest_2016LCY'n");
byte[] hash = SHA1.Create().ComputeHash(data);
Console.Write(hash.Select(x=>x.ToString("X2")).Aggregate((x,y)=>x+y));
prints ECC2065575DCBF977CD923996C598C3DC481404E but if you change Encoding.Unicode to Encoding.ASCII it gives the 5E85AB2ED11CDB696BC0544131D7C8571F4F8FA8.
We have the following scenario: process is to return string with Greek letters using an Oracle stored procedure on output.
Oracle function (example) is :
FUNCTION GREEKLATINSTRING (a_latin_name IN VARCHAR2) RETURN VARCHAR2
IS
BEGIN RETURN 'ΣΤΡΟΒΟΛΟΣ/123/ABC'; END;
This function is called from within a T-SQL stored procedure (please assume all connections are 100% as we have other procedures executing w/o issues)
TSQL stored procedure is :
CREATE PROCEDURE [dbo].[GreekLatinString] #NameLatin NVARCHAR(100)
AS
DECLARE #output NVARCHAR(100);
DECLARE #SQL NVARCHAR(MAX);
BEGIN
SET #SQL = N'BEGIN ? := LINKED_SERVER.DB_INSTANCE.GREEKLATINSTRING(?); END;';
EXECUTE(#SQL,
#output OUTPUT ,
#NameGr ) --1Params
AT MYORACLE;
SELECT cast (#output as nvarchar)
END
And C# code is nothing special - simply getting data back:
dbCommand = CreateCommand();
dbCommand.Transaction = ModelContext.CurrentDBUtils.Transaction;
dbCommand.CommandText = "GreekLatinString";
dbCommand.CommandType = CommandType.StoredProcedure;
SqlParameter param0 = new SqlParameter("NameLatin", nameLatin);
param0.Direction = ParameterDirection.Input;
dbCommand.Parameters.Add(param0);
using (SqlDataAdapter adapter = new SqlDataAdapter(dbCommand as SqlCommand))
{
adapter.Fill(dataset);
}
SQL Server instance collation is SQL_Latin1_General_CP1253_CI_AS AND Oracle NLS_LANG is al32utf8
Problem is that whenever function is executed directly in Oracle it returns value as it should, however whenever we call is from C# from inside of SQL Server stored procedure the output in the dataset is always ????????
Can anybody suggest what might be the reason for that?
Not really an answer, but got too long for a comment:
When the character set of an Oracle database and Oracle client are different Oracle will perform translation of character data in both directions. If the target character set does not support a source character Oracle will substitute something valid. In many single byte character sets that something is ?, in Unicode character sets u+FFFD, REPLACEMENT CHARACTER, is used.
Note that the client character set is is not fixed for a client machine, but can be set at the connection level.
In this case then:
Character data is sourced in the Oracle database character set. This character data includes Greek letters.
The character data is sent to the Oracle client used by SQL Server's linked DB connection. If the client character set and database character set differ, translation will occur.
From the Oracle client the character data may travel through other software layers. (For example OLE DB.)
The character data is taken into SQL Server.
The character data is displayed. The Greek letters have become question marks.
My guess is that the Oracle client character set at step 2 is a single byte character set that does not support Greek letters and that at this step the characters are translated to question marks. This is where I would begin an investigation. Again, the client character set is not set for the machine so one can't start up SQLPlus on the SQL Server machine and say, "Works, problem not in the Oracle client character set." since SQLPlus may be using something different from SQL Server.
Once you have verified that the Oracle client character set is suitable and if you still have a problem, you'll have to figure out how to work forward. I don't have any guidance to offer. Maybe write a simple client application against the same OLE DB drivers you are using. I'm not sure.
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.
I am using C# to parse a chat log and insert messages into a database.
When trying to insert the string "Don't worry, it's unloaded"
(with the double quotes) it gives me the following exception:
System.Data.Odbc.OdbcException: ERROR [HY000] [MySQL][ODBC 5.1 Driver][mysqld-5.5.11]Incorrect string value: '\xEF\xBB\xBF it...' for column 'msg' at row 1
at void System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode)
The database is using latin-1 default collation for the encoding scheme.
I have tried switching to utf-8 but this gave me the error on the same line.
Not sure what it means to your specific error, but EF BB BF is the UTF BOM character which could be causing an issue.
This answer pointed out that the client connection needs to be set to the proper character set as well. It could be that the C# client character isn't matching the MySQL encoding.
Depending on your chosen way to insert data (I assume by building the SQL directly), the ' character needs to be escaped. That's because ' is string delimiting character in most databases.
What you need to insert is "Don''t worry, it''s unloaded", with the single quotes escaped by doubling them.
!Important: You need to be careful about raw using raw SQL as it can easily create security holes that can SQL injection. Use parametrized queries whenever possible or fully escape the query sent to the server.
Don't forget that if you're constructing the SQL statement (don't! -- use a parameterized query instead), if the construct winds up looking like:
insert foo ( bar ) values( "This is my data" )
The insert will fail because the double quote introduces a quoted column name. It is not the same as a string literal which is quoted with the apostrophe (').
User SQL Parameters instead of using raw sql. There can be SQL Injection security issue and these sort of issues.
See how to use sql parameters mysql-c#
Eg:
MySqlCommand mySqlCommand1;
...
mySqlCommand1.CommandText = "INSERT INTO dept (deptno, dname, desc) VALUES (?, ?, ?)";
mySqlCommand1.Parameters.Add("param1", 30);
mySqlCommand1.Parameters.Add("param2", "SALES");
mySqlCommand1.Parameters.Add("param3", #"Don''t worry, it''s unloaded");