We are currently using **HMACSHA512** in .net, with a **128Char (64byte) validation key**
The **salt is 64 char randomly generated** string.
We allocated 2048 length on the database for the hashed base64 string result.
It will be a public facing website.
**Is this approach reasonable** or should it be changed to another approach such as Rfc2898DeriveBytes?

```
 public string HashEncode(string password, string salt, string validationKey) {
        byte[] hashKey = BosUtilites.HexStringToByteArray(validationKey);
        var sha512 = new HMACSHA512(hashKey);
        var hashInput = BosUtilites.StringToByteArray(password + salt);
        byte[] hash = sha512.ComputeHash(hashInput);
        return Convert.ToBase64String(hash);
    }

 public string GenerateSimpleSalt(int Size = 64) {
        var alphaSet = new char[64]; // use 62 for strict alpha... that random generator for alphas only
        //nicer results with set length * int i = 256. But still produces excellent random results.
        //alphaset plus 2.  Reduce to 62 if alpha requried
        alphaSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890#=".ToCharArray();
        var tempSB = GenerateRandomString(Size, alphaSet);
        return tempSB.ToString();
    }

    public StringBuilder GenerateRandomString(int Size, char[] alphaSet) {
        using (var crypto = new RNGCryptoServiceProvider()) {
            var bytes = new byte[Size];
            crypto.GetBytes(bytes); //get a bucket of very random bytes
            var tempSB = new StringBuilder(Size);
            foreach (var b in bytes) { // use b , a random from 0-255 as the index to our source array. Just mod on length set
                tempSB.Append(alphaSet[b%(alphaSet.Length)]);
            }

            return tempSB;
        }

```

**EDIT2: In case Someone finds this via google, I have included the lessons learnt**
Average sample in tests on workstations was around 300 msecs. This should not be too noticeable during logon. And no more need for a Validation key. Which is a relief :-)

```
 SCrypt package installed via nuget. and rfc2898 PBKDF2 changed to be large number or iterations but only 20bytes output.  SAme CPU time.

```

New passwords are encoded in SCRYPT by default,

```
  <package id="CryptSharpOfficial" version="2.0.0.0" targetFramework="net451" />
  // save salt, hash algorithm used and resulting encoding on user record
  public string PasswordEncode(string password, byte[] salt, HashAlgorithm hashAlgorithm ) {
        switch (hashAlgorithm) {
            case HashAlgorithm.PBKDF2:
                    var deriver2898 = new Rfc2898DeriveBytes(password, salt,<Use a number around 50K>); // approx 300msecs on workstation
                    byte[] hash = deriver2898.GetBytes(20); // 
                    return Convert.ToBase64String(hash);
            case HashAlgorithm.Scrypt:
                var key = Encoding.UTF8.GetBytes(password);
                byte[] hashScrypt =  SCrypt.ComputeDerivedKey(key: key, salt: salt, 
                                    cost: 65536, // must be a power of 2 !, on PC, singlethread this is approx 1 sec
                                    blockSize: 8, 
                                    parallel: 1,
                                    maxThreads: 1, 
                                    derivedKeyLength: 128);

                    return Convert.ToBase64String(hashScrypt);
            default:
                throw new ArgumentOutOfRangeException("hashAlgorithm");
        }
    }

```

\*\*EDIT 3: Latest Library Bcrypt.Net-Next 4.x  

This Bcrypt library offers an up to date solution to the hashing process. For more details see why we selected bcrypt.  

[Do any security experts recommend bcrypt for password storage?](https://security.stackexchange.com/questions/4781/do-any-security-experts-recommend-bcrypt-for-password-storage)