我有这个方法,它返回一串加密强的随机字符。
首先,GetBytes()
用 0 到 255 的值填充一个字节数组。
{byte value} % {length of character set}
接下来,通过从字符集中选择字符编号来构建返回字符串。
问题是我的大部分字符集的长度都不能被256整除,所以结果会偏向一些字符。例如,如果字符集长度为 8、16 或 32 个字符,则余数为 0,没有问题。
所以我在想 - 我可以限制返回的值GetBytes()
,使字符集的长度可以被最大值整除吗?例如,如果字符集的长度为 62,则最大值应为 247。
我当然可以一次只得到一个字节,如果值太高,我可以再得到一个。但这不是很优雅。
/// <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();
}