我如何在c#中生成一个随机的8个字符的字母数字字符串?


当前回答

这是我从Dot Net Perls的Sam Allen那里偷来的一个例子

如果你只需要8个字符,那么在系统中使用Path.GetRandomFileName()。IO命名空间。Sam说使用“Path.”这里的GetRandomFileName方法有时更优越,因为它使用RNGCryptoServiceProvider来获得更好的随机性。然而,它被限制为11个随机字符。”

GetRandomFileName总是返回一个12个字符的字符串,第9个字符是句点。所以你需要去掉句点(因为这不是随机的),然后从字符串中取出8个字符。实际上,你可以只取前8个字符而不用考虑句点。

public string Get8CharacterRandomString()
{
    string path = Path.GetRandomFileName();
    path = path.Replace(".", ""); // Remove period.
    return path.Substring(0, 8);  // Return 8 character string
}

PS:谢谢,Sam

其他回答

Eric J.写的代码很潦草(很明显这是6年前写的……他今天可能不会写那个代码),甚至还有一些问题。

与目前提出的一些替代方案不同,这个方案在密码学上是合理的。

不真实的…在密码中有一个偏差(正如在注释中所写的那样),bcdefgh比其他的更有可能(a不是,因为通过GetNonZeroBytes,它不会生成值为0的字节,因此a的偏差由它平衡),所以它在密码学上并不可靠。

这应该可以纠正所有的问题。

public static string GetUniqueKey(int size = 6, string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
{
    using (var crypto = new RNGCryptoServiceProvider())
    {
        var data = new byte[size];

        // If chars.Length isn't a power of 2 then there is a bias if
        // we simply use the modulus operator. The first characters of
        // chars will be more probable than the last ones.

        // buffer used if we encounter an unusable random byte. We will
        // regenerate it in this buffer
        byte[] smallBuffer = null;

        // Maximum random number that can be used without introducing a
        // bias
        int maxRandom = byte.MaxValue - ((byte.MaxValue + 1) % chars.Length);

        crypto.GetBytes(data);

        var result = new char[size];

        for (int i = 0; i < size; i++)
        {
            byte v = data[i];

            while (v > maxRandom)
            {
                if (smallBuffer == null)
                {
                    smallBuffer = new byte[1];
                }

                crypto.GetBytes(smallBuffer);
                v = smallBuffer[0];
            }

            result[i] = chars[v % chars.Length];
        }

        return new string(result);
    }
}

我们也使用自定义字符串随机,但我们实现的是字符串的帮助器,所以它提供了一些灵活性…

public static string Random(this string chars, int length = 8)
{
    var randomString = new StringBuilder();
    var random = new Random();

    for (int i = 0; i < length; i++)
        randomString.Append(chars[random.Next(chars.Length)]);

    return randomString.ToString();
}

使用

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Random();

or

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".Random(16);

我不知道这在密码学上听起来如何,但它比迄今为止(在我看来)更复杂的解决方案更具可读性和简练性,而且它应该比系统更“随机”。Random-based解决方案。

return alphabet
    .OrderBy(c => Guid.NewGuid())
    .Take(strLength)
    .Aggregate(
        new StringBuilder(),
        (builder, c) => builder.Append(c))
    .ToString();

我不知道我认为这个版本还是下一个版本“更漂亮”,但它们给出了完全相同的结果:

return new string(alphabet
    .OrderBy(o => Guid.NewGuid())
    .Take(strLength)
    .ToArray());

当然,它并没有针对速度进行优化,所以如果每秒生成数百万个随机字符串是关键任务,请尝试另一个!

注意:此解决方案不允许字母中符号的重复,并且字母必须等于或大于输出字符串的大小,使得这种方法在某些情况下不太可取,这完全取决于您的用例。

这里有一个机制来生成一个随机的字母-数字字符串(我用它来生成密码和测试数据),而不定义字母和数字,

CleanupBase64将删除字符串中必要的部分,并继续递归地添加随机的字母-数字字母。

        public static string GenerateRandomString(int length)
        {
            var numArray = new byte[length];
            new RNGCryptoServiceProvider().GetBytes(numArray);
            return CleanUpBase64String(Convert.ToBase64String(numArray), length);
        }

        private static string CleanUpBase64String(string input, int maxLength)
        {
            input = input.Replace("-", "");
            input = input.Replace("=", "");
            input = input.Replace("/", "");
            input = input.Replace("+", "");
            input = input.Replace(" ", "");
            while (input.Length < maxLength)
                input = input + GenerateRandomString(maxLength);
            return input.Length <= maxLength ?
                input.ToUpper() : //In my case I want capital letters
                input.ToUpper().Substring(0, maxLength);
        }

一种简单且高度安全的方法可能是生成加密Aes密钥。

public static string GenerateRandomString()
{
    using Aes crypto = Aes.Create();
    crypto.GenerateKey();
    return Convert.ToBase64String(crypto.Key);
}