So I recently created a static class for password related methods and had to make a method that generated a secure salt.
Initially I implemented RNGCryptoServiceProvider and filed n bytes into an array, which I converted to base64 and returned.
The issue was that with the output length, after conversion of course it was longer than n (which makes sense).
To fix this I changed the function to the method below, and I was just wondering if by trimming the base64 string any security risks are raised?
/// <summary>
/// Generates a salt for use with the Hash method.
/// </summary>
/// <param name="length">The length of string to generate.</param>
/// <returns>A cryptographically secure random salt.</returns>
public static string GenerateSalt(int length)
{
// Check the length isn't too short.
if (length < MIN_LENGTH)
{
throw new ArgumentOutOfRangeException("length", "Please increase the salt length to meet the minimum acceptable value of " + MIN_LENGTH + " characters.");
}
// Calculate the number of bytes required.
// https://en.wikipedia.org/wiki/Base64#Padding
// http://stackoverflow.com/questions/17944/how-to-round-up-the-result-of-integer-division
int bytelen = ((3 * length) + 4 - 1) / 4;
// Create our empty salt array.
byte[] bytes = new byte[bytelen];
// Where we'll put our generated salt.
string salt;
// Generate a random secure salt.
using (RNGCryptoServiceProvider randcrypto = new RNGCryptoServiceProvider())
{
// Fill our array with random bytes.
randcrypto.GetBytes(bytes);
// Get a base64 string from the random byte array.
salt = GetBase64(bytes);
}
// Trim the end off only if we need to.
if (salt.Length > length)
{
// Substring is the fastest method to use.
salt = salt.Substring(0, length);
}
// Return the salt.
return salt;
}
Also as a side question, I was having a quick look around and couldn’t actually find what the hash function of the C# implementation of RNGCryptoServiceProvider actually is. Anyone know offhand?
There is no security risk with that way of generating the salt.
The salt doesn’t need that level of security at all, it’s just there so that rainbow tables can’t be used to crack the hash/encryption. The regular
Randomclass would be enough to create a salt.Example:
Note: If the function would be used more than once close in time, you would use a single
Randomobject and pass into the function, asRandominstances created too close in time will give the same random sequence.