Une fois que j'ai généré un salt et haché le mot de passe (en utilisant bcrypt, etc) serait-il préférable de stocker les résultats sous la forme d'une chaîne ou d'un tableau d'octets dans la base de données? Y a-t-il des avantages de toute façon? Ou est-ce une décision plus subjective?Meilleure façon de stocker les mots de passe hachés et les valeurs de sel dans la base de données - varchar ou binaire?
Répondre
VARCHAR devrait être suffisant. À mon avis, les données VARCHAR seront plus faciles à utiliser et à utiliser que les données binaires.
Les fournisseurs d'appartenance ASP.NET intégrés stockent également les mots de passe hachés en tant que champs VARCHAR.
Si vous utilisez VARCHAR, assurez-vous que les octets sont des caractères valides ou forcez les octets à ASCII avant d'enregistrer le hachage et le salt. Faire est plus sûr de la corruption de données, vous pouvez soit encoder les octets dans Base64 ou Hexadecimal avant de les stocker dans le champ VARCHAR.
Par exemple, si vous stockez la sortie byte[]
de MD5 ou SHA1 certaines des valeurs d'octets peuvent être supprimées ou remplacées lorsque le byte[]
est converti en texte est qu'ils ne sont pas valides UTF-8/Unicode. Cela ne devrait pas être un problème si vous utilisez ASCII, mais il pourrait toujours causer une corruption de données.
Si vous ne voulez pas traiter avec Hex, vous pouvez utiliser cette méthode base64 Convert.ToBase64String intégrée au framework.
Si vous utilisez VARBINARY et n'essayez pas d'utiliser les méthodes d'encodage de texte, ce problème ne devrait pas exister, mais pourrait rendre la comparaison des hachages plus difficile.
... Notez que si vous utilisez NVARCHAR
cette corruption de données peut se produire encore ...
static void Main(string[] args)
{
var salt = "MySalt";
var password = "MyPassword";
var saltedKey = CalculateHash(salt, password);
Console.WriteLine(saltedKey);
// MySalt$teGOpFi57nENIRifSW3m1RQndiU=
var checkHash = CheckHash(saltedKey, password);
Console.WriteLine(checkHash);
// True
}
private static string CalculateHash(string saltOrSaltedKey, string password)
{
var salt =
saltOrSaltedKey.Contains('$')
? saltOrSaltedKey.Substring(0, saltOrSaltedKey.IndexOf('$') + 1)
: saltOrSaltedKey + '$';
var newKey = Encoding.UTF8.GetBytes(salt + password);
var sha1 = SHA1.Create();
sha1.Initialize();
var result = sha1.ComputeHash(newKey);
// if you replace this base64 version with one of the encoding
// classes this will become corrupt due to nulls and other
// control character values in the byte[]
var outval = salt + Convert.ToBase64String(result);
return outval;
}
private static bool CheckHash(string saltedKey, string password)
{
var outval = CalculateHash(saltedKey, password);
return outval == saltedKey;
}
la plupart des bibliothèques md5/sha1 retour hashes base64 encodée auquel cas varchar suffirait
I Je n'ai jamais vu quelqu'un jamais utiliser autre chose qu'une chaîne varchar standard. – Layke