I've had a go at creating a small class in C# that can generated salted hashes from text. I would like to know how this could be improved (in terms of code style) and whether or not this code is secure enough that it could be used in a professional environment (it won't be).
Hasher.cs
using System.Security.Cryptography;
namespace HashAndSaltTest
{
public static class Hasher
{
private static readonly int MaxSaltLength = 32;
public static byte[] GenerateSaltedHash(byte[] plainText)
{
HashAlgorithm algorithm = new SHA256Managed();
byte[] salt = GenerateSalt();
byte[] saltedText = new byte[plainText.Length + salt.Length];
for (int i = 0; i < plainText.Length; i++)
saltedText[i] = plainText[i];
for (int i = 0; i < salt.Length; i++)
saltedText[plainText.Length + i] = salt[i];
return algorithm.ComputeHash(saltedText);
}
private static byte[] GenerateSalt()
{
byte[] salt = new byte[MaxSaltLength];
using (RandomNumberGenerator random = new RNGCryptoServiceProvider())
random.GetNonZeroBytes(salt);
return salt;
}
}
}
-
\$\begingroup\$ What exactly do you want to use this code for? How do you intend to verify the hashed value? \$\endgroup\$Roland Illig– Roland Illig2018年05月13日 16:03:25 +00:00Commented May 13, 2018 at 16:03
-
\$\begingroup\$ If "plainttext" is ever going to be a password, this is not secure. SHA256 is not designed to handle passwords (use PBKDF2 or bCrypt instead). If you're not using it with passwords, I don't get the purpose of the salt. A bit more context of what kind of input is expected and what'll you use the hashes for is relevant when speaking about security. \$\endgroup\$Alejandro– Alejandro2018年05月14日 01:02:49 +00:00Commented May 14, 2018 at 1:02
1 Answer 1
Because
HashAlgorithm
implementsIDisposable
you should enclose the usage of it in anusing
block as well.Omitting braces
{}
although they might be optional can lead to hidden and therfor hard to find bugs. I would like to encourage you to always use braces.Instead of using a
for
loop to copyplainText
tosaltedText
andsalt
tosaltedText
you may take advantage of theArray.CopyTo()
method.Public
methods should validate passed parameters.Because you don't return the
salt
you can only generate a hash but you can't verify the hash.
Applying the mentioned points can lead to
public static byte[] GenerateSaltedHash(byte[] plainText)
{
if (plainText == null) { throw new ArgumentNullException("plainText"); }
if (plainText.Length == 0) { throw new ArgumentException("Length may not be zero", "plainText"); }
using (HashAlgorithm algorithm = new SHA256Managed())
{
byte[] salt = GenerateSalt();
byte[] saltedText = new byte[plainText.Length + salt.Length];
plainText.CopyTo(saltedText, 0);
salt.CopyTo(saltedText, plainText.Length);
return algorithm.ComputeHash(saltedText);
}
}
private static byte[] GenerateSalt()
{
using (RandomNumberGenerator random = new RNGCryptoServiceProvider())
{
byte[] salt = new byte[MaxSaltLength];
random.GetNonZeroBytes(salt);
return salt;
}
}
-
\$\begingroup\$ Thanks for the feedback. Just wondering, from a security standpoint, how safe is this method of generating salted hashes? \$\endgroup\$user162687– user1626872018年05月13日 20:31:28 +00:00Commented May 13, 2018 at 20:31
-
\$\begingroup\$ IMO its safe enough at least if the
plainText
isn't containing security relevant information. IfplainText
contains security relevant information you should override it inside this method. \$\endgroup\$Heslacher– Heslacher2018年05月13日 20:35:36 +00:00Commented May 13, 2018 at 20:35 -
\$\begingroup\$ @Heslacher, could you elaborate on
you should override it inside this method
a little, and/or show an example? I'm assumingsecurity relevant information
would be passwords and such. \$\endgroup\$Sinjai– Sinjai2018年05月20日 21:11:20 +00:00Commented May 20, 2018 at 21:11 -
\$\begingroup\$ I meant overwriting the passed array. \$\endgroup\$Heslacher– Heslacher2018年05月22日 05:51:16 +00:00Commented May 22, 2018 at 5:51