I was just going through one of DavidHayden\'s articles on Hashing User Passwords.
Really I can\'t get what he is trying to achieve.
Here is his code:
<create proc [dbo].[hash_pass] @family nvarchar(50), @username nvarchar(50), @pass nvarchar(Max),``` @semat nvarchar(50), @tell nvarchar(50)
as insert into tbl_karbar values (@family,@username,(select HASHBYTES('SHA1' ,@pass)),@semat,@tell)
I read all answers and I think those enough, specially @Michael articles with slow hashing and @CodesInChaos good comments, but I decided to share my code snippet for hashing/validating that may be useful and it does not require [Microsoft.AspNet.Cryptography.KeyDerivation].
private static bool SlowEquals(byte[] a, byte[] b)
{
uint diff = (uint)a.Length ^ (uint)b.Length;
for (int i = 0; i < a.Length && i < b.Length; i++)
diff |= (uint)(a[i] ^ b[i]);
return diff == 0;
}
private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
{
Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt);
pbkdf2.IterationCount = iterations;
return pbkdf2.GetBytes(outputBytes);
}
private static string CreateHash(string value, int salt_bytes, int hash_bytes, int pbkdf2_iterations)
{
// Generate a random salt
RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
byte[] salt = new byte[salt_bytes];
csprng.GetBytes(salt);
// Hash the value and encode the parameters
byte[] hash = PBKDF2(value, salt, pbkdf2_iterations, hash_bytes);
//You need to return the salt value too for the validation process
return Convert.ToBase64String(hash) + ":" +
Convert.ToBase64String(hash);
}
private static bool ValidateHash(string pureVal, string saltVal, string hashVal, int pbkdf2_iterations)
{
try
{
byte[] salt = Convert.FromBase64String(saltVal);
byte[] hash = Convert.FromBase64String(hashVal);
byte[] testHash = PBKDF2(pureVal, salt, pbkdf2_iterations, hash.Length);
return SlowEquals(hash, testHash);
}
catch (Exception ex)
{
return false;
}
}
Please pay attention SlowEquals function that is so important, Finally, I hope this help and Please don't hesitate to advise me about better approaches.
I created a class that has the following method:
Create Salt
Hash Input
Validate input
public class CryptographyProcessor
{
public string CreateSalt(int size)
{
//Generate a cryptographic random number.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
public string GenerateHash(string input, string salt)
{
byte[] bytes = Encoding.UTF8.GetBytes(input + salt);
SHA256Managed sHA256ManagedString = new SHA256Managed();
byte[] hash = sHA256ManagedString.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
public bool AreEqual(string plainTextInput, string hashedInput, string salt)
{
string newHashedPin = GenerateHash(plainTextInput, salt);
return newHashedPin.Equals(hashedInput);
}
}
Use the System.Web.Helpers.Crypto
NuGet package from Microsoft. It automatically adds salt to the hash.
You hash a password like this: var hash = Crypto.HashPassword("foo");
You verify a password like this: var verified = Crypto.VerifyHashedPassword(hash, "foo");
In answer to this part of the original question "Is there any other C# method for hashing passwords" You can achieve this using ASP.NET Identity v3.0 https://www.nuget.org/packages/Microsoft.AspNet.Identity.EntityFramework/3.0.0-rc1-final
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using System.Security.Principal;
namespace HashTest{
class Program
{
static void Main(string[] args)
{
WindowsIdentity wi = WindowsIdentity.GetCurrent();
var ph = new PasswordHasher<WindowsIdentity>();
Console.WriteLine(ph.HashPassword(wi,"test"));
Console.WriteLine(ph.VerifyHashedPassword(wi,"AQAAAAEAACcQAAAAEA5S5X7dmbx/NzTk6ixCX+bi8zbKqBUjBhID3Dg1teh+TRZMkAy3CZC5yIfbLqwk2A==","test"));
}
}
}
Bah, this is better! http://sourceforge.net/projects/pwdtknet/ and it is better because ..... it performs Key Stretching AND uses HMACSHA512 :)