How can I generate random alphanumeric strings?

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

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

30条回答
  •  心在旅途
    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 generator)
            {
                Dictionary counts = new Dictionary();
                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")}%");
                }
            }
        }
    }
    

提交回复
热议问题