暗号的に強力なランダム文字の文字列を返すこのメソッドがあります。
最初にGetBytes()
、バイト配列に 0 から 255 までの値を設定します。
{byte value} % {length of character set}
次に、文字セットから文字番号を選択して、戻り文字列を作成します。
問題は、ほとんどの文字セットの長さが 256 で割り切れないため、結果が一部の文字に偏ってしまうことです。たとえば、文字セットが 8、16、または 32 文字の長さの場合、残りは 0 で問題ありません。
GetBytes()
だから私は考えていました-文字セットの長さが最大値で均等に割り切れるように、返される値を制限できますか? たとえば、文字セットの長さが 62 の場合、最大値は 247 にする必要があります。
もちろん、一度に 1 バイトだけ取得することもできます。値が高すぎる場合は、別のバイトを取得することもできます。しかし、それはあまりエレガントではありません。
/// <summary>
/// Returns a string of cryptographically sound random characters
/// </summary>
/// <param name="type">Accepted parameter variables are HEX (0-F), hex (0-f),
/// DEC/dec/NUM/num (0-9), ALPHA (A-Z), alpha (a-z), ALPHANUM (A-Z and 0-9),
/// alphanum (a-z and 0-9) and FULL/full (A-Z, a-z and 0-9)</param>
/// <param name="length">The length of the output string</param>
/// <returns>String of cryptographically sound random characters</returns>
public static string Serial(string type, int length)
{
if (length < 1) return "";
string chars;
switch (type)
{
case "HEX":
chars = "0123456789ABCDEF"; // 16
break;
case "hex":
chars = "0123456789abcdef"; // 16
break;
case "DEC":
case "dec":
case "NUM":
case "num":
chars = "0123456789"; // 10
break;
case "ALPHA":
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 26
break;
case "alpha":
chars = "abcdefghijklmnopqrstuvwxyz"; // 26
break;
case "ALPHANUM":
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // 36
break;
case "alphanum":
chars = "abcdefghijklmnopqrstuvwxyz0123456789"; // 36
break;
case "FULL":
case "full":
default:
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // 62
break;
}
byte[] data = new byte[length];
using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
{
crypto.GetBytes(data);
}
StringBuilder result = new StringBuilder(length);
foreach (byte b in data)
{
result.Append(chars[b % chars.Length]);
}
return result.ToString();
}