Как мне генерировать набор случайных строк в программе на C #, чтобы они не были тривиально предсказаны? - PullRequest
4 голосов
/ 22 июля 2010

Я столкнулся со следующей проблемой: сгенерировать N уникальных буквенно-цифровых строк из ограниченного алфавита.Вот мое решение в C #:

string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random generator = new Random();
const int ToGenerate = 10000;
const int CharactersCount = 4;
ArrayList generatedStrings = new ArrayList();
while( generatedStrings.Count < ToGenerate ) {
   string newString = "Prefix";
   for( int i = 0; i < CharactersCount; i++ ) {
      int index = generator.Next( Alphabet.Length );
      char character = Alphabet[index];
      newString += character;
   }
   if( !generatedStrings.Contains( newString ) ) {
      generatedStrings.Add( newString );
   }                
}
for( int i = 0; i < generatedStrings.Count; i++ ) {
    System.Console.Out.WriteLine( generatedStrings[i] );
}

, оно генерирует строки по 10 КБ, начинающиеся с «Префикса» и в противном случае состоящие из заглавных букв и цифр.Вывод выглядит хорошо.

Теперь я вижу следующую проблему.Созданные строки предназначены для сценария, в котором они вряд ли могут быть предсказаны кем-либо.В моей программе семя зависит от времени.Когда кто-то знает начальное значение, он может запустить тот же код и получить точно такие же строки.Если он знает какие-либо две строки, он может легко выяснить мой алгоритм (поскольку он действительно наивен) и попытаться перебором начального значения - просто перечислить все возможные начальные значения, пока он не увидит две известные строки в выводе.

Могут ли быть внесены некоторые простые изменения в мой код, чтобы сделать описанную атаку менее вероятной?

Ответы [ 2 ]

7 голосов
/ 22 июля 2010

Ну, как бы он узнал семя?Если он не знал, когда точное время вы запустили код, то это очень трудно сделать.Но если вам нужны более сильные, вы также можете создавать криптографически сильные случайные числа с помощью System.Security.Cryptography.RandomNumberGenerator.Create - что-то вроде:

        var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
        byte[] buffer = new byte[4];
        char[] chars = new char[CharactersCount];
        for(int i = 0 ; i < chars.Length ; i++)
        {
            rng.GetBytes(buffer);
            int nxt = BitConverter.ToInt32(buffer, 0);
            int index = nxt % Alphabet.Length;
            if(index < 0) index += Alphabet.Length;
            chars[i] = Alphabet[index];
        }
        string s = new string(chars);
5 голосов
/ 22 июля 2010

Ну, это зависит от того, что вы считаете "простым".

Вы можете «решить» вашу проблему, используя «истинный» источник случайных чисел. Вы можете попробовать бесплатные (random.org, fourmilab hotbits и т. Д.) Или купить одну , в зависимости от типа выполняемой операции.

В качестве альтернативы (и, возможно, лучше) не генерировать заранее, а генерировать по требованию. Но это может быть значительным изменением вашего бизнес-процесса / модели.

...