Actualmente estamos utilizando HMACSHA512 en .net, con una clave de validación 128Char (64bytes) La sal es de 64 caracteres generados aleatoriamente cadena. Asignamos 2048 de longitud en la base de datos para el resultado de la cadena hash base64. Será un sitio web público. ¿Es razonable este enfoque o debería cambiarse a otro enfoque como 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: en caso de que alguien encuentre esto a través de google, he incluido las lecciones aprendidas El promedio de muestra en las pruebas en estaciones de trabajo fue de alrededor de 300 ms. Esto no debe ser demasiado notable durante el inicio de sesión. Y ya no hay necesidad de una clave de validación. Que es un alivio :-)
SCrypt package installed via nuget. and rfc2898 PBKDF2 changed to be large number or iterations but only 20bytes output. SAme CPU time.
Las contraseñas nuevas están codificadas en SCRYPT de forma predeterminada,
<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");
}
}