I am trying to store hashed password in sql express database. but I am not able to do that one.
Here is my code:
SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
byte[] encode = sha.ComputeHash(Encoding.ASCII.GetBytes(pass));
string cmd = "insert into tblLogin (username,password,email,state,active) values ('"+name+"',"+encode+",'"+email+"','"+state +"',"+ active + ")" ;
And in database I kept password as varbinary.
Here my problem is I am getting value of encode as System.Byte[] but not hashed value.
How can I do this, I tried to find and I am getting how to hash password but not how to store password.
Here my main problem is How can I construct Insert query and store Byte[] into database?
Save it as a varchar, not varbinary.
var provider = new SHA1CryptoServiceProvider(salt);
byte[] bytes = Encoding.UTF8.GetBytes(input);
string result = Convert.ToBase64String(provider.ComputeHash(bytes)); // store it
Related
This should be so simple but I've spent 4 hours fiddling with this code and I just can't seem to get it to work.
The PHP code works as follows (I didn't write it and I can't change it, so I'm stuck with it):
$password = hash('sha512', "HelloWorld1");
$salt = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true);
$hashed = hash('sha512', $password.$salt);
$hashed and $salt are stored in the DB as is. That means $salt is already hashed for later on.
I have no idea why they decided to hash everything but what's done is done.
In this case, the result is
Pswd: ab3e648d69a71b33d0420fc3bfc9e2e8e3ef2a300385ea26bc22057a84cd9a5c359bd15c4a0a552122309e58938ce310839cd9d2ecad5f294266015d823331dd
Salt: fb5a0f741db0be2439dc14662aae3fc68eb5e16b446385d3ddd319b862d5e2d4f50488a39487b27fdd8ff7b7b76420fc3ebef2bce9e082ac15c9f2d6fe7d87fc
Now the login code on the C# side just needs to match a plain text hashed password along with the already hashed salt.
string password = "HelloWorld1";
string storedSalt = "fb5a0f741db0be2439dc14662aae3fc68eb5e16b446385d3ddd319b862d5e2d4f50488a39487b27fdd8ff7b7b76420fc3ebef2bce9e082ac15c9f2d6fe7d87fc";
using(SHA512 shaManaged = new SHA512Managed())
{
byte[] hashPassword = shaManaged.ComputeHash(Encoding.UTF8.GetBytes(password));
string hashPasswordString = BitConverter.ToString(hashPassword).Replace("-", "");
byte[] finalHash = shaManaged.ComputeHash(Encoding.UTF8.GetBytes(hashPasswordString + storedSalt));
Debug.WriteLine("Calculated Hash Password: " + BitConverter.ToString(finalHash).Replace("-", ""));
}
Essentially the idea is to
Hash the plain text password first (same as with the PHP code).
Convert the byte array to a string that matches the PHP format of hashing.
Then hash the hashed password and previously hashed salt together.
The result is as follows:
Stored Hash Password: AB3E648D69A71B33D0420FC3BFC9E2E8E3EF2A300385EA26BC22057A84CD9A5C359BD15C4A0A552122309E58938CE310839CD9D2ECAD5F294266015D823331DD
Calculated Hash Password: 189ABBA71AAEDDE5C8154558B68D59500A72E64D5F3F3C07EFA94F0126571FBB68C6ADD105E0C029BABF30CADD8A6A6B6E4749075854461A88EE1CE545E84507
Hopefully someone can spot where I'm going wrong :)
You have to tweak your code a little bit. Note the ToLowerInvariant(). C# returns upper case letters as string. As you see in your original code $salt and $password are returned with lower case letters, so your self calculated password hash hashPasswordString must also be lower case before concatenating with your storedSalt to gain the correct finalHash. Your shown expected result again uses upper case letters (maybe before stored it was converted in PHP?) so you don't need ToLowerCaseInvariant() on your final hash string.
Here is the code:
string password = "HelloWorld1";
string storedSalt = "fb5a0f741db0be2439dc14662aae3fc68eb5e16b446385d3ddd319b862d5e2d4f50488a39487b27fdd8ff7b7b76420fc3ebef2bce9e082ac15c9f2d6fe7d87fc";
using (SHA512 shaManaged = new SHA512Managed())
{
byte[] hashPassword = shaManaged.ComputeHash(Encoding.UTF8.GetBytes(password));
string hashPasswordString = BitConverter.ToString(hashPassword).Replace("-", "").ToLowerInvariant(); // Note the ToLowerInvariant();
byte[] finalHash = shaManaged.ComputeHash(Encoding.UTF8.GetBytes(hashPasswordString + storedSalt));
return BitConverter.ToString(finalHash).Replace("-", "");
}
This question already has answers here:
How can I unhash a hash using C#?
(4 answers)
Closed 8 years ago.
I have this asp.net project that I need to hash the password (preferably with salt) and save it in sql database then unhash it for comparing with the login password or sth like that....
the thing is I'm not sure what is the best way to do it in a most secure way and how can I code this in C#?
You do not unhash. That's the point of hashing: it cannot be reversed.
You look up the salt, then you hash the password that they entered together with the salt. If the hash is the same as the hash in the database, it's a valid login.
Maybe take a look here:
Salted password hashing
First of all you cannot recover the hashed data. Its one way process. But you can match hashed data. To do so check the code given below :
Do this inside your button click event
string salt = GetSalt(10); // 10 is the size of Salt
string hashedPass = HashPassword(salt, Password.Text);
This are the functions that will help your to hash the password
const string alphanumeric = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
public static string GetSalt(int saltSize)
{
Random r = new Random();
StringBuilder strB = new StringBuilder("");
while ((saltSize--) > 0)
strB.Append(alphanumeric[(int)(r.NextDouble() * alphanumeric.Length)]);
return strB.ToString();
}
public static string HashPassword(string salt, string password)
{
string mergedPass = string.Concat(salt, password);
return EncryptUsingMD5(mergedPass);
}
public static string EncryptUsingMD5(string inputStr)
{
using (MD5 md5Hash = MD5.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(inputStr));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
sBuilder.Append(data[i].ToString("x2"));
// Return the hexadecimal string.
return sBuilder.ToString();
}
}
Similarly, when you try to match the password to authenticate the user, perform the same method just fetch your hashed password from your database and compare them. If the entered hashed password matches the database hashed password, its an authorized user.
Updated :
When you hash the password of the user for the first time and then store into database in the same table store the salt for that user.
Next time when you try to compare the password, fetch that salt of the user from the database and hash it using to compare with the
hashed password in the database.
Hope that answers your Question.
I have a sha512 password hash that is generated by a nodejs web server, which for some reason c# isn't interpreting it correctly.
The hash in the db is:
09d5c4cfdf9449bba5c8f36f6feba141e91467d2602388930f2b4ec36939e60c3d81f6aec07ebdcab74c67d7c99e516521b5565e09ea547d66dc460a80b06b4e
The hash that C# consoles out is:
09d5c4cfdf9449bba5c8f36f6feba141e91467d2602388930f2b4ec36939e60c3d81f6aec07ebdcab74c67d7c99e516521b5565e09ea547d66dc460a80b06băć
As you can see the last two characters are non utf8.
MySQL stores the hash in a utf8_general_ci table. Here is the snippet of code which queries for the information.
I read somewhere that c# string is utf16 by default, and i'd guess thats the problem, how can i fix this?
C Sharp
Command.CommandText = string.Format( "SELECT username, password FROM {0} WHERE state='{1}'", DatabaseTable, ( int )Status.Pending );
OdbcDataReader reader = Command.ExecuteReader( );
QueryCount += 1;
while( reader.Read() ){
string username = reader.GetString(0);
string password = reader.GetString(1);
Console.WriteLine("Password from DB Is: {0}", password);
I am using hashed passwords with a salt (the username).
Problem is that the hashed values of c# are not equal to the initial values I add to the database by a TSQL Script.
TSQL:
UPDATE [Users]
SET Password = HASHBYTES('SHA2_256', 'test123'+UPPER([UserName]))
GO;
C#:
var passBytes = new UnicodeEncoding().GetBytes(pass);
var saltBytes = new UnicodeEncoding().GetBytes(userName.ToUpper());
var dataToHash = new byte[passBytes.Length + saltBytes.Length];
Array.Copy(passBytes, dataToHash, passBytes.Length);
Array.Copy(saltBytes, dataToHash, saltBytes.Length);
var sha = new SHA256Managed();
return sha.ComputeHash(dataToHash);
I guess it has something to do with the encoding.
But i have no idea how to fix this.
UserName is varchar(50)
The DB is an existing one so changing the varchar will not be so easy.
I already tried:
UPDATE [Users]
SET Password = HASHBYTES('SHA2_256', N'test123'+UPPER([UserName]))
GO;
After struggling to get this to work, here is a sample of what I finally got to work:
public string Hash(string input)
{
using (SHA256 hasher = SHA256.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = hasher.ComputeHash(Encoding.Unicode.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("X2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
}
TSQL
declare #input as nvarchar(max) = 'Test';
select #input;
declare #hash as varbinary(max) = HASHBYTES('SHA2_256', #input );
select #hash;
declare #result as nvarchar(max) = CONVERT(NVARCHAR(MAX), #hash, 2);
select #result;
These will produce identical results.
Note that this is using a nvarchar datatype, not a varchar.
If your SQL Server database is configured to use the default collation of SQL_Latin1_General_CP1_CI_AS, then in your C# code, use code page 1252 to convert characters to bytes. Thus, the equivalent of
HASHBYTES('SHA2_256', 'test123' + UPPER([UserName]))
is
byte[] data = Encoding.GetEncoding(1252).GetBytes("test123" + userName.ToUpper());
var sha = new SHA256Managed();
byte[] hash = sha.ComputeHash(data);
Hashes work on bytes, not on characters. What you're doing is Hash(StringToBytes(str)). Your StringToBytes step is different. In SQL you are using ANSI varchar strings and in C# UTF-16 strings. Decide which one you want and use that. I recommend Unicode (nvarchar).
Encoding.UTF8.GetBytes(input) = HASHBYTES('SHA2_256', #varcharVariable);
Encoding.Unicode.GetBytes(input) = HASHBYTES('SHA2_256', #nvarcharVariable);
I have created a web form in c# that accepts username and password and stores password in MSSQL 2005 db in 'image' format. The password is merged with salt, encoded in UTF8 and lastly it is applied with a SHA512 encryption. I want to be able to see the passwords in string format when I pull them up back from the database. How should my decrypt function be, if the following is how I encrypted the password? Is that possible? :
string loginID = "";//This will be stored in varchar format in MSSQL..(Unrelated to the question)
string password =""; //This is where I store password inputted by user.
Random r = new Random();
int salt = r.Next((int)Math.Pow(2, 16));
int verifyCode = r.Next((int)Math.Pow(2, 16));
string tmpPwd = password.ToLower() + salt.ToString();
UTF8Encoding textConverter = new UTF8Encoding();
byte[] passBytes = textConverter.GetBytes(tmpPwd);
byte[] hashedPWD = new SHA512Managed().ComputeHash(passBytes);
The value in hashedPWD is stored in MSSQL as image datatype and salt is stored as int.
You can't - that's what a hash function is, by definition - a one-way function. Up until the last line, you can get the password back, but after the hash function, all you can do is generate a second hash and compare the two to see if they've produced the same result, in which case you can presume that the source strings were the same.