How can I generate random alphanumeric strings?

后端 未结 30 2811
予麋鹿
予麋鹿 2020-11-22 03:17

How can I generate a random 8 character alphanumeric string in C#?

相关标签:
30条回答
  • 2020-11-22 04:05

    The code written by Eric J. is quite sloppy (it is quite clear that it is from 6 years ago... he probably wouldn't write that code today), and there are even some problems.

    Unlike some of the alternatives presented, this one is cryptographically sound.

    Untrue... There is a bias in the password (as written in a comment), bcdefgh are a little more probable than the others (the a isn't because by the GetNonZeroBytes it isn't generating bytes with a value of zero, so the bias for the a is balanced by it), so it isn't really cryptographically sound.

    This should correct all the problems.

    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);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 04:05

    There is one of the awasome nuget packages that make this so simple.

    var myObject = new Faker<MyObject>()
    .RuleFor(p => p.MyAlphaNumericProperty, f => f.Random.AlphaNumeric(/*lenght*/ 7))
    .Generate();
    

    One of the good example is here.

    0 讨论(0)
  • 2020-11-22 04:06

    UPDATED based on comments. The original implementation generated a-h ~1.95% of the time and the remaining characters ~1.56% of the time. The update generates all characters ~1.61% of the time.

    FRAMEWORK SUPPORT - .NET Core 3 (and future platforms that support .NET Standard 2.1 or above) provides a cryptographically sound method RandomNumberGenerator.GetInt32() to generate a random integer within a desired range.

    Unlike some of the alternatives presented, this one is cryptographically sound.

    using System;
    using System.Security.Cryptography;
    using System.Text;
    
    namespace UniqueKey
    {
        public class KeyGenerator
        {
            internal static readonly char[] chars =
                "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray(); 
    
            public static string GetUniqueKey(int size)
            {            
                byte[] data = new byte[4*size];
                using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
                {
                    crypto.GetBytes(data);
                }
                StringBuilder result = new StringBuilder(size);
                for (int i = 0; i < size; i++)
                {
                    var rnd = BitConverter.ToUInt32(data, i * 4);
                    var idx = rnd % chars.Length;
    
                    result.Append(chars[idx]);
                }
    
                return result.ToString();
            }
    
            public static string GetUniqueKeyOriginal_BIASED(int size)
            {
                char[] chars =
                    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
                byte[] data = new byte[size];
                using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
                {
                    crypto.GetBytes(data);
                }
                StringBuilder result = new StringBuilder(size);
                foreach (byte b in data)
                {
                    result.Append(chars[b % (chars.Length)]);
                }
                return result.ToString();
            }
        }
    }
    

    Based on a discussion of alternatives here and updated/modified based on the comments below.

    Here's a small test harness that demonstrates the distribution of characters in the old and updated output. For a deep discussion of the analysis of randomness, check out random.org.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using UniqueKey;
    
    namespace CryptoRNGDemo
    {
        class Program
        {
    
            const int REPETITIONS = 1000000;
            const int KEY_SIZE = 32;
    
            static void Main(string[] args)
            {
                Console.WriteLine("Original BIASED implementation");
                PerformTest(REPETITIONS, KEY_SIZE, KeyGenerator.GetUniqueKeyOriginal_BIASED);
    
                Console.WriteLine("Updated implementation");
                PerformTest(REPETITIONS, KEY_SIZE, KeyGenerator.GetUniqueKey);
                Console.ReadKey();
            }
    
            static void PerformTest(int repetitions, int keySize, Func<int, string> generator)
            {
                Dictionary<char, int> counts = new Dictionary<char, int>();
                foreach (var ch in UniqueKey.KeyGenerator.chars) counts.Add(ch, 0);
    
                for (int i = 0; i < REPETITIONS; i++)
                {
                    var key = generator(KEY_SIZE); 
                    foreach (var ch in key) counts[ch]++;
                }
    
                int totalChars = counts.Values.Sum();
                foreach (var ch in UniqueKey.KeyGenerator.chars)
                {
                    Console.WriteLine($"{ch}: {(100.0 * counts[ch] / totalChars).ToString("#.000")}%");
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 04:09
     public static string RandomString(int length)
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            var random = new Random();
            return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
        }
    
    0 讨论(0)
  • 2020-11-22 04:09

    Horrible, I know, but I just couldn't help myself:

    
    namespace ConsoleApplication2
    {
        using System;
        using System.Text.RegularExpressions;
    
        class Program
        {
            static void Main(string[] args)
            {
                Random adomRng = new Random();
                string rndString = string.Empty;
                char c;
    
                for (int i = 0; i < 8; i++)
                {
                    while (!Regex.IsMatch((c=Convert.ToChar(adomRng.Next(48,128))).ToString(), "[A-Za-z0-9]"));
                    rndString += c;
                }
    
                Console.WriteLine(rndString + Environment.NewLine);
            }
        }
    }
    
    
    0 讨论(0)
  • 2020-11-22 04:10

    I know this one is not the best way. But you can try this.

    string str = Path.GetRandomFileName(); //This method returns a random file name of 11 characters
    str = str.Replace(".","");
    Console.WriteLine("Random string: " + str);
    
    0 讨论(0)
提交回复
热议问题