4

そのため、最近、パスワード関連のメソッドの静的クラスを作成し、安全なソルトを生成するメソッドを作成する必要がありました。

最初にRNGCryptoServiceProvider、nバイトを実装して配列にファイルし、base64に変換して返しました。

問題は、出力の長さで、変換後はもちろんnよりも長くなることでした(これは理にかなっています)。

これを修正するために、関数を以下の方法に変更しました。base64文字列をトリミングすることで、セキュリティ上のリスクが発生するのではないかと考えていました。

/// <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;
}

C#また、副次的な質問として、私はざっと見て回っていましたが、実際の実装のハッシュ関数が実際に何であるかを見つけることができませんでしたRNGCryptoServiceProvider。誰もが手に負えないことを知っていますか?

4

3 に答える 3

3

なぜ塩の長さがあなたにとってとても重要なのですか?ソルトの唯一の本当の要件は、それがランダムで推測できないことであるため、実際のセキュリティへの影響はないと思います。

言い換えれば、それのために行きなさい。

編集:Linqを使用してそれを行う別の方法があります。

Random random = new Random();
int length = 25; // Whatever length you want
char[] keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890!£$%^&*()".ToCharArray(); // whatever chars you want
var salt = Enumerable
    .Range(1, length) // equivalent to the loop bit, for(i.. ) 
    .Select(k => keys[random.Next(0, keys.Length - 1)])  // generate a new random char 
    .Aggregate("", (e, c) => e + c); // join them together into a string
于 2012-08-22T08:31:21.450 に答える
2

ソルトを生成するその方法にはセキュリティ上のリスクはありません。

ソルトはそのレベルのセキュリティをまったく必要としません。レインボーテーブルを使用してハッシュ/暗号化を解読できないようにするためだけにあります。通常のRandomクラスでソルトを作成できます。

例:

/// <summary>
/// Generates a salt for use with the Hash method.
/// </summary>
/// <param name="length">The length of string to generate.</param>
/// <returns>A 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.");
    }

    // Where we'll put our generated salt.
    StringBuilder salt = new StringBuilder(length);

    // Fill our string with random characters.
    Random rnd = new Random();
    string chars = "0123456798ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    for (int i = 0; i < length; i++) {
      salt.Append(chars[rnd.Next(chars.Length)]);
    }

    // Return the salt.
    return salt.ToString();
}

注:関数が時間的に2回以上使用される場合は、単一のRandomオブジェクトを使用して関数に渡しRandomます。時間的に作成されたインスタンスは同じランダムシーケンスを与えるためです。

于 2012-08-22T08:31:26.533 に答える
1

楽しみのために、これははるかに高速な方法です(コードは見栄えがよくありませんが)。これを切り取って貼り付けてみてください。私のマシンでは、7.1秒と比較して約1.6秒で実行されました。いずれの場合も100万回の反復を行っていたので、実行時間はそれほど重要ではないと思います。

string msg = "";
int desiredLength = 93; // Length of salt required
Stopwatch watch = new Stopwatch();
watch.Start();
for (int k=0; k<1000000; k++)
{
    double guidsNeeded = Math.Ceiling(desiredLength / 36.0);
    string salt = "";
    for (int i=0; i<guidsNeeded; i++)
    {
       salt += Guid.NewGuid().ToString();
    }
    salt = salt.Substring(0,desiredLength);
}
msg += watch.ElapsedMilliseconds.ToString(); // 1654 ms

watch.Start();
for (int j=0; j<1000000; j++)
{
    GenerateSalt(93);
}
msg += "\r\n" + watch.ElapsedMilliseconds.ToString(); // 7096 ms

これは、Guffaのコードを使用していGenerateSaltます。

于 2012-08-22T09:20:11.740 に答える