Update SHA256 hashing into SQL Server Database in C# - c#

I want to hash the user password in SQL Server from C#, I followed the instruction as found in http://www.codeproject.com/Articles/608860/Understanding-and-Implementing-Password-Hashing link and I created the user table with three columns
UserID NVarchar(250)
UserPassword NVarchar(MAX)
UserSalt NVarchar(50).
It works fine when I insert user and can log in correctly, but when I update the UserPassword and UserSalt, then I can not log in with the updated user, saying the UserPassword and UserSalt are incorrect.
Any advise to follow?

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.

Login Form Authentication C#

I create a stored procedure name sp_Auth and inside it is
Table name UserAccounts with two fields, username and password both varchar(50)
I declared two variables, #username,#password on stored procedure
Select * From UserAccounts where #username = username and #password = password
After I create it I put it into Linq to SQL together with the table and then I create new class to call the stored procedure from the linq to sql class.
My question is how do I make a method in order for the button in my login form to check or validate username and password typed in the textboxes to the data found on the table using my stored procedure.
I know there are a lot of ways on doing this but I found out they uses sqlcommand or something.
I need to use the class to call the stored proc.
The code I want to achieve is like this
Public static sp_Insert(Product p)
db = new dataclass1context();
db.storedprocInsert(#Name,#Pname);
Can I create a validator or checker in the class like the code above?
Take a look at Passing parameter to stored procedure. This will get you on the way. You can use the result of the query to determine if the user was validated.
Please keep in mind that passwords should not be stored as plaintext, and should be at least hashed and even salted, which would require you to convert the users password to the matching type of hash before your query.

ASP.NET MVC 5 - GeneratePasswordResetToken with custom user table

I have a table 'user' with the following fields:
id
username
password
salt
folder_files
active
The password is obtained using Rfc2898DeriveBytes. I would like to allow the user to change his password. I read the this guide:
http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-web-app-with-email-confirmation-and-password-reset
I would like to use the GeneratePasswordResetToken. How can I use this method (and therefore also ASP.NET Identity) with che 'user' table (also maintaing the use of Rfc2898DeriveBytes for password hasing)? Can I avoid using the AspNetUsers table?
Unfortunately, that's not possible. However, the AspNetUsers is customizable, as the Password Hasher.

Convert string to varbinary - Comparing the two

I need to covert a string to a varbinary(85), which is the data type in my SQL Server Table (unable to change). The data is for a username and I need to compare the windows user name of a person who logs onto a website with this SQL data entry. An example of a login that I have in my database is:
0x0105000000000005150000004CCDD8292B55E7A8CD006C0E061F0012 which is the of the datatype varbinary(85).
Now I need to compare this to a string. What is the best way for me to convert a string to varbinary(85) so that I can get the exact same value.
I would preferably do this all in C# although I guess I could do it on the database end in SQL.
ANSWER:
using sql I could generate the name perfectly.
SELECT SUSER_SID(string)
1) I would create an [unique] index on varbinary(85) column:
CREATE UNIQUE INDEX IUN_Users_UserName
ON dbo.Users (UserName) -- Where UserName is varbinary(85)
2) I would convert current user name to varbinary(85) using the same algorithm
DECLARE #binCurrentUserName VARBINARY(85);
SET #binCurrentUserName = .... convert here the current user name to VB(85) ...
and I would compare only varbinary values:
SELECT u.UserID
FROM dbo.Users u
WHERE u.UserName = #binCurrentUserName -- Please remember that UserName's type is VB(85)
Note: converting the varbinary values from UserName column to string (nvarchar) it's a bad idea because the SQL query will look like this
SELECT u.UserID
FROM dbo.Users u
WHERE CONVERT(... u.UserName ... ) = #nvarcharCurrentUserName
and because will be a function (ex. CONVERT) applied on UserName column this will block Index Seek => the execution plan of this query will contain an Index Scan operator.

Get application username for Audit table

I want to implement an audit table and I have no idea how am I supposed to get the username.
I am using C# and Sql Server. I have a Users table in my database. When I log in my windows form application I verify if the correct combination of username and password is used. But how do I inform the database of the current user? I thought of adding an extra column to my Users table in which to set on 1 the logged username. Is that a solution for single-user? But my application in supposed to support multi-user. What could be done in this case?
Depending on your authentication scheme, you need to get the the User name.
for thick client applications,
Environment.Username
and
System.Security.Principal.WindowsIdentity.GetCurrent()
are a couple of options.
typically for audit tables, there is a column called 'ModifiedByUser' where you can log the user name provided by the win form app.
create the nvarchar and datetime columns (if not already) in your audit table.
one will stored the user name and the other the datetime of the audit action.
in your code, whenever you want to add an entry to the audit table, get Environment.Username or System.Security.Principal.WindowsIdentity.GetCurrent(), along with DateTime.UtcNow and pass it on to be saved to the DB into the Audit table.
SQL Server knows who you are. You can simply use SUSER_SNAME() or/and ORIGINAL_LOGIN() function as a default value for the username column in your audit table. Same for the time of audit event, use GetDate() function. There is no need to send this information from the client.
This is a very open-ended question but I think I understand what you are trying to do. You have application-specfic users that are defined in a Users table (as opposed to using database users or active directory users) and you need to log specific information for auditing purposes or drive security based off of the logins. Is that correct?
This can be done, but the logic for it will need to be written in your application.
Let’s pretend we are writing a program to send out an invoice to a customer.
I used role based security where you can give users access to do specific tasks by granting them a role. For example, “Create New Invoice” could be a role. I usually have 2 tables for this:
SecuirtyRoleDefintion
SecurityRoleUsers
The fist table, Security Role Definition will have an ID column, the Description (“Create New Invoice”), and I usually have a Audit column to indicate if this action needs to be logged for Audit.
The second table, SecurityRoleUsers, is where I define if a user has permission to execute that role. Columns are usually something like this: a unique ID, User ID (foreign key to the Users table), RoleID (foreign key to SecurityRoleDefintion)
Now in your application we need a class to check if a user has a role. It needs to take in the role ID (or name) and the user ID. Example: public bool IsUserAuthorized(int RoleID, int UserID)
This method can run a query on your SecurityRoleUsers table to see if the user is in the table for that role. If so, it returns true. If not, it returns false.
Now back in the application when user click the “Create New Invoice” button it runs the IsUserAuthorized() method to check if a user can perform the operation.
If creating an audit log is necessary, you could do something similar. After the security check is done for “Create New Invoice” you can check to see if the Role needs to be audit logged, if so then write to an Audit table.
DECLARE #username varchar(128)
SET #username = CONVERT(VarChar(128), CONTEXT_INFO());
PRINT #username
DECLARE #ID_User int
SET #ID_User = ( SELECT Users.ID_User
FROM Users
WHERE Users.Username=#username )
PRINT #ID_User
This is how I solved it. I inserted this piece of code in each update trigger.

Categories

Resources