Cryptographically random unique strings

In this answer , the code below was sent to create unique random alphanumeric strings. Can someone clarify for me exactly how they are guaranteed to be unique in this code and how unique they are? If I repeat this method in different cases, do I still get unique strings?

Or did I just misunderstand the answer, and they do not generate unique keys at all, only random ones?

I already asked about this in a comment on this answer, but the user seems inactive.

    public static string GetUniqueKey()
    {
        int maxSize = 8;
        char[] chars = new char[62];
        string a;
        a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        chars = a.ToCharArray();
        int size = maxSize;
        byte[] data = new byte[1];
        RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
        crypto.GetNonZeroBytes(data);
        size = maxSize;
        data = new byte[size];
        crypto.GetNonZeroBytes(data);
        StringBuilder result = new StringBuilder(size);
        foreach (byte b in data)
        { result.Append(chars[b % (chars.Length - 1)]); }
        return result.ToString();
    }   
+4
source share
4 answers

, . , , , , (, GUID). 48 , , 128 GUID.

, , , . :

  • char, .
  • , .
  • GetNonZeroBytes GetBytes, , .
  • modulo (%) , , .
  • chars.Length - 1 chars.Length, , , 61 62 .

, , .

, , , :

public static string GetUniqueKey() {
  int size = 16;
  byte[] data = new byte[size];
  RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
  crypto.GetBytes(data);
  return BitConverter.ToString(data).Replace("-", String.Empty);
}
+6

. , . , , , , , . , , (, , , ).

, , , , 100% . .

+3

7 - . .

-, , RNGCryptoServiceProvider,

100.000 - 1.000.000 - 10.000.000

;

    public static Tuple<List<string>, List<string>> GenerateUniqueList(int count)
        {
            uniqueHashTable = new Hashtable();
            nonUniqueList = new List<string>();
            uniqueList = new List<string>();

            for (int i = 0; i < count; i++)
            {
                isUniqueGenerated = false;

                while (!isUniqueGenerated)
                {
                    uniqueStr = GetUniqueKey();
                    try
                    {
                        uniqueHashTable.Add(uniqueStr, "");
                        isUniqueGenerated = true;
                    }
                    catch (Exception ex)
                    {
                        nonUniqueList.Add(uniqueStr);
                        // Non-unique generated
                    }
                }
            }

            uniqueList = uniqueHashTable.Keys.Cast<string>().ToList();

            return new Tuple<List<string>, List<string>>(uniqueList, nonUniqueList);
        }

        public static string GetUniqueKey()
        {
            int size = 7;
            char[] chars = new char[62];
            string a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
            chars = a.ToCharArray();

            RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();

            byte[] data = new byte[size];
            crypto.GetNonZeroBytes(data);

            StringBuilder result = new StringBuilder(size);

            foreach (byte b in data)
                result.Append(chars[b % (chars.Length - 1)]);

            return Convert.ToString(result);
        }

;

    class Program
    {
        static string uniqueStr;
        static Stopwatch stopwatch;
        static bool isUniqueGenerated;
        static Hashtable uniqueHashTable;
        static List<string> uniqueList;
        static List<string> nonUniqueList;
        static Tuple<List<string>, List<string>> generatedTuple;

        static void Main(string[] args)
        {
            int i = 0, y = 0, count = 100000;

            while (i < 10 && y < 4)
            {
                stopwatch = new Stopwatch();

                stopwatch.Start();

                generatedTuple = GenerateUniqueList(count);

                stopwatch.Stop();

                Console.WriteLine("Time elapsed: {0} --- {1} Unique  --- {2} nonUnique",
                    stopwatch.Elapsed,
                    generatedTuple.Item1.Count().ToFormattedInt(),
                    generatedTuple.Item2.Count().ToFormattedInt());

                i++;
                if (i == 9)
                {
                    Console.WriteLine(string.Empty);
                    y++;
                    count *= 10;
                    i = 0;
                }
            }


            Console.ReadLine();
        }

        public static Tuple<List<string>, List<string>> GenerateUniqueList(int count)
        {
            uniqueHashTable = new Hashtable();
            nonUniqueList = new List<string>();
            uniqueList = new List<string>();

            for (int i = 0; i < count; i++)
            {
                isUniqueGenerated = false;

                while (!isUniqueGenerated)
                {
                    uniqueStr = GetUniqueKey();
                    try
                    {
                        uniqueHashTable.Add(uniqueStr, "");
                        isUniqueGenerated = true;
                    }
                    catch (Exception ex)
                    {
                        nonUniqueList.Add(uniqueStr);
                        // Non-unique generated
                    }
                }
            }

            uniqueList = uniqueHashTable.Keys.Cast<string>().ToList();

            return new Tuple<List<string>, List<string>>(uniqueList, nonUniqueList);
        }

        public static string GetUniqueKey()
        {
            int size = 7;
            char[] chars = new char[62];
            string a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
            chars = a.ToCharArray();

            RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();

            byte[] data = new byte[size];
            crypto.GetNonZeroBytes(data);

            StringBuilder result = new StringBuilder(size);

            foreach (byte b in data)
                result.Append(chars[b % (chars.Length - 1)]);

            return Convert.ToString(result);
        }
    }

    public static class IntExtensions
    {
        public static string ToFormattedInt(this int value)
        {
            return string.Format(CultureInfo.InvariantCulture, "{0:0,0}", value);
        }
    }
+1

Using strictly alphanumeric characters limits the pool you are drawing onto to 62. Using the full character set for printing (ASCII 32-126) increases your pool to 94, reducing the chance of collisions and eliminating the creation of a separate pool.

0
source

Source: https://habr.com/ru/post/1543070/


All Articles